Home | History | Annotate | Download | only in src
      1 /*
      2 ** 2008 October 07
      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 implementation in this file does not provide any mutual
     15 ** exclusion and is thus suitable for use only in applications
     16 ** that use SQLite in a single thread.  The routines defined
     17 ** here are place-holders.  Applications can substitute working
     18 ** mutex routines at start-time using the
     19 **
     20 **     sqlite3_config(SQLITE_CONFIG_MUTEX,...)
     21 **
     22 ** interface.
     23 **
     24 ** If compiled with SQLITE_DEBUG, then additional logic is inserted
     25 ** that does error checking on mutexes to make sure they are being
     26 ** called correctly.
     27 */
     28 #include "sqliteInt.h"
     29 
     30 #ifndef SQLITE_MUTEX_OMIT
     31 
     32 #ifndef SQLITE_DEBUG
     33 /*
     34 ** Stub routines for all mutex methods.
     35 **
     36 ** This routines provide no mutual exclusion or error checking.
     37 */
     38 static int noopMutexInit(void){ return SQLITE_OK; }
     39 static int noopMutexEnd(void){ return SQLITE_OK; }
     40 static sqlite3_mutex *noopMutexAlloc(int id){
     41   UNUSED_PARAMETER(id);
     42   return (sqlite3_mutex*)8;
     43 }
     44 static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
     45 static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
     46 static int noopMutexTry(sqlite3_mutex *p){
     47   UNUSED_PARAMETER(p);
     48   return SQLITE_OK;
     49 }
     50 static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
     51 
     52 sqlite3_mutex_methods const *sqlite3NoopMutex(void){
     53   static const sqlite3_mutex_methods sMutex = {
     54     noopMutexInit,
     55     noopMutexEnd,
     56     noopMutexAlloc,
     57     noopMutexFree,
     58     noopMutexEnter,
     59     noopMutexTry,
     60     noopMutexLeave,
     61 
     62     0,
     63     0,
     64   };
     65 
     66   return &sMutex;
     67 }
     68 #endif /* !SQLITE_DEBUG */
     69 
     70 #ifdef SQLITE_DEBUG
     71 /*
     72 ** In this implementation, error checking is provided for testing
     73 ** and debugging purposes.  The mutexes still do not provide any
     74 ** mutual exclusion.
     75 */
     76 
     77 /*
     78 ** The mutex object
     79 */
     80 typedef struct sqlite3_debug_mutex {
     81   int id;     /* The mutex type */
     82   int cnt;    /* Number of entries without a matching leave */
     83 } sqlite3_debug_mutex;
     84 
     85 /*
     86 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
     87 ** intended for use inside assert() statements.
     88 */
     89 static int debugMutexHeld(sqlite3_mutex *pX){
     90   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
     91   return p==0 || p->cnt>0;
     92 }
     93 static int debugMutexNotheld(sqlite3_mutex *pX){
     94   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
     95   return p==0 || p->cnt==0;
     96 }
     97 
     98 /*
     99 ** Initialize and deinitialize the mutex subsystem.
    100 */
    101 static int debugMutexInit(void){ return SQLITE_OK; }
    102 static int debugMutexEnd(void){ return SQLITE_OK; }
    103 
    104 /*
    105 ** The sqlite3_mutex_alloc() routine allocates a new
    106 ** mutex and returns a pointer to it.  If it returns NULL
    107 ** that means that a mutex could not be allocated.
    108 */
    109 static sqlite3_mutex *debugMutexAlloc(int id){
    110   static sqlite3_debug_mutex aStatic[6];
    111   sqlite3_debug_mutex *pNew = 0;
    112   switch( id ){
    113     case SQLITE_MUTEX_FAST:
    114     case SQLITE_MUTEX_RECURSIVE: {
    115       pNew = sqlite3Malloc(sizeof(*pNew));
    116       if( pNew ){
    117         pNew->id = id;
    118         pNew->cnt = 0;
    119       }
    120       break;
    121     }
    122     default: {
    123       assert( id-2 >= 0 );
    124       assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
    125       pNew = &aStatic[id-2];
    126       pNew->id = id;
    127       break;
    128     }
    129   }
    130   return (sqlite3_mutex*)pNew;
    131 }
    132 
    133 /*
    134 ** This routine deallocates a previously allocated mutex.
    135 */
    136 static void debugMutexFree(sqlite3_mutex *pX){
    137   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
    138   assert( p->cnt==0 );
    139   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
    140   sqlite3_free(p);
    141 }
    142 
    143 /*
    144 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
    145 ** to enter a mutex.  If another thread is already within the mutex,
    146 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
    147 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
    148 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
    149 ** be entered multiple times by the same thread.  In such cases the,
    150 ** mutex must be exited an equal number of times before another thread
    151 ** can enter.  If the same thread tries to enter any other kind of mutex
    152 ** more than once, the behavior is undefined.
    153 */
    154 static void debugMutexEnter(sqlite3_mutex *pX){
    155   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
    156   assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
    157   p->cnt++;
    158 }
    159 static int debugMutexTry(sqlite3_mutex *pX){
    160   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
    161   assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
    162   p->cnt++;
    163   return SQLITE_OK;
    164 }
    165 
    166 /*
    167 ** The sqlite3_mutex_leave() routine exits a mutex that was
    168 ** previously entered by the same thread.  The behavior
    169 ** is undefined if the mutex is not currently entered or
    170 ** is not currently allocated.  SQLite will never do either.
    171 */
    172 static void debugMutexLeave(sqlite3_mutex *pX){
    173   sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
    174   assert( debugMutexHeld(pX) );
    175   p->cnt--;
    176   assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
    177 }
    178 
    179 sqlite3_mutex_methods const *sqlite3NoopMutex(void){
    180   static const sqlite3_mutex_methods sMutex = {
    181     debugMutexInit,
    182     debugMutexEnd,
    183     debugMutexAlloc,
    184     debugMutexFree,
    185     debugMutexEnter,
    186     debugMutexTry,
    187     debugMutexLeave,
    188 
    189     debugMutexHeld,
    190     debugMutexNotheld
    191   };
    192 
    193   return &sMutex;
    194 }
    195 #endif /* SQLITE_DEBUG */
    196 
    197 /*
    198 ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
    199 ** is used regardless of the run-time threadsafety setting.
    200 */
    201 #ifdef SQLITE_MUTEX_NOOP
    202 sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
    203   return sqlite3NoopMutex();
    204 }
    205 #endif /* SQLITE_MUTEX_NOOP */
    206 #endif /* SQLITE_MUTEX_OMIT */
    207