118472fa7Sdrh /*
218472fa7Sdrh ** 2008 October 07
318472fa7Sdrh **
418472fa7Sdrh ** The author disclaims copyright to this source code. In place of
518472fa7Sdrh ** a legal notice, here is a blessing:
618472fa7Sdrh **
718472fa7Sdrh ** May you do good and not evil.
818472fa7Sdrh ** May you find forgiveness for yourself and forgive others.
918472fa7Sdrh ** May you share freely, never taking more than you give.
1018472fa7Sdrh **
1118472fa7Sdrh *************************************************************************
1218472fa7Sdrh ** This file contains the C functions that implement mutexes.
1318472fa7Sdrh **
1418472fa7Sdrh ** This implementation in this file does not provide any mutual
1518472fa7Sdrh ** exclusion and is thus suitable for use only in applications
1618472fa7Sdrh ** that use SQLite in a single thread. The routines defined
1718472fa7Sdrh ** here are place-holders. Applications can substitute working
1818472fa7Sdrh ** mutex routines at start-time using the
1918472fa7Sdrh **
2018472fa7Sdrh ** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
2118472fa7Sdrh **
2218472fa7Sdrh ** interface.
2318472fa7Sdrh **
2418472fa7Sdrh ** If compiled with SQLITE_DEBUG, then additional logic is inserted
2518472fa7Sdrh ** that does error checking on mutexes to make sure they are being
2618472fa7Sdrh ** called correctly.
2718472fa7Sdrh */
2818472fa7Sdrh #include "sqliteInt.h"
2918472fa7Sdrh
30e874d9edSdrh #ifndef SQLITE_MUTEX_OMIT
3118472fa7Sdrh
3292d76523Sdrh #ifndef SQLITE_DEBUG
3318472fa7Sdrh /*
3418472fa7Sdrh ** Stub routines for all mutex methods.
3518472fa7Sdrh **
3618472fa7Sdrh ** This routines provide no mutual exclusion or error checking.
3718472fa7Sdrh */
noopMutexInit(void)3818472fa7Sdrh static int noopMutexInit(void){ return SQLITE_OK; }
noopMutexEnd(void)3918472fa7Sdrh static int noopMutexEnd(void){ return SQLITE_OK; }
noopMutexAlloc(int id)40ff82894fSdrh static sqlite3_mutex *noopMutexAlloc(int id){
41ff82894fSdrh UNUSED_PARAMETER(id);
42ff82894fSdrh return (sqlite3_mutex*)8;
43ff82894fSdrh }
noopMutexFree(sqlite3_mutex * p)44ff82894fSdrh static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
noopMutexEnter(sqlite3_mutex * p)45ff82894fSdrh static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
noopMutexTry(sqlite3_mutex * p)46ff82894fSdrh static int noopMutexTry(sqlite3_mutex *p){
47ff82894fSdrh UNUSED_PARAMETER(p);
48ff82894fSdrh return SQLITE_OK;
49ff82894fSdrh }
noopMutexLeave(sqlite3_mutex * p)50ff82894fSdrh static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
5118472fa7Sdrh
sqlite3NoopMutex(void)52558814f8Sdan sqlite3_mutex_methods const *sqlite3NoopMutex(void){
53558814f8Sdan static const sqlite3_mutex_methods sMutex = {
5418472fa7Sdrh noopMutexInit,
5518472fa7Sdrh noopMutexEnd,
5618472fa7Sdrh noopMutexAlloc,
5718472fa7Sdrh noopMutexFree,
5818472fa7Sdrh noopMutexEnter,
5918472fa7Sdrh noopMutexTry,
6018472fa7Sdrh noopMutexLeave,
6118472fa7Sdrh
62e404de05Sdrh 0,
63e404de05Sdrh 0,
6418472fa7Sdrh };
6518472fa7Sdrh
6618472fa7Sdrh return &sMutex;
6718472fa7Sdrh }
6892d76523Sdrh #endif /* !SQLITE_DEBUG */
6918472fa7Sdrh
7092d76523Sdrh #ifdef SQLITE_DEBUG
7118472fa7Sdrh /*
7218472fa7Sdrh ** In this implementation, error checking is provided for testing
7318472fa7Sdrh ** and debugging purposes. The mutexes still do not provide any
7418472fa7Sdrh ** mutual exclusion.
7518472fa7Sdrh */
7618472fa7Sdrh
7718472fa7Sdrh /*
7818472fa7Sdrh ** The mutex object
7918472fa7Sdrh */
80fc34ad29Sdrh typedef struct sqlite3_debug_mutex {
8118472fa7Sdrh int id; /* The mutex type */
8218472fa7Sdrh int cnt; /* Number of entries without a matching leave */
83fc34ad29Sdrh } sqlite3_debug_mutex;
8418472fa7Sdrh
8518472fa7Sdrh /*
8618472fa7Sdrh ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
8718472fa7Sdrh ** intended for use inside assert() statements.
8818472fa7Sdrh */
debugMutexHeld(sqlite3_mutex * pX)89fc34ad29Sdrh static int debugMutexHeld(sqlite3_mutex *pX){
90fc34ad29Sdrh sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
9118472fa7Sdrh return p==0 || p->cnt>0;
9218472fa7Sdrh }
debugMutexNotheld(sqlite3_mutex * pX)93fc34ad29Sdrh static int debugMutexNotheld(sqlite3_mutex *pX){
94fc34ad29Sdrh sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
9518472fa7Sdrh return p==0 || p->cnt==0;
9618472fa7Sdrh }
9718472fa7Sdrh
9818472fa7Sdrh /*
9918472fa7Sdrh ** Initialize and deinitialize the mutex subsystem.
10018472fa7Sdrh */
debugMutexInit(void)10118472fa7Sdrh static int debugMutexInit(void){ return SQLITE_OK; }
debugMutexEnd(void)10218472fa7Sdrh static int debugMutexEnd(void){ return SQLITE_OK; }
10318472fa7Sdrh
10418472fa7Sdrh /*
10518472fa7Sdrh ** The sqlite3_mutex_alloc() routine allocates a new
10618472fa7Sdrh ** mutex and returns a pointer to it. If it returns NULL
10718472fa7Sdrh ** that means that a mutex could not be allocated.
10818472fa7Sdrh */
debugMutexAlloc(int id)10918472fa7Sdrh static sqlite3_mutex *debugMutexAlloc(int id){
110*93de6538Smistachkin static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1];
111fc34ad29Sdrh sqlite3_debug_mutex *pNew = 0;
11218472fa7Sdrh switch( id ){
11318472fa7Sdrh case SQLITE_MUTEX_FAST:
11418472fa7Sdrh case SQLITE_MUTEX_RECURSIVE: {
11518472fa7Sdrh pNew = sqlite3Malloc(sizeof(*pNew));
11618472fa7Sdrh if( pNew ){
11718472fa7Sdrh pNew->id = id;
11818472fa7Sdrh pNew->cnt = 0;
11918472fa7Sdrh }
12018472fa7Sdrh break;
12118472fa7Sdrh }
12218472fa7Sdrh default: {
12396c707a3Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
12496c707a3Sdrh if( id-2<0 || id-2>=ArraySize(aStatic) ){
12596c707a3Sdrh (void)SQLITE_MISUSE_BKPT;
12696c707a3Sdrh return 0;
12796c707a3Sdrh }
12896c707a3Sdrh #endif
12918472fa7Sdrh pNew = &aStatic[id-2];
13018472fa7Sdrh pNew->id = id;
13118472fa7Sdrh break;
13218472fa7Sdrh }
13318472fa7Sdrh }
134fc34ad29Sdrh return (sqlite3_mutex*)pNew;
13518472fa7Sdrh }
13618472fa7Sdrh
13718472fa7Sdrh /*
13818472fa7Sdrh ** This routine deallocates a previously allocated mutex.
13918472fa7Sdrh */
debugMutexFree(sqlite3_mutex * pX)140fc34ad29Sdrh static void debugMutexFree(sqlite3_mutex *pX){
141fc34ad29Sdrh sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
14218472fa7Sdrh assert( p->cnt==0 );
14396c707a3Sdrh if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){
14418472fa7Sdrh sqlite3_free(p);
14596c707a3Sdrh }else{
14696c707a3Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
14796c707a3Sdrh (void)SQLITE_MISUSE_BKPT;
14896c707a3Sdrh #endif
14996c707a3Sdrh }
15018472fa7Sdrh }
15118472fa7Sdrh
15218472fa7Sdrh /*
15318472fa7Sdrh ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
15418472fa7Sdrh ** to enter a mutex. If another thread is already within the mutex,
15518472fa7Sdrh ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
15618472fa7Sdrh ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
15718472fa7Sdrh ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
15818472fa7Sdrh ** be entered multiple times by the same thread. In such cases the,
15918472fa7Sdrh ** mutex must be exited an equal number of times before another thread
16018472fa7Sdrh ** can enter. If the same thread tries to enter any other kind of mutex
16118472fa7Sdrh ** more than once, the behavior is undefined.
16218472fa7Sdrh */
debugMutexEnter(sqlite3_mutex * pX)163fc34ad29Sdrh static void debugMutexEnter(sqlite3_mutex *pX){
164fc34ad29Sdrh sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
165fc34ad29Sdrh assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
16618472fa7Sdrh p->cnt++;
16718472fa7Sdrh }
debugMutexTry(sqlite3_mutex * pX)168fc34ad29Sdrh static int debugMutexTry(sqlite3_mutex *pX){
169fc34ad29Sdrh sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
170fc34ad29Sdrh assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
17118472fa7Sdrh p->cnt++;
17218472fa7Sdrh return SQLITE_OK;
17318472fa7Sdrh }
17418472fa7Sdrh
17518472fa7Sdrh /*
17618472fa7Sdrh ** The sqlite3_mutex_leave() routine exits a mutex that was
17718472fa7Sdrh ** previously entered by the same thread. The behavior
17818472fa7Sdrh ** is undefined if the mutex is not currently entered or
17918472fa7Sdrh ** is not currently allocated. SQLite will never do either.
18018472fa7Sdrh */
debugMutexLeave(sqlite3_mutex * pX)181fc34ad29Sdrh static void debugMutexLeave(sqlite3_mutex *pX){
182fc34ad29Sdrh sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
183fc34ad29Sdrh assert( debugMutexHeld(pX) );
18418472fa7Sdrh p->cnt--;
185fc34ad29Sdrh assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
18618472fa7Sdrh }
18718472fa7Sdrh
sqlite3NoopMutex(void)188558814f8Sdan sqlite3_mutex_methods const *sqlite3NoopMutex(void){
189558814f8Sdan static const sqlite3_mutex_methods sMutex = {
19018472fa7Sdrh debugMutexInit,
19118472fa7Sdrh debugMutexEnd,
19218472fa7Sdrh debugMutexAlloc,
19318472fa7Sdrh debugMutexFree,
19418472fa7Sdrh debugMutexEnter,
19518472fa7Sdrh debugMutexTry,
19618472fa7Sdrh debugMutexLeave,
19718472fa7Sdrh
19818472fa7Sdrh debugMutexHeld,
19918472fa7Sdrh debugMutexNotheld
20018472fa7Sdrh };
20118472fa7Sdrh
20218472fa7Sdrh return &sMutex;
20318472fa7Sdrh }
20492d76523Sdrh #endif /* SQLITE_DEBUG */
20592d76523Sdrh
20692d76523Sdrh /*
20792d76523Sdrh ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
20892d76523Sdrh ** is used regardless of the run-time threadsafety setting.
20992d76523Sdrh */
21092d76523Sdrh #ifdef SQLITE_MUTEX_NOOP
sqlite3DefaultMutex(void)211558814f8Sdan sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
2127750ab48Sdrh return sqlite3NoopMutex();
21392d76523Sdrh }
214e4c88c0cSdrh #endif /* defined(SQLITE_MUTEX_NOOP) */
215e4c88c0cSdrh #endif /* !defined(SQLITE_MUTEX_OMIT) */
216