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.30 2009/02/17 16:29:11 danielk1977 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 if( sqlite3GlobalConfig.mutex.xMutexEnd ){ 71 rc = sqlite3GlobalConfig.mutex.xMutexEnd(); 72 } 73 return rc; 74 } 75 76 /* 77 ** Retrieve a pointer to a static mutex or allocate a new dynamic one. 78 */ 79 sqlite3_mutex *sqlite3_mutex_alloc(int id){ 80 #ifndef SQLITE_OMIT_AUTOINIT 81 if( sqlite3_initialize() ) return 0; 82 #endif 83 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 84 } 85 86 sqlite3_mutex *sqlite3MutexAlloc(int id){ 87 if( !sqlite3GlobalConfig.bCoreMutex ){ 88 return 0; 89 } 90 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 91 } 92 93 /* 94 ** Free a dynamic mutex. 95 */ 96 void sqlite3_mutex_free(sqlite3_mutex *p){ 97 if( p ){ 98 sqlite3GlobalConfig.mutex.xMutexFree(p); 99 } 100 } 101 102 /* 103 ** Obtain the mutex p. If some other thread already has the mutex, block 104 ** until it can be obtained. 105 */ 106 void sqlite3_mutex_enter(sqlite3_mutex *p){ 107 if( p ){ 108 sqlite3GlobalConfig.mutex.xMutexEnter(p); 109 } 110 } 111 112 /* 113 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another 114 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. 115 */ 116 int sqlite3_mutex_try(sqlite3_mutex *p){ 117 int rc = SQLITE_OK; 118 if( p ){ 119 return sqlite3GlobalConfig.mutex.xMutexTry(p); 120 } 121 return rc; 122 } 123 124 /* 125 ** The sqlite3_mutex_leave() routine exits a mutex that was previously 126 ** entered by the same thread. The behavior is undefined if the mutex 127 ** is not currently entered. If a NULL pointer is passed as an argument 128 ** this function is a no-op. 129 */ 130 void sqlite3_mutex_leave(sqlite3_mutex *p){ 131 if( p ){ 132 sqlite3GlobalConfig.mutex.xMutexLeave(p); 133 } 134 } 135 136 #ifndef NDEBUG 137 /* 138 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are 139 ** intended for use inside assert() statements. 140 */ 141 int sqlite3_mutex_held(sqlite3_mutex *p){ 142 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); 143 } 144 int sqlite3_mutex_notheld(sqlite3_mutex *p){ 145 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); 146 } 147 #endif 148 149 #endif /* SQLITE_OMIT_MUTEX */ 150