190f6a5beSdrh /*
290f6a5beSdrh ** 2007 August 14
390f6a5beSdrh **
490f6a5beSdrh ** The author disclaims copyright to this source code. In place of
590f6a5beSdrh ** a legal notice, here is a blessing:
690f6a5beSdrh **
790f6a5beSdrh ** May you do good and not evil.
890f6a5beSdrh ** May you find forgiveness for yourself and forgive others.
990f6a5beSdrh ** May you share freely, never taking more than you give.
1090f6a5beSdrh **
1190f6a5beSdrh *************************************************************************
12437b9013Sdrh ** This file contains the C functions that implement mutexes.
1390f6a5beSdrh **
1418472fa7Sdrh ** This file contains code that is common across all mutex implementations.
1590f6a5beSdrh */
1690f6a5beSdrh #include "sqliteInt.h"
1790f6a5beSdrh
18d0bc5d2aSdrh #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
19fe5bdb36Sdrh /*
20fe5bdb36Sdrh ** For debugging purposes, record when the mutex subsystem is initialized
21fe5bdb36Sdrh ** and uninitialized so that we can assert() if there is an attempt to
22fe5bdb36Sdrh ** allocate a mutex while the system is uninitialized.
23fe5bdb36Sdrh */
24fe5bdb36Sdrh static SQLITE_WSD int mutexIsInit = 0;
2504abf087Smistachkin #endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */
26fe5bdb36Sdrh
27fe5bdb36Sdrh
2818472fa7Sdrh #ifndef SQLITE_MUTEX_OMIT
298385becfSdan
308385becfSdan #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
318385becfSdan /*
328385becfSdan ** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
338385becfSdan ** the implementation of a wrapper around the system default mutex
348385becfSdan ** implementation (sqlite3DefaultMutex()).
358385becfSdan **
368385becfSdan ** Most calls are passed directly through to the underlying default
378385becfSdan ** mutex implementation. Except, if a mutex is configured by calling
388385becfSdan ** sqlite3MutexWarnOnContention() on it, then if contention is ever
398385becfSdan ** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
408385becfSdan **
418385becfSdan ** This type of mutex is used as the database handle mutex when testing
428385becfSdan ** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
438385becfSdan */
448385becfSdan
458385becfSdan /*
468385becfSdan ** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
47a90a2d58Sdan ** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
48a90a2d58Sdan ** allocated by the system mutex implementation. Variable iType is usually set
49a90a2d58Sdan ** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
50a90a2d58Sdan ** or one of the static mutex identifiers. Or, if this is a recursive mutex
51a90a2d58Sdan ** that has been configured using sqlite3MutexWarnOnContention(), it is
52a90a2d58Sdan ** set to SQLITE_MUTEX_WARNONCONTENTION.
538385becfSdan */
548385becfSdan typedef struct CheckMutex CheckMutex;
558385becfSdan struct CheckMutex {
568385becfSdan int iType;
578385becfSdan sqlite3_mutex *mutex;
588385becfSdan };
598385becfSdan
60a90a2d58Sdan #define SQLITE_MUTEX_WARNONCONTENTION (-1)
61a90a2d58Sdan
628385becfSdan /*
638385becfSdan ** Pointer to real mutex methods object used by the CheckMutex
648385becfSdan ** implementation. Set by checkMutexInit().
658385becfSdan */
668385becfSdan static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
678385becfSdan
688385becfSdan #ifdef SQLITE_DEBUG
checkMutexHeld(sqlite3_mutex * p)698385becfSdan static int checkMutexHeld(sqlite3_mutex *p){
708385becfSdan return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex);
718385becfSdan }
checkMutexNotheld(sqlite3_mutex * p)728385becfSdan static int checkMutexNotheld(sqlite3_mutex *p){
738385becfSdan return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex);
748385becfSdan }
758385becfSdan #endif
768385becfSdan
778385becfSdan /*
788385becfSdan ** Initialize and deinitialize the mutex subsystem.
798385becfSdan */
checkMutexInit(void)808385becfSdan static int checkMutexInit(void){
818385becfSdan pGlobalMutexMethods = sqlite3DefaultMutex();
828385becfSdan return SQLITE_OK;
838385becfSdan }
checkMutexEnd(void)848385becfSdan static int checkMutexEnd(void){
858385becfSdan pGlobalMutexMethods = 0;
868385becfSdan return SQLITE_OK;
878385becfSdan }
888385becfSdan
898385becfSdan /*
908385becfSdan ** Allocate a mutex.
918385becfSdan */
checkMutexAlloc(int iType)928385becfSdan static sqlite3_mutex *checkMutexAlloc(int iType){
938385becfSdan static CheckMutex staticMutexes[] = {
948385becfSdan {2, 0}, {3, 0}, {4, 0}, {5, 0},
958385becfSdan {6, 0}, {7, 0}, {8, 0}, {9, 0},
968385becfSdan {10, 0}, {11, 0}, {12, 0}, {13, 0}
978385becfSdan };
988385becfSdan CheckMutex *p = 0;
998385becfSdan
1008385becfSdan assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 );
1018385becfSdan if( iType<2 ){
1028385becfSdan p = sqlite3MallocZero(sizeof(CheckMutex));
1038385becfSdan if( p==0 ) return 0;
1048385becfSdan p->iType = iType;
1058385becfSdan }else{
1068385becfSdan #ifdef SQLITE_ENABLE_API_ARMOR
1078385becfSdan if( iType-2>=ArraySize(staticMutexes) ){
1088385becfSdan (void)SQLITE_MISUSE_BKPT;
1098385becfSdan return 0;
1108385becfSdan }
1118385becfSdan #endif
1128385becfSdan p = &staticMutexes[iType-2];
1138385becfSdan }
1148385becfSdan
1158385becfSdan if( p->mutex==0 ){
1168385becfSdan p->mutex = pGlobalMutexMethods->xMutexAlloc(iType);
1178385becfSdan if( p->mutex==0 ){
1188385becfSdan if( iType<2 ){
1198385becfSdan sqlite3_free(p);
1208385becfSdan }
1218385becfSdan p = 0;
1228385becfSdan }
1238385becfSdan }
1248385becfSdan
1258385becfSdan return (sqlite3_mutex*)p;
1268385becfSdan }
1278385becfSdan
1288385becfSdan /*
1298385becfSdan ** Free a mutex.
1308385becfSdan */
checkMutexFree(sqlite3_mutex * p)1318385becfSdan static void checkMutexFree(sqlite3_mutex *p){
132a90a2d58Sdan assert( SQLITE_MUTEX_RECURSIVE<2 );
133a90a2d58Sdan assert( SQLITE_MUTEX_FAST<2 );
134a90a2d58Sdan assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
135a90a2d58Sdan
1368385becfSdan #if SQLITE_ENABLE_API_ARMOR
1378adb25abSdan if( ((CheckMutex*)p)->iType<2 )
1388385becfSdan #endif
1398385becfSdan {
1408385becfSdan CheckMutex *pCheck = (CheckMutex*)p;
1418385becfSdan pGlobalMutexMethods->xMutexFree(pCheck->mutex);
1428385becfSdan sqlite3_free(pCheck);
1438385becfSdan }
1448385becfSdan #ifdef SQLITE_ENABLE_API_ARMOR
1458385becfSdan else{
1468385becfSdan (void)SQLITE_MISUSE_BKPT;
1478385becfSdan }
1488385becfSdan #endif
1498385becfSdan }
1508385becfSdan
1518385becfSdan /*
1528385becfSdan ** Enter the mutex.
1538385becfSdan */
checkMutexEnter(sqlite3_mutex * p)1548385becfSdan static void checkMutexEnter(sqlite3_mutex *p){
1558385becfSdan CheckMutex *pCheck = (CheckMutex*)p;
156a90a2d58Sdan if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){
1578385becfSdan if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
1588385becfSdan return;
1598385becfSdan }
1608385becfSdan sqlite3_log(SQLITE_MISUSE,
1618385becfSdan "illegal multi-threaded access to database connection"
1628385becfSdan );
1638385becfSdan }
1648385becfSdan pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
1658385becfSdan }
1668385becfSdan
1678385becfSdan /*
1688385becfSdan ** Enter the mutex (do not block).
1698385becfSdan */
checkMutexTry(sqlite3_mutex * p)1708385becfSdan static int checkMutexTry(sqlite3_mutex *p){
1718385becfSdan CheckMutex *pCheck = (CheckMutex*)p;
1728385becfSdan return pGlobalMutexMethods->xMutexTry(pCheck->mutex);
1738385becfSdan }
1748385becfSdan
1758385becfSdan /*
1768385becfSdan ** Leave the mutex.
1778385becfSdan */
checkMutexLeave(sqlite3_mutex * p)1788385becfSdan static void checkMutexLeave(sqlite3_mutex *p){
1798385becfSdan CheckMutex *pCheck = (CheckMutex*)p;
1808385becfSdan pGlobalMutexMethods->xMutexLeave(pCheck->mutex);
1818385becfSdan }
1828385becfSdan
multiThreadedCheckMutex(void)1838385becfSdan sqlite3_mutex_methods const *multiThreadedCheckMutex(void){
1848385becfSdan static const sqlite3_mutex_methods sMutex = {
1858385becfSdan checkMutexInit,
1868385becfSdan checkMutexEnd,
1878385becfSdan checkMutexAlloc,
1888385becfSdan checkMutexFree,
1898385becfSdan checkMutexEnter,
1908385becfSdan checkMutexTry,
1918385becfSdan checkMutexLeave,
1928385becfSdan #ifdef SQLITE_DEBUG
1938385becfSdan checkMutexHeld,
1948385becfSdan checkMutexNotheld
1958385becfSdan #else
1968385becfSdan 0,
1978385becfSdan 0
1988385becfSdan #endif
1998385becfSdan };
2008385becfSdan return &sMutex;
2018385becfSdan }
2028385becfSdan
2038385becfSdan /*
2048385becfSdan ** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as
2058385becfSdan ** one on which there should be no contention.
2068385becfSdan */
sqlite3MutexWarnOnContention(sqlite3_mutex * p)2078385becfSdan void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
2088385becfSdan if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){
2098385becfSdan CheckMutex *pCheck = (CheckMutex*)p;
2108385becfSdan assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE );
211a90a2d58Sdan pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
2128385becfSdan }
2138385becfSdan }
2148385becfSdan #endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
2158385becfSdan
2166d2ab0e4Sdanielk1977 /*
2176d2ab0e4Sdanielk1977 ** Initialize the mutex system.
2186d2ab0e4Sdanielk1977 */
sqlite3MutexInit(void)219d025174fSdanielk1977 int sqlite3MutexInit(void){
22059f8c08eSdanielk1977 int rc = SQLITE_OK;
221075c23afSdanielk1977 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
222b2e36222Sdanielk1977 /* If the xMutexAlloc method has not been set, then the user did not
223b2e36222Sdanielk1977 ** install a mutex implementation via sqlite3_config() prior to
224b2e36222Sdanielk1977 ** sqlite3_initialize() being called. This block copies pointers to
225075c23afSdanielk1977 ** the default implementation into the sqlite3GlobalConfig structure.
226b2e36222Sdanielk1977 */
227558814f8Sdan sqlite3_mutex_methods const *pFrom;
228e64ca7baSdrh sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
2296d2ab0e4Sdanielk1977
23092d76523Sdrh if( sqlite3GlobalConfig.bCoreMutex ){
2318385becfSdan #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
2328385becfSdan pFrom = multiThreadedCheckMutex();
2338385becfSdan #else
23492d76523Sdrh pFrom = sqlite3DefaultMutex();
2358385becfSdan #endif
23692d76523Sdrh }else{
23792d76523Sdrh pFrom = sqlite3NoopMutex();
23892d76523Sdrh }
239f5ed7ad6Sdrh pTo->xMutexInit = pFrom->xMutexInit;
240f5ed7ad6Sdrh pTo->xMutexEnd = pFrom->xMutexEnd;
241f5ed7ad6Sdrh pTo->xMutexFree = pFrom->xMutexFree;
242f5ed7ad6Sdrh pTo->xMutexEnter = pFrom->xMutexEnter;
243f5ed7ad6Sdrh pTo->xMutexTry = pFrom->xMutexTry;
244f5ed7ad6Sdrh pTo->xMutexLeave = pFrom->xMutexLeave;
245f5ed7ad6Sdrh pTo->xMutexHeld = pFrom->xMutexHeld;
246f5ed7ad6Sdrh pTo->xMutexNotheld = pFrom->xMutexNotheld;
2476081c1dbSdrh sqlite3MemoryBarrier();
248e64ca7baSdrh pTo->xMutexAlloc = pFrom->xMutexAlloc;
2496d2ab0e4Sdanielk1977 }
25004abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexInit );
251075c23afSdanielk1977 rc = sqlite3GlobalConfig.mutex.xMutexInit();
2526d2ab0e4Sdanielk1977
253fe5bdb36Sdrh #ifdef SQLITE_DEBUG
254fe5bdb36Sdrh GLOBAL(int, mutexIsInit) = 1;
255fe5bdb36Sdrh #endif
256fe5bdb36Sdrh
257*ffd3fd0cSdrh sqlite3MemoryBarrier();
2586d2ab0e4Sdanielk1977 return rc;
2596d2ab0e4Sdanielk1977 }
2606d2ab0e4Sdanielk1977
2616d2ab0e4Sdanielk1977 /*
2626d2ab0e4Sdanielk1977 ** Shutdown the mutex system. This call frees resources allocated by
263d025174fSdanielk1977 ** sqlite3MutexInit().
2646d2ab0e4Sdanielk1977 */
sqlite3MutexEnd(void)265d025174fSdanielk1977 int sqlite3MutexEnd(void){
2666d2ab0e4Sdanielk1977 int rc = SQLITE_OK;
2670a549071Sdanielk1977 if( sqlite3GlobalConfig.mutex.xMutexEnd ){
268075c23afSdanielk1977 rc = sqlite3GlobalConfig.mutex.xMutexEnd();
2690a549071Sdanielk1977 }
270fe5bdb36Sdrh
271fe5bdb36Sdrh #ifdef SQLITE_DEBUG
272fe5bdb36Sdrh GLOBAL(int, mutexIsInit) = 0;
273fe5bdb36Sdrh #endif
274fe5bdb36Sdrh
2756d2ab0e4Sdanielk1977 return rc;
2766d2ab0e4Sdanielk1977 }
2776d2ab0e4Sdanielk1977
2786d2ab0e4Sdanielk1977 /*
2796d2ab0e4Sdanielk1977 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
2806d2ab0e4Sdanielk1977 */
sqlite3_mutex_alloc(int id)2816d2ab0e4Sdanielk1977 sqlite3_mutex *sqlite3_mutex_alloc(int id){
282bc10d773Sdanielk1977 #ifndef SQLITE_OMIT_AUTOINIT
283d42d0bedSdrh if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
2842d8ad51cSmistachkin if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
285bc10d773Sdanielk1977 #endif
28604abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
287075c23afSdanielk1977 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
2886d2ab0e4Sdanielk1977 }
2896d2ab0e4Sdanielk1977
sqlite3MutexAlloc(int id)29059f8c08eSdanielk1977 sqlite3_mutex *sqlite3MutexAlloc(int id){
291075c23afSdanielk1977 if( !sqlite3GlobalConfig.bCoreMutex ){
29259f8c08eSdanielk1977 return 0;
29359f8c08eSdanielk1977 }
294fe5bdb36Sdrh assert( GLOBAL(int, mutexIsInit) );
29504abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
296075c23afSdanielk1977 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
29759f8c08eSdanielk1977 }
29859f8c08eSdanielk1977
2996d2ab0e4Sdanielk1977 /*
3006d2ab0e4Sdanielk1977 ** Free a dynamic mutex.
3016d2ab0e4Sdanielk1977 */
sqlite3_mutex_free(sqlite3_mutex * p)3026d2ab0e4Sdanielk1977 void sqlite3_mutex_free(sqlite3_mutex *p){
3036d2ab0e4Sdanielk1977 if( p ){
30404abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexFree );
305075c23afSdanielk1977 sqlite3GlobalConfig.mutex.xMutexFree(p);
3066d2ab0e4Sdanielk1977 }
3076d2ab0e4Sdanielk1977 }
3086d2ab0e4Sdanielk1977
3096d2ab0e4Sdanielk1977 /*
3106d2ab0e4Sdanielk1977 ** Obtain the mutex p. If some other thread already has the mutex, block
3116d2ab0e4Sdanielk1977 ** until it can be obtained.
3126d2ab0e4Sdanielk1977 */
sqlite3_mutex_enter(sqlite3_mutex * p)3136d2ab0e4Sdanielk1977 void sqlite3_mutex_enter(sqlite3_mutex *p){
3146d2ab0e4Sdanielk1977 if( p ){
31504abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexEnter );
316075c23afSdanielk1977 sqlite3GlobalConfig.mutex.xMutexEnter(p);
3176d2ab0e4Sdanielk1977 }
3186d2ab0e4Sdanielk1977 }
3196d2ab0e4Sdanielk1977
3206d2ab0e4Sdanielk1977 /*
3216d2ab0e4Sdanielk1977 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
3226d2ab0e4Sdanielk1977 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
3236d2ab0e4Sdanielk1977 */
sqlite3_mutex_try(sqlite3_mutex * p)3246d2ab0e4Sdanielk1977 int sqlite3_mutex_try(sqlite3_mutex *p){
3256d2ab0e4Sdanielk1977 int rc = SQLITE_OK;
3266d2ab0e4Sdanielk1977 if( p ){
32704abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexTry );
328075c23afSdanielk1977 return sqlite3GlobalConfig.mutex.xMutexTry(p);
3296d2ab0e4Sdanielk1977 }
3306d2ab0e4Sdanielk1977 return rc;
3316d2ab0e4Sdanielk1977 }
3326d2ab0e4Sdanielk1977
3336d2ab0e4Sdanielk1977 /*
3346d2ab0e4Sdanielk1977 ** The sqlite3_mutex_leave() routine exits a mutex that was previously
3356d2ab0e4Sdanielk1977 ** entered by the same thread. The behavior is undefined if the mutex
3366d2ab0e4Sdanielk1977 ** is not currently entered. If a NULL pointer is passed as an argument
3376d2ab0e4Sdanielk1977 ** this function is a no-op.
3386d2ab0e4Sdanielk1977 */
sqlite3_mutex_leave(sqlite3_mutex * p)3396d2ab0e4Sdanielk1977 void sqlite3_mutex_leave(sqlite3_mutex *p){
3406d2ab0e4Sdanielk1977 if( p ){
34104abf087Smistachkin assert( sqlite3GlobalConfig.mutex.xMutexLeave );
342075c23afSdanielk1977 sqlite3GlobalConfig.mutex.xMutexLeave(p);
3436d2ab0e4Sdanielk1977 }
3446d2ab0e4Sdanielk1977 }
3456d2ab0e4Sdanielk1977
3466d2ab0e4Sdanielk1977 #ifndef NDEBUG
3476d2ab0e4Sdanielk1977 /*
3486d2ab0e4Sdanielk1977 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
3496d2ab0e4Sdanielk1977 ** intended for use inside assert() statements.
3506d2ab0e4Sdanielk1977 */
sqlite3_mutex_held(sqlite3_mutex * p)3516d2ab0e4Sdanielk1977 int sqlite3_mutex_held(sqlite3_mutex *p){
35204abf087Smistachkin assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
353075c23afSdanielk1977 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
3546d2ab0e4Sdanielk1977 }
sqlite3_mutex_notheld(sqlite3_mutex * p)3556d2ab0e4Sdanielk1977 int sqlite3_mutex_notheld(sqlite3_mutex *p){
35604abf087Smistachkin assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
357075c23afSdanielk1977 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
3586d2ab0e4Sdanielk1977 }
3596d2ab0e4Sdanielk1977 #endif
3606d2ab0e4Sdanielk1977
361e4c88c0cSdrh #endif /* !defined(SQLITE_MUTEX_OMIT) */
362