| /* | |
| ** 2008 October 07 | |
| ** | |
| ** The author disclaims copyright to this source code. In place of | |
| ** a legal notice, here is a blessing: | |
| ** | |
| ** May you do good and not evil. | |
| ** May you find forgiveness for yourself and forgive others. | |
| ** May you share freely, never taking more than you give. | |
| ** | |
| ************************************************************************* | |
| ** This file contains the C functions that implement mutexes. | |
| ** | |
| ** This implementation in this file does not provide any mutual | |
| ** exclusion and is thus suitable for use only in applications | |
| ** that use SQLite in a single thread. The routines defined | |
| ** here are place-holders. Applications can substitute working | |
| ** mutex routines at start-time using the | |
| ** | |
| ** sqlite3_config(SQLITE_CONFIG_MUTEX,...) | |
| ** | |
| ** interface. | |
| ** | |
| ** If compiled with SQLITE_DEBUG, then additional logic is inserted | |
| ** that does error checking on mutexes to make sure they are being | |
| ** called correctly. | |
| */ | |
| #include "sqliteInt.h" | |
| #ifndef SQLITE_MUTEX_OMIT | |
| #ifndef SQLITE_DEBUG | |
| /* | |
| ** Stub routines for all mutex methods. | |
| ** | |
| ** This routines provide no mutual exclusion or error checking. | |
| */ | |
| static int noopMutexInit(void){ return SQLITE_OK; } | |
| static int noopMutexEnd(void){ return SQLITE_OK; } | |
| static sqlite3_mutex *noopMutexAlloc(int id){ | |
| UNUSED_PARAMETER(id); | |
| return (sqlite3_mutex*)8; | |
| } | |
| static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } | |
| static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } | |
| static int noopMutexTry(sqlite3_mutex *p){ | |
| UNUSED_PARAMETER(p); | |
| return SQLITE_OK; | |
| } | |
| static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } | |
| sqlite3_mutex_methods const *sqlite3NoopMutex(void){ | |
| static const sqlite3_mutex_methods sMutex = { | |
| noopMutexInit, | |
| noopMutexEnd, | |
| noopMutexAlloc, | |
| noopMutexFree, | |
| noopMutexEnter, | |
| noopMutexTry, | |
| noopMutexLeave, | |
| 0, | |
| 0, | |
| }; | |
| return &sMutex; | |
| } | |
| #endif /* !SQLITE_DEBUG */ | |
| #ifdef SQLITE_DEBUG | |
| /* | |
| ** In this implementation, error checking is provided for testing | |
| ** and debugging purposes. The mutexes still do not provide any | |
| ** mutual exclusion. | |
| */ | |
| /* | |
| ** The mutex object | |
| */ | |
| typedef struct sqlite3_debug_mutex { | |
| int id; /* The mutex type */ | |
| int cnt; /* Number of entries without a matching leave */ | |
| } sqlite3_debug_mutex; | |
| /* | |
| ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | |
| ** intended for use inside assert() statements. | |
| */ | |
| static int debugMutexHeld(sqlite3_mutex *pX){ | |
| sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; | |
| return p==0 || p->cnt>0; | |
| } | |
| static int debugMutexNotheld(sqlite3_mutex *pX){ | |
| sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; | |
| return p==0 || p->cnt==0; | |
| } | |
| /* | |
| ** Initialize and deinitialize the mutex subsystem. | |
| */ | |
| static int debugMutexInit(void){ return SQLITE_OK; } | |
| static int debugMutexEnd(void){ return SQLITE_OK; } | |
| /* | |
| ** The sqlite3_mutex_alloc() routine allocates a new | |
| ** mutex and returns a pointer to it. If it returns NULL | |
| ** that means that a mutex could not be allocated. | |
| */ | |
| static sqlite3_mutex *debugMutexAlloc(int id){ | |
| static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; | |
| sqlite3_debug_mutex *pNew = 0; | |
| switch( id ){ | |
| case SQLITE_MUTEX_FAST: | |
| case SQLITE_MUTEX_RECURSIVE: { | |
| pNew = sqlite3Malloc(sizeof(*pNew)); | |
| if( pNew ){ | |
| pNew->id = id; | |
| pNew->cnt = 0; | |
| } | |
| break; | |
| } | |
| default: { | |
| #ifdef SQLITE_ENABLE_API_ARMOR | |
| if( id-2<0 || id-2>=ArraySize(aStatic) ){ | |
| (void)SQLITE_MISUSE_BKPT; | |
| return 0; | |
| } | |
| #endif | |
| pNew = &aStatic[id-2]; | |
| pNew->id = id; | |
| break; | |
| } | |
| } | |
| return (sqlite3_mutex*)pNew; | |
| } | |
| /* | |
| ** This routine deallocates a previously allocated mutex. | |
| */ | |
| static void debugMutexFree(sqlite3_mutex *pX){ | |
| sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; | |
| assert( p->cnt==0 ); | |
| if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ | |
| sqlite3_free(p); | |
| }else{ | |
| #ifdef SQLITE_ENABLE_API_ARMOR | |
| (void)SQLITE_MISUSE_BKPT; | |
| #endif | |
| } | |
| } | |
| /* | |
| ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt | |
| ** to enter a mutex. If another thread is already within the mutex, | |
| ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return | |
| ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK | |
| ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can | |
| ** be entered multiple times by the same thread. In such cases the, | |
| ** mutex must be exited an equal number of times before another thread | |
| ** can enter. If the same thread tries to enter any other kind of mutex | |
| ** more than once, the behavior is undefined. | |
| */ | |
| static void debugMutexEnter(sqlite3_mutex *pX){ | |
| sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; | |
| assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); | |
| p->cnt++; | |
| } | |
| static int debugMutexTry(sqlite3_mutex *pX){ | |
| sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; | |
| assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); | |
| p->cnt++; | |
| return SQLITE_OK; | |
| } | |
| /* | |
| ** The sqlite3_mutex_leave() routine exits a mutex that was | |
| ** previously entered by the same thread. The behavior | |
| ** is undefined if the mutex is not currently entered or | |
| ** is not currently allocated. SQLite will never do either. | |
| */ | |
| static void debugMutexLeave(sqlite3_mutex *pX){ | |
| sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; | |
| assert( debugMutexHeld(pX) ); | |
| p->cnt--; | |
| assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); | |
| } | |
| sqlite3_mutex_methods const *sqlite3NoopMutex(void){ | |
| static const sqlite3_mutex_methods sMutex = { | |
| debugMutexInit, | |
| debugMutexEnd, | |
| debugMutexAlloc, | |
| debugMutexFree, | |
| debugMutexEnter, | |
| debugMutexTry, | |
| debugMutexLeave, | |
| debugMutexHeld, | |
| debugMutexNotheld | |
| }; | |
| return &sMutex; | |
| } | |
| #endif /* SQLITE_DEBUG */ | |
| /* | |
| ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation | |
| ** is used regardless of the run-time threadsafety setting. | |
| */ | |
| #ifdef SQLITE_MUTEX_NOOP | |
| sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ | |
| return sqlite3NoopMutex(); | |
| } | |
| #endif /* defined(SQLITE_MUTEX_NOOP) */ | |
| #endif /* !defined(SQLITE_MUTEX_OMIT) */ |