| OLD | NEW |
| (Empty) |
| 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) */ | |
| OLD | NEW |