Home | History | Annotate | Download | only in src
      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 */
     26 
     27 
     28 #ifndef SQLITE_MUTEX_OMIT
     29 /*
     30 ** Initialize the mutex system.
     31 */
     32 int sqlite3MutexInit(void){
     33   int rc = SQLITE_OK;
     34   if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
     35     /* If the xMutexAlloc method has not been set, then the user did not
     36     ** install a mutex implementation via sqlite3_config() prior to
     37     ** sqlite3_initialize() being called. This block copies pointers to
     38     ** the default implementation into the sqlite3GlobalConfig structure.
     39     */
     40     sqlite3_mutex_methods const *pFrom;
     41     sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
     42 
     43     if( sqlite3GlobalConfig.bCoreMutex ){
     44       pFrom = sqlite3DefaultMutex();
     45     }else{
     46       pFrom = sqlite3NoopMutex();
     47     }
     48     memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
     49     memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
     50            sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
     51     pTo->xMutexAlloc = pFrom->xMutexAlloc;
     52   }
     53   rc = sqlite3GlobalConfig.mutex.xMutexInit();
     54 
     55 #ifdef SQLITE_DEBUG
     56   GLOBAL(int, mutexIsInit) = 1;
     57 #endif
     58 
     59   return rc;
     60 }
     61 
     62 /*
     63 ** Shutdown the mutex system. This call frees resources allocated by
     64 ** sqlite3MutexInit().
     65 */
     66 int sqlite3MutexEnd(void){
     67   int rc = SQLITE_OK;
     68   if( sqlite3GlobalConfig.mutex.xMutexEnd ){
     69     rc = sqlite3GlobalConfig.mutex.xMutexEnd();
     70   }
     71 
     72 #ifdef SQLITE_DEBUG
     73   GLOBAL(int, mutexIsInit) = 0;
     74 #endif
     75 
     76   return rc;
     77 }
     78 
     79 /*
     80 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
     81 */
     82 sqlite3_mutex *sqlite3_mutex_alloc(int id){
     83 #ifndef SQLITE_OMIT_AUTOINIT
     84   if( sqlite3_initialize() ) return 0;
     85 #endif
     86   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
     87 }
     88 
     89 sqlite3_mutex *sqlite3MutexAlloc(int id){
     90   if( !sqlite3GlobalConfig.bCoreMutex ){
     91     return 0;
     92   }
     93   assert( GLOBAL(int, mutexIsInit) );
     94   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
     95 }
     96 
     97 /*
     98 ** Free a dynamic mutex.
     99 */
    100 void sqlite3_mutex_free(sqlite3_mutex *p){
    101   if( p ){
    102     sqlite3GlobalConfig.mutex.xMutexFree(p);
    103   }
    104 }
    105 
    106 /*
    107 ** Obtain the mutex p. If some other thread already has the mutex, block
    108 ** until it can be obtained.
    109 */
    110 void sqlite3_mutex_enter(sqlite3_mutex *p){
    111   if( p ){
    112     sqlite3GlobalConfig.mutex.xMutexEnter(p);
    113   }
    114 }
    115 
    116 /*
    117 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
    118 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
    119 */
    120 int sqlite3_mutex_try(sqlite3_mutex *p){
    121   int rc = SQLITE_OK;
    122   if( p ){
    123     return sqlite3GlobalConfig.mutex.xMutexTry(p);
    124   }
    125   return rc;
    126 }
    127 
    128 /*
    129 ** The sqlite3_mutex_leave() routine exits a mutex that was previously
    130 ** entered by the same thread.  The behavior is undefined if the mutex
    131 ** is not currently entered. If a NULL pointer is passed as an argument
    132 ** this function is a no-op.
    133 */
    134 void sqlite3_mutex_leave(sqlite3_mutex *p){
    135   if( p ){
    136     sqlite3GlobalConfig.mutex.xMutexLeave(p);
    137   }
    138 }
    139 
    140 #ifndef NDEBUG
    141 /*
    142 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
    143 ** intended for use inside assert() statements.
    144 */
    145 int sqlite3_mutex_held(sqlite3_mutex *p){
    146   return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
    147 }
    148 int sqlite3_mutex_notheld(sqlite3_mutex *p){
    149   return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
    150 }
    151 #endif
    152 
    153 #endif /* SQLITE_MUTEX_OMIT */
    154