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