1 /* 2 ** 2008 October 07 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 ** This 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. The routines defined 17 ** here are place-holders. Applications can substitute working 18 ** mutex routines at start-time using the 19 ** 20 ** sqlite3_config(SQLITE_CONFIG_MUTEX,...) 21 ** 22 ** interface. 23 ** 24 ** If compiled with SQLITE_DEBUG, then additional logic is inserted 25 ** that does error checking on mutexes to make sure they are being 26 ** called correctly. 27 */ 28 #include "sqliteInt.h" 29 30 #ifndef SQLITE_MUTEX_OMIT 31 32 #ifndef SQLITE_DEBUG 33 /* 34 ** Stub routines for all mutex methods. 35 ** 36 ** This routines provide no mutual exclusion or error checking. 37 */ 38 static int noopMutexInit(void){ return SQLITE_OK; } 39 static int noopMutexEnd(void){ return SQLITE_OK; } 40 static sqlite3_mutex *noopMutexAlloc(int id){ 41 UNUSED_PARAMETER(id); 42 return (sqlite3_mutex*)8; 43 } 44 static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } 45 static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } 46 static int noopMutexTry(sqlite3_mutex *p){ 47 UNUSED_PARAMETER(p); 48 return SQLITE_OK; 49 } 50 static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } 51 52 sqlite3_mutex_methods const *sqlite3NoopMutex(void){ 53 static const sqlite3_mutex_methods sMutex = { 54 noopMutexInit, 55 noopMutexEnd, 56 noopMutexAlloc, 57 noopMutexFree, 58 noopMutexEnter, 59 noopMutexTry, 60 noopMutexLeave, 61 62 0, 63 0, 64 }; 65 66 return &sMutex; 67 } 68 #endif /* !SQLITE_DEBUG */ 69 70 #ifdef SQLITE_DEBUG 71 /* 72 ** In this implementation, error checking is provided for testing 73 ** and debugging purposes. The mutexes still do not provide any 74 ** mutual exclusion. 75 */ 76 77 /* 78 ** The mutex object 79 */ 80 typedef struct sqlite3_debug_mutex { 81 int id; /* The mutex type */ 82 int cnt; /* Number of entries without a matching leave */ 83 } sqlite3_debug_mutex; 84 85 /* 86 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are 87 ** intended for use inside assert() statements. 88 */ 89 static int debugMutexHeld(sqlite3_mutex *pX){ 90 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; 91 return p==0 || p->cnt>0; 92 } 93 static int debugMutexNotheld(sqlite3_mutex *pX){ 94 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; 95 return p==0 || p->cnt==0; 96 } 97 98 /* 99 ** Initialize and deinitialize the mutex subsystem. 100 */ 101 static int debugMutexInit(void){ return SQLITE_OK; } 102 static int debugMutexEnd(void){ return SQLITE_OK; } 103 104 /* 105 ** The sqlite3_mutex_alloc() routine allocates a new 106 ** mutex and returns a pointer to it. If it returns NULL 107 ** that means that a mutex could not be allocated. 108 */ 109 static sqlite3_mutex *debugMutexAlloc(int id){ 110 static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; 111 sqlite3_debug_mutex *pNew = 0; 112 switch( id ){ 113 case SQLITE_MUTEX_FAST: 114 case SQLITE_MUTEX_RECURSIVE: { 115 pNew = sqlite3Malloc(sizeof(*pNew)); 116 if( pNew ){ 117 pNew->id = id; 118 pNew->cnt = 0; 119 } 120 break; 121 } 122 default: { 123 #ifdef SQLITE_ENABLE_API_ARMOR 124 if( id-2<0 || id-2>=ArraySize(aStatic) ){ 125 (void)SQLITE_MISUSE_BKPT; 126 return 0; 127 } 128 #endif 129 pNew = &aStatic[id-2]; 130 pNew->id = id; 131 break; 132 } 133 } 134 return (sqlite3_mutex*)pNew; 135 } 136 137 /* 138 ** This routine deallocates a previously allocated mutex. 139 */ 140 static void debugMutexFree(sqlite3_mutex *pX){ 141 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; 142 assert( p->cnt==0 ); 143 if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ 144 sqlite3_free(p); 145 }else{ 146 #ifdef SQLITE_ENABLE_API_ARMOR 147 (void)SQLITE_MISUSE_BKPT; 148 #endif 149 } 150 } 151 152 /* 153 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt 154 ** to enter a mutex. If another thread is already within the mutex, 155 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return 156 ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK 157 ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can 158 ** be entered multiple times by the same thread. In such cases the, 159 ** mutex must be exited an equal number of times before another thread 160 ** can enter. If the same thread tries to enter any other kind of mutex 161 ** more than once, the behavior is undefined. 162 */ 163 static void debugMutexEnter(sqlite3_mutex *pX){ 164 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; 165 assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); 166 p->cnt++; 167 } 168 static int debugMutexTry(sqlite3_mutex *pX){ 169 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; 170 assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); 171 p->cnt++; 172 return SQLITE_OK; 173 } 174 175 /* 176 ** The sqlite3_mutex_leave() routine exits a mutex that was 177 ** previously entered by the same thread. The behavior 178 ** is undefined if the mutex is not currently entered or 179 ** is not currently allocated. SQLite will never do either. 180 */ 181 static void debugMutexLeave(sqlite3_mutex *pX){ 182 sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; 183 assert( debugMutexHeld(pX) ); 184 p->cnt--; 185 assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); 186 } 187 188 sqlite3_mutex_methods const *sqlite3NoopMutex(void){ 189 static const sqlite3_mutex_methods sMutex = { 190 debugMutexInit, 191 debugMutexEnd, 192 debugMutexAlloc, 193 debugMutexFree, 194 debugMutexEnter, 195 debugMutexTry, 196 debugMutexLeave, 197 198 debugMutexHeld, 199 debugMutexNotheld 200 }; 201 202 return &sMutex; 203 } 204 #endif /* SQLITE_DEBUG */ 205 206 /* 207 ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation 208 ** is used regardless of the run-time threadsafety setting. 209 */ 210 #ifdef SQLITE_MUTEX_NOOP 211 sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ 212 return sqlite3NoopMutex(); 213 } 214 #endif /* defined(SQLITE_MUTEX_NOOP) */ 215 #endif /* !defined(SQLITE_MUTEX_OMIT) */ 216