|         |      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 ** The 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.  But this implementation | 
|         |     17 ** does do a lot of error checking on mutexes to make sure they | 
|         |     18 ** are called correctly and at appropriate times.  Hence, this | 
|         |     19 ** implementation is suitable for testing. | 
|         |     20 ** debugging purposes | 
|         |     21 ** | 
|         |     22 ** $Id: mutex.c,v 1.27 2008/06/19 08:51:24 danielk1977 Exp $ | 
|         |     23 */ | 
|         |     24 #include "sqliteInt.h" | 
|         |     25  | 
|         |     26 #ifndef SQLITE_MUTEX_NOOP | 
|         |     27 /* | 
|         |     28 ** Initialize the mutex system. | 
|         |     29 */ | 
|         |     30 int sqlite3MutexInit(void){  | 
|         |     31   int rc = SQLITE_OK; | 
|         |     32   if( sqlite3Config.bCoreMutex ){ | 
|         |     33     if( !sqlite3Config.mutex.xMutexAlloc ){ | 
|         |     34       /* If the xMutexAlloc method has not been set, then the user did not | 
|         |     35       ** install a mutex implementation via sqlite3_config() prior to  | 
|         |     36       ** sqlite3_initialize() being called. This block copies pointers to | 
|         |     37       ** the default implementation into the sqlite3Config structure. | 
|         |     38       ** | 
|         |     39       ** The danger is that although sqlite3_config() is not a threadsafe | 
|         |     40       ** API, sqlite3_initialize() is, and so multiple threads may be | 
|         |     41       ** attempting to run this function simultaneously. To guard write | 
|         |     42       ** access to the sqlite3Config structure, the 'MASTER' static mutex | 
|         |     43       ** is obtained before modifying it. | 
|         |     44       */ | 
|         |     45       sqlite3_mutex_methods *p = sqlite3DefaultMutex(); | 
|         |     46       sqlite3_mutex *pMaster = 0; | 
|         |     47    | 
|         |     48       rc = p->xMutexInit(); | 
|         |     49       if( rc==SQLITE_OK ){ | 
|         |     50         pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER); | 
|         |     51         assert(pMaster); | 
|         |     52         p->xMutexEnter(pMaster); | 
|         |     53         assert( sqlite3Config.mutex.xMutexAlloc==0  | 
|         |     54              || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc | 
|         |     55         ); | 
|         |     56         if( !sqlite3Config.mutex.xMutexAlloc ){ | 
|         |     57           sqlite3Config.mutex = *p; | 
|         |     58         } | 
|         |     59         p->xMutexLeave(pMaster); | 
|         |     60       } | 
|         |     61     }else{ | 
|         |     62       rc = sqlite3Config.mutex.xMutexInit(); | 
|         |     63     } | 
|         |     64   } | 
|         |     65  | 
|         |     66   return rc; | 
|         |     67 } | 
|         |     68  | 
|         |     69 /* | 
|         |     70 ** Shutdown the mutex system. This call frees resources allocated by | 
|         |     71 ** sqlite3MutexInit(). | 
|         |     72 */ | 
|         |     73 int sqlite3MutexEnd(void){ | 
|         |     74   int rc = SQLITE_OK; | 
|         |     75   rc = sqlite3Config.mutex.xMutexEnd(); | 
|         |     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 sqlite3Config.mutex.xMutexAlloc(id); | 
|         |     87 } | 
|         |     88  | 
|         |     89 sqlite3_mutex *sqlite3MutexAlloc(int id){ | 
|         |     90   if( !sqlite3Config.bCoreMutex ){ | 
|         |     91     return 0; | 
|         |     92   } | 
|         |     93   return sqlite3Config.mutex.xMutexAlloc(id); | 
|         |     94 } | 
|         |     95  | 
|         |     96 /* | 
|         |     97 ** Free a dynamic mutex. | 
|         |     98 */ | 
|         |     99 void sqlite3_mutex_free(sqlite3_mutex *p){ | 
|         |    100   if( p ){ | 
|         |    101     sqlite3Config.mutex.xMutexFree(p); | 
|         |    102   } | 
|         |    103 } | 
|         |    104  | 
|         |    105 /* | 
|         |    106 ** Obtain the mutex p. If some other thread already has the mutex, block | 
|         |    107 ** until it can be obtained. | 
|         |    108 */ | 
|         |    109 void sqlite3_mutex_enter(sqlite3_mutex *p){ | 
|         |    110   if( p ){ | 
|         |    111     sqlite3Config.mutex.xMutexEnter(p); | 
|         |    112   } | 
|         |    113 } | 
|         |    114  | 
|         |    115 /* | 
|         |    116 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another | 
|         |    117 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY. | 
|         |    118 */ | 
|         |    119 int sqlite3_mutex_try(sqlite3_mutex *p){ | 
|         |    120   int rc = SQLITE_OK; | 
|         |    121   if( p ){ | 
|         |    122     return sqlite3Config.mutex.xMutexTry(p); | 
|         |    123   } | 
|         |    124   return rc; | 
|         |    125 } | 
|         |    126  | 
|         |    127 /* | 
|         |    128 ** The sqlite3_mutex_leave() routine exits a mutex that was previously | 
|         |    129 ** entered by the same thread.  The behavior is undefined if the mutex  | 
|         |    130 ** is not currently entered. If a NULL pointer is passed as an argument | 
|         |    131 ** this function is a no-op. | 
|         |    132 */ | 
|         |    133 void sqlite3_mutex_leave(sqlite3_mutex *p){ | 
|         |    134   if( p ){ | 
|         |    135     sqlite3Config.mutex.xMutexLeave(p); | 
|         |    136   } | 
|         |    137 } | 
|         |    138  | 
|         |    139 #ifndef NDEBUG | 
|         |    140 /* | 
|         |    141 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | 
|         |    142 ** intended for use inside assert() statements. | 
|         |    143 */ | 
|         |    144 int sqlite3_mutex_held(sqlite3_mutex *p){ | 
|         |    145   return p==0 || sqlite3Config.mutex.xMutexHeld(p); | 
|         |    146 } | 
|         |    147 int sqlite3_mutex_notheld(sqlite3_mutex *p){ | 
|         |    148   return p==0 || sqlite3Config.mutex.xMutexNotheld(p); | 
|         |    149 } | 
|         |    150 #endif | 
|         |    151  | 
|         |    152 #endif | 
|         |    153  | 
|         |    154 #ifdef SQLITE_MUTEX_NOOP_DEBUG | 
|         |    155 /* | 
|         |    156 ** In this implementation, mutexes do not provide any mutual exclusion. | 
|         |    157 ** But the error checking is provided.  This implementation is useful | 
|         |    158 ** for test purposes. | 
|         |    159 */ | 
|         |    160  | 
|         |    161 /* | 
|         |    162 ** The mutex object | 
|         |    163 */ | 
|         |    164 struct sqlite3_mutex { | 
|         |    165   int id;     /* The mutex type */ | 
|         |    166   int cnt;    /* Number of entries without a matching leave */ | 
|         |    167 }; | 
|         |    168  | 
|         |    169 /* | 
|         |    170 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | 
|         |    171 ** intended for use inside assert() statements. | 
|         |    172 */ | 
|         |    173 static int noopMutexHeld(sqlite3_mutex *p){ | 
|         |    174   return p==0 || p->cnt>0; | 
|         |    175 } | 
|         |    176 static int noopMutexNotheld(sqlite3_mutex *p){ | 
|         |    177   return p==0 || p->cnt==0; | 
|         |    178 } | 
|         |    179  | 
|         |    180 /* | 
|         |    181 ** Initialize and deinitialize the mutex subsystem. | 
|         |    182 */ | 
|         |    183 static int noopMutexInit(void){ return SQLITE_OK; } | 
|         |    184 static int noopMutexEnd(void){ return SQLITE_OK; } | 
|         |    185  | 
|         |    186 /* | 
|         |    187 ** The sqlite3_mutex_alloc() routine allocates a new | 
|         |    188 ** mutex and returns a pointer to it.  If it returns NULL | 
|         |    189 ** that means that a mutex could not be allocated.  | 
|         |    190 */ | 
|         |    191 static sqlite3_mutex *noopMutexAlloc(int id){ | 
|         |    192   static sqlite3_mutex aStatic[6]; | 
|         |    193   sqlite3_mutex *pNew = 0; | 
|         |    194   switch( id ){ | 
|         |    195     case SQLITE_MUTEX_FAST: | 
|         |    196     case SQLITE_MUTEX_RECURSIVE: { | 
|         |    197       pNew = sqlite3Malloc(sizeof(*pNew)); | 
|         |    198       if( pNew ){ | 
|         |    199         pNew->id = id; | 
|         |    200         pNew->cnt = 0; | 
|         |    201       } | 
|         |    202       break; | 
|         |    203     } | 
|         |    204     default: { | 
|         |    205       assert( id-2 >= 0 ); | 
|         |    206       assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); | 
|         |    207       pNew = &aStatic[id-2]; | 
|         |    208       pNew->id = id; | 
|         |    209       break; | 
|         |    210     } | 
|         |    211   } | 
|         |    212   return pNew; | 
|         |    213 } | 
|         |    214  | 
|         |    215 /* | 
|         |    216 ** This routine deallocates a previously allocated mutex. | 
|         |    217 */ | 
|         |    218 static void noopMutexFree(sqlite3_mutex *p){ | 
|         |    219   assert( p->cnt==0 ); | 
|         |    220   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); | 
|         |    221   sqlite3_free(p); | 
|         |    222 } | 
|         |    223  | 
|         |    224 /* | 
|         |    225 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt | 
|         |    226 ** to enter a mutex.  If another thread is already within the mutex, | 
|         |    227 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return | 
|         |    228 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK | 
|         |    229 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can | 
|         |    230 ** be entered multiple times by the same thread.  In such cases the, | 
|         |    231 ** mutex must be exited an equal number of times before another thread | 
|         |    232 ** can enter.  If the same thread tries to enter any other kind of mutex | 
|         |    233 ** more than once, the behavior is undefined. | 
|         |    234 */ | 
|         |    235 static void noopMutexEnter(sqlite3_mutex *p){ | 
|         |    236   assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); | 
|         |    237   p->cnt++; | 
|         |    238 } | 
|         |    239 static int noopMutexTry(sqlite3_mutex *p){ | 
|         |    240   assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); | 
|         |    241   p->cnt++; | 
|         |    242   return SQLITE_OK; | 
|         |    243 } | 
|         |    244  | 
|         |    245 /* | 
|         |    246 ** The sqlite3_mutex_leave() routine exits a mutex that was | 
|         |    247 ** previously entered by the same thread.  The behavior | 
|         |    248 ** is undefined if the mutex is not currently entered or | 
|         |    249 ** is not currently allocated.  SQLite will never do either. | 
|         |    250 */ | 
|         |    251 static void noopMutexLeave(sqlite3_mutex *p){ | 
|         |    252   assert( noopMutexHeld(p) ); | 
|         |    253   p->cnt--; | 
|         |    254   assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); | 
|         |    255 } | 
|         |    256  | 
|         |    257 sqlite3_mutex_methods *sqlite3DefaultMutex(void){ | 
|         |    258   static sqlite3_mutex_methods sMutex = { | 
|         |    259     noopMutexInit, | 
|         |    260     noopMutexEnd, | 
|         |    261     noopMutexAlloc, | 
|         |    262     noopMutexFree, | 
|         |    263     noopMutexEnter, | 
|         |    264     noopMutexTry, | 
|         |    265     noopMutexLeave, | 
|         |    266  | 
|         |    267     noopMutexHeld, | 
|         |    268     noopMutexNotheld | 
|         |    269   }; | 
|         |    270  | 
|         |    271   return &sMutex; | 
|         |    272 } | 
|         |    273 #endif /* SQLITE_MUTEX_NOOP_DEBUG */ |