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 ** 17 ** $Id: mutex.c,v 1.29 2008/10/07 15:25:48 drh Exp $ 18 */ 19 #include "sqliteInt.h" 20 21 #ifndef SQLITE_MUTEX_OMIT 22 /* 23 ** Initialize the mutex system. 24 */ 25 int sqlite3MutexInit(void){ 26 int rc = SQLITE_OK; 27 if( sqlite3GlobalConfig.bCoreMutex ){ 28 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ 29 /* If the xMutexAlloc method has not been set, then the user did not 30 ** install a mutex implementation via sqlite3_config() prior to 31 ** sqlite3_initialize() being called. This block copies pointers to 32 ** the default implementation into the sqlite3GlobalConfig structure. 33 ** 34 ** The danger is that although sqlite3_config() is not a threadsafe 35 ** API, sqlite3_initialize() is, and so multiple threads may be 36 ** attempting to run this function simultaneously. To guard write 37 ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex 38 ** is obtained before modifying it. 39 */ 40 sqlite3_mutex_methods *p = sqlite3DefaultMutex(); 41 sqlite3_mutex *pMaster = 0; 42 43 rc = p->xMutexInit(); 44 if( rc==SQLITE_OK ){ 45 pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); 46 assert(pMaster); 47 p->xMutexEnter(pMaster); 48 assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0 49 || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc 50 ); 51 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){ 52 sqlite3GlobalConfig.mutex = *p; 53 } 54 p->xMutexLeave(pMaster); 55 } 56 }else{ 57 rc = sqlite3GlobalConfig.mutex.xMutexInit(); 58 } 59 } 60 61 return rc; 62 } 63 64 /* 65 ** Shutdown the mutex system. This call frees resources allocated by 66 ** sqlite3MutexInit(). 67 */ 68 int sqlite3MutexEnd(void){ 69 int rc = SQLITE_OK; 70 rc = sqlite3GlobalConfig.mutex.xMutexEnd(); 71 return rc; 72 } 73 74 /* 75 ** Retrieve a pointer to a static mutex or allocate a new dynamic one. 76 */ 77 sqlite3_mutex *sqlite3_mutex_alloc(int id){ 78 #ifndef SQLITE_OMIT_AUTOINIT 79 if( sqlite3_initialize() ) return 0; 80 #endif 81 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 82 } 83 84 sqlite3_mutex *sqlite3MutexAlloc(int id){ 85 if( !sqlite3GlobalConfig.bCoreMutex ){ 86 return 0; 87 } 88 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 89 } 90 91 /* 92 ** Free a dynamic mutex. 93 */ 94 void sqlite3_mutex_free(sqlite3_mutex *p){ 95 if( p ){ 96 sqlite3GlobalConfig.mutex.xMutexFree(p); 97 } 98 } 99 100 /* 101 ** Obtain the mutex p. If some other thread already has the mutex, block 102 ** until it can be obtained. 103 */ 104 void sqlite3_mutex_enter(sqlite3_mutex *p){ 105 if( p ){ 106 sqlite3GlobalConfig.mutex.xMutexEnter(p); 107 } 108 } 109 110 /* 111 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another 112 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. 113 */ 114 int sqlite3_mutex_try(sqlite3_mutex *p){ 115 int rc = SQLITE_OK; 116 if( p ){ 117 return sqlite3GlobalConfig.mutex.xMutexTry(p); 118 } 119 return rc; 120 } 121 122 /* 123 ** The sqlite3_mutex_leave() routine exits a mutex that was previously 124 ** entered by the same thread. The behavior is undefined if the mutex 125 ** is not currently entered. If a NULL pointer is passed as an argument 126 ** this function is a no-op. 127 */ 128 void sqlite3_mutex_leave(sqlite3_mutex *p){ 129 if( p ){ 130 sqlite3GlobalConfig.mutex.xMutexLeave(p); 131 } 132 } 133 134 #ifndef NDEBUG 135 /* 136 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are 137 ** intended for use inside assert() statements. 138 */ 139 int sqlite3_mutex_held(sqlite3_mutex *p){ 140 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); 141 } 142 int sqlite3_mutex_notheld(sqlite3_mutex *p){ 143 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); 144 } 145 #endif 146 147 #endif /* SQLITE_OMIT_MUTEX */ 148