1 /* 2 ** 2007 August 14 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** This file contains the C functions that implement mutexes. 13 ** 14 ** The implementation in this file does not provide any mutual 15 ** exclusion and is thus suitable for use only in applications 16 ** that use SQLite in a single thread. But this implementation 17 ** does do a lot of error checking on mutexes to make sure they 18 ** are called correctly and at appropriate times. Hence, this 19 ** implementation is suitable for testing. 20 ** debugging purposes 21 ** 22 ** $Id: mutex.c,v 1.17 2008/03/26 18:34:43 danielk1977 Exp $ 23 */ 24 #include "sqliteInt.h" 25 26 #ifdef SQLITE_MUTEX_NOOP_DEBUG 27 /* 28 ** In this implementation, mutexes do not provide any mutual exclusion. 29 ** But the error checking is provided. This implementation is useful 30 ** for test purposes. 31 */ 32 33 /* 34 ** The mutex object 35 */ 36 struct sqlite3_mutex { 37 int id; /* The mutex type */ 38 int cnt; /* Number of entries without a matching leave */ 39 }; 40 41 /* 42 ** The sqlite3_mutex_alloc() routine allocates a new 43 ** mutex and returns a pointer to it. If it returns NULL 44 ** that means that a mutex could not be allocated. 45 */ 46 sqlite3_mutex *sqlite3_mutex_alloc(int id){ 47 static sqlite3_mutex aStatic[6]; 48 sqlite3_mutex *pNew = 0; 49 switch( id ){ 50 case SQLITE_MUTEX_FAST: 51 case SQLITE_MUTEX_RECURSIVE: { 52 pNew = sqlite3_malloc(sizeof(*pNew)); 53 if( pNew ){ 54 pNew->id = id; 55 pNew->cnt = 0; 56 } 57 break; 58 } 59 default: { 60 assert( id-2 >= 0 ); 61 assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); 62 pNew = &aStatic[id-2]; 63 pNew->id = id; 64 break; 65 } 66 } 67 return pNew; 68 } 69 70 /* 71 ** This routine deallocates a previously allocated mutex. 72 */ 73 void sqlite3_mutex_free(sqlite3_mutex *p){ 74 assert( p ); 75 assert( p->cnt==0 ); 76 assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); 77 sqlite3_free(p); 78 } 79 80 /* 81 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt 82 ** to enter a mutex. If another thread is already within the mutex, 83 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return 84 ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK 85 ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can 86 ** be entered multiple times by the same thread. In such cases the, 87 ** mutex must be exited an equal number of times before another thread 88 ** can enter. If the same thread tries to enter any other kind of mutex 89 ** more than once, the behavior is undefined. 90 */ 91 void sqlite3_mutex_enter(sqlite3_mutex *p){ 92 assert( p ); 93 assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); 94 p->cnt++; 95 } 96 int sqlite3_mutex_try(sqlite3_mutex *p){ 97 assert( p ); 98 assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); 99 p->cnt++; 100 return SQLITE_OK; 101 } 102 103 /* 104 ** The sqlite3_mutex_leave() routine exits a mutex that was 105 ** previously entered by the same thread. The behavior 106 ** is undefined if the mutex is not currently entered or 107 ** is not currently allocated. SQLite will never do either. 108 */ 109 void sqlite3_mutex_leave(sqlite3_mutex *p){ 110 assert( p ); 111 assert( sqlite3_mutex_held(p) ); 112 p->cnt--; 113 assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); 114 } 115 116 /* 117 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are 118 ** intended for use inside assert() statements. 119 */ 120 int sqlite3_mutex_held(sqlite3_mutex *p){ 121 return p==0 || p->cnt>0; 122 } 123 int sqlite3_mutex_notheld(sqlite3_mutex *p){ 124 return p==0 || p->cnt==0; 125 } 126 #endif /* SQLITE_MUTEX_NOOP_DEBUG */ 127