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 ** This file contains code that is common across all mutex implementations. 15 */ 16 #include "sqliteInt.h" 17 18 #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) 19 /* 20 ** For debugging purposes, record when the mutex subsystem is initialized 21 ** and uninitialized so that we can assert() if there is an attempt to 22 ** allocate a mutex while the system is uninitialized. 23 */ 24 static SQLITE_WSD int mutexIsInit = 0; 25 #endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */ 26 27 28 #ifndef SQLITE_MUTEX_OMIT 29 30 #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS 31 /* 32 ** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains 33 ** the implementation of a wrapper around the system default mutex 34 ** implementation (sqlite3DefaultMutex()). 35 ** 36 ** Most calls are passed directly through to the underlying default 37 ** mutex implementation. Except, if a mutex is configured by calling 38 ** sqlite3MutexWarnOnContention() on it, then if contention is ever 39 ** encountered within xMutexEnter() a warning is emitted via sqlite3_log(). 40 ** 41 ** This type of mutex is used as the database handle mutex when testing 42 ** apps that usually use SQLITE_CONFIG_MULTITHREAD mode. 43 */ 44 45 /* 46 ** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS 47 ** is defined. 48 */ 49 typedef struct CheckMutex CheckMutex; 50 struct CheckMutex { 51 int iType; 52 sqlite3_mutex *mutex; 53 }; 54 55 /* 56 ** Pointer to real mutex methods object used by the CheckMutex 57 ** implementation. Set by checkMutexInit(). 58 */ 59 static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods; 60 61 #ifdef SQLITE_DEBUG 62 static int checkMutexHeld(sqlite3_mutex *p){ 63 return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex); 64 } 65 static int checkMutexNotheld(sqlite3_mutex *p){ 66 return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex); 67 } 68 #endif 69 70 /* 71 ** Initialize and deinitialize the mutex subsystem. 72 */ 73 static int checkMutexInit(void){ 74 pGlobalMutexMethods = sqlite3DefaultMutex(); 75 return SQLITE_OK; 76 } 77 static int checkMutexEnd(void){ 78 pGlobalMutexMethods = 0; 79 return SQLITE_OK; 80 } 81 82 /* 83 ** Allocate a mutex. 84 */ 85 static sqlite3_mutex *checkMutexAlloc(int iType){ 86 static CheckMutex staticMutexes[] = { 87 {2, 0}, {3, 0}, {4, 0}, {5, 0}, 88 {6, 0}, {7, 0}, {8, 0}, {9, 0}, 89 {10, 0}, {11, 0}, {12, 0}, {13, 0} 90 }; 91 CheckMutex *p = 0; 92 93 assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 ); 94 if( iType<2 ){ 95 p = sqlite3MallocZero(sizeof(CheckMutex)); 96 if( p==0 ) return 0; 97 p->iType = iType; 98 }else{ 99 #ifdef SQLITE_ENABLE_API_ARMOR 100 if( iType-2>=ArraySize(staticMutexes) ){ 101 (void)SQLITE_MISUSE_BKPT; 102 return 0; 103 } 104 #endif 105 p = &staticMutexes[iType-2]; 106 } 107 108 if( p->mutex==0 ){ 109 p->mutex = pGlobalMutexMethods->xMutexAlloc(iType); 110 if( p->mutex==0 ){ 111 if( iType<2 ){ 112 sqlite3_free(p); 113 } 114 p = 0; 115 } 116 } 117 118 return (sqlite3_mutex*)p; 119 } 120 121 /* 122 ** Free a mutex. 123 */ 124 static void checkMutexFree(sqlite3_mutex *p){ 125 #if SQLITE_ENABLE_API_ARMOR 126 if( p->iType<2 ){ 127 #endif 128 { 129 CheckMutex *pCheck = (CheckMutex*)p; 130 pGlobalMutexMethods->xMutexFree(pCheck->mutex); 131 sqlite3_free(pCheck); 132 } 133 #ifdef SQLITE_ENABLE_API_ARMOR 134 else{ 135 (void)SQLITE_MISUSE_BKPT; 136 } 137 #endif 138 } 139 140 /* 141 ** Enter the mutex. 142 */ 143 static void checkMutexEnter(sqlite3_mutex *p){ 144 CheckMutex *pCheck = (CheckMutex*)p; 145 if( pCheck->iType<0 ){ 146 if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){ 147 return; 148 } 149 sqlite3_log(SQLITE_MISUSE, 150 "illegal multi-threaded access to database connection" 151 ); 152 } 153 pGlobalMutexMethods->xMutexEnter(pCheck->mutex); 154 } 155 156 /* 157 ** Enter the mutex (do not block). 158 */ 159 static int checkMutexTry(sqlite3_mutex *p){ 160 CheckMutex *pCheck = (CheckMutex*)p; 161 return pGlobalMutexMethods->xMutexTry(pCheck->mutex); 162 } 163 164 /* 165 ** Leave the mutex. 166 */ 167 static void checkMutexLeave(sqlite3_mutex *p){ 168 CheckMutex *pCheck = (CheckMutex*)p; 169 pGlobalMutexMethods->xMutexLeave(pCheck->mutex); 170 } 171 172 sqlite3_mutex_methods const *multiThreadedCheckMutex(void){ 173 static const sqlite3_mutex_methods sMutex = { 174 checkMutexInit, 175 checkMutexEnd, 176 checkMutexAlloc, 177 checkMutexFree, 178 checkMutexEnter, 179 checkMutexTry, 180 checkMutexLeave, 181 #ifdef SQLITE_DEBUG 182 checkMutexHeld, 183 checkMutexNotheld 184 #else 185 0, 186 0 187 #endif 188 }; 189 return &sMutex; 190 } 191 192 /* 193 ** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as 194 ** one on which there should be no contention. 195 */ 196 void sqlite3MutexWarnOnContention(sqlite3_mutex *p){ 197 if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){ 198 CheckMutex *pCheck = (CheckMutex*)p; 199 assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE ); 200 pCheck->iType = -1; 201 } 202 } 203 #endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */ 204 205 /* 206 ** Initialize the mutex system. 207 */ 208 int sqlite3MutexInit(void){ 209 int rc = SQLITE_OK; 210 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ 211 /* If the xMutexAlloc method has not been set, then the user did not 212 ** install a mutex implementation via sqlite3_config() prior to 213 ** sqlite3_initialize() being called. This block copies pointers to 214 ** the default implementation into the sqlite3GlobalConfig structure. 215 */ 216 sqlite3_mutex_methods const *pFrom; 217 sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; 218 219 if( sqlite3GlobalConfig.bCoreMutex ){ 220 #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS 221 pFrom = multiThreadedCheckMutex(); 222 #else 223 pFrom = sqlite3DefaultMutex(); 224 #endif 225 }else{ 226 pFrom = sqlite3NoopMutex(); 227 } 228 pTo->xMutexInit = pFrom->xMutexInit; 229 pTo->xMutexEnd = pFrom->xMutexEnd; 230 pTo->xMutexFree = pFrom->xMutexFree; 231 pTo->xMutexEnter = pFrom->xMutexEnter; 232 pTo->xMutexTry = pFrom->xMutexTry; 233 pTo->xMutexLeave = pFrom->xMutexLeave; 234 pTo->xMutexHeld = pFrom->xMutexHeld; 235 pTo->xMutexNotheld = pFrom->xMutexNotheld; 236 sqlite3MemoryBarrier(); 237 pTo->xMutexAlloc = pFrom->xMutexAlloc; 238 } 239 assert( sqlite3GlobalConfig.mutex.xMutexInit ); 240 rc = sqlite3GlobalConfig.mutex.xMutexInit(); 241 242 #ifdef SQLITE_DEBUG 243 GLOBAL(int, mutexIsInit) = 1; 244 #endif 245 246 return rc; 247 } 248 249 /* 250 ** Shutdown the mutex system. This call frees resources allocated by 251 ** sqlite3MutexInit(). 252 */ 253 int sqlite3MutexEnd(void){ 254 int rc = SQLITE_OK; 255 if( sqlite3GlobalConfig.mutex.xMutexEnd ){ 256 rc = sqlite3GlobalConfig.mutex.xMutexEnd(); 257 } 258 259 #ifdef SQLITE_DEBUG 260 GLOBAL(int, mutexIsInit) = 0; 261 #endif 262 263 return rc; 264 } 265 266 /* 267 ** Retrieve a pointer to a static mutex or allocate a new dynamic one. 268 */ 269 sqlite3_mutex *sqlite3_mutex_alloc(int id){ 270 #ifndef SQLITE_OMIT_AUTOINIT 271 if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0; 272 if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0; 273 #endif 274 assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); 275 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 276 } 277 278 sqlite3_mutex *sqlite3MutexAlloc(int id){ 279 if( !sqlite3GlobalConfig.bCoreMutex ){ 280 return 0; 281 } 282 assert( GLOBAL(int, mutexIsInit) ); 283 assert( sqlite3GlobalConfig.mutex.xMutexAlloc ); 284 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 285 } 286 287 /* 288 ** Free a dynamic mutex. 289 */ 290 void sqlite3_mutex_free(sqlite3_mutex *p){ 291 if( p ){ 292 assert( sqlite3GlobalConfig.mutex.xMutexFree ); 293 sqlite3GlobalConfig.mutex.xMutexFree(p); 294 } 295 } 296 297 /* 298 ** Obtain the mutex p. If some other thread already has the mutex, block 299 ** until it can be obtained. 300 */ 301 void sqlite3_mutex_enter(sqlite3_mutex *p){ 302 if( p ){ 303 assert( sqlite3GlobalConfig.mutex.xMutexEnter ); 304 sqlite3GlobalConfig.mutex.xMutexEnter(p); 305 } 306 } 307 308 /* 309 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another 310 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. 311 */ 312 int sqlite3_mutex_try(sqlite3_mutex *p){ 313 int rc = SQLITE_OK; 314 if( p ){ 315 assert( sqlite3GlobalConfig.mutex.xMutexTry ); 316 return sqlite3GlobalConfig.mutex.xMutexTry(p); 317 } 318 return rc; 319 } 320 321 /* 322 ** The sqlite3_mutex_leave() routine exits a mutex that was previously 323 ** entered by the same thread. The behavior is undefined if the mutex 324 ** is not currently entered. If a NULL pointer is passed as an argument 325 ** this function is a no-op. 326 */ 327 void sqlite3_mutex_leave(sqlite3_mutex *p){ 328 if( p ){ 329 assert( sqlite3GlobalConfig.mutex.xMutexLeave ); 330 sqlite3GlobalConfig.mutex.xMutexLeave(p); 331 } 332 } 333 334 #ifndef NDEBUG 335 /* 336 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are 337 ** intended for use inside assert() statements. 338 */ 339 int sqlite3_mutex_held(sqlite3_mutex *p){ 340 assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld ); 341 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); 342 } 343 int sqlite3_mutex_notheld(sqlite3_mutex *p){ 344 assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld ); 345 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); 346 } 347 #endif 348 349 #endif /* !defined(SQLITE_MUTEX_OMIT) */ 350 351