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.31 2009/07/16 18:21:18 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 sqlite3_mutex_methods *pFrom = sqlite3DefaultMutex(); 35 sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex; 36 37 memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc)); 38 memcpy(&pTo->xMutexFree, &pFrom->xMutexFree, 39 sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree)); 40 pTo->xMutexAlloc = pFrom->xMutexAlloc; 41 } 42 rc = sqlite3GlobalConfig.mutex.xMutexInit(); 43 } 44 45 return rc; 46 } 47 48 /* 49 ** Shutdown the mutex system. This call frees resources allocated by 50 ** sqlite3MutexInit(). 51 */ 52 int sqlite3MutexEnd(void){ 53 int rc = SQLITE_OK; 54 if( sqlite3GlobalConfig.mutex.xMutexEnd ){ 55 rc = sqlite3GlobalConfig.mutex.xMutexEnd(); 56 } 57 return rc; 58 } 59 60 /* 61 ** Retrieve a pointer to a static mutex or allocate a new dynamic one. 62 */ 63 sqlite3_mutex *sqlite3_mutex_alloc(int id){ 64 #ifndef SQLITE_OMIT_AUTOINIT 65 if( sqlite3_initialize() ) return 0; 66 #endif 67 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 68 } 69 70 sqlite3_mutex *sqlite3MutexAlloc(int id){ 71 if( !sqlite3GlobalConfig.bCoreMutex ){ 72 return 0; 73 } 74 return sqlite3GlobalConfig.mutex.xMutexAlloc(id); 75 } 76 77 /* 78 ** Free a dynamic mutex. 79 */ 80 void sqlite3_mutex_free(sqlite3_mutex *p){ 81 if( p ){ 82 sqlite3GlobalConfig.mutex.xMutexFree(p); 83 } 84 } 85 86 /* 87 ** Obtain the mutex p. If some other thread already has the mutex, block 88 ** until it can be obtained. 89 */ 90 void sqlite3_mutex_enter(sqlite3_mutex *p){ 91 if( p ){ 92 sqlite3GlobalConfig.mutex.xMutexEnter(p); 93 } 94 } 95 96 /* 97 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another 98 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. 99 */ 100 int sqlite3_mutex_try(sqlite3_mutex *p){ 101 int rc = SQLITE_OK; 102 if( p ){ 103 return sqlite3GlobalConfig.mutex.xMutexTry(p); 104 } 105 return rc; 106 } 107 108 /* 109 ** The sqlite3_mutex_leave() routine exits a mutex that was previously 110 ** entered by the same thread. The behavior is undefined if the mutex 111 ** is not currently entered. If a NULL pointer is passed as an argument 112 ** this function is a no-op. 113 */ 114 void sqlite3_mutex_leave(sqlite3_mutex *p){ 115 if( p ){ 116 sqlite3GlobalConfig.mutex.xMutexLeave(p); 117 } 118 } 119 120 #ifndef NDEBUG 121 /* 122 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are 123 ** intended for use inside assert() statements. 124 */ 125 int sqlite3_mutex_held(sqlite3_mutex *p){ 126 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p); 127 } 128 int sqlite3_mutex_notheld(sqlite3_mutex *p){ 129 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p); 130 } 131 #endif 132 133 #endif /* SQLITE_OMIT_MUTEX */ 134