blob: a2e4e6387a987c5f40548f96b3a8f5a6d120c94f [file] [log] [blame]
drh90f6a5b2007-08-15 13:04:54 +00001/*
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*************************************************************************
drh437b9012007-08-28 16:34:42 +000012** This file contains the C functions that implement mutexes.
drh90f6a5b2007-08-15 13:04:54 +000013**
drh18472fa2008-10-07 15:25:48 +000014** This file contains code that is common across all mutex implementations.
drh90f6a5b2007-08-15 13:04:54 +000015*/
16#include "sqliteInt.h"
17
drhd0bc5d22009-09-10 22:30:53 +000018#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
drhfe5bdb32009-09-10 17:45:00 +000019/*
20** For debugging purposes, record when the mutex subsystem is initialized
21** and uninitialized so that we can assert() if there is an attempt to
22** allocate a mutex while the system is uninitialized.
23*/
24static SQLITE_WSD int mutexIsInit = 0;
25#endif /* SQLITE_DEBUG */
26
27
drh18472fa2008-10-07 15:25:48 +000028#ifndef SQLITE_MUTEX_OMIT
danielk19776d2ab0e2008-06-17 17:21:18 +000029/*
30** Initialize the mutex system.
31*/
danielk1977d0251742008-06-18 18:57:42 +000032int sqlite3MutexInit(void){
danielk197759f8c082008-06-18 17:09:10 +000033 int rc = SQLITE_OK;
drh92d76522010-05-05 00:05:24 +000034 if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
35 /* If the xMutexAlloc method has not been set, then the user did not
36 ** install a mutex implementation via sqlite3_config() prior to
37 ** sqlite3_initialize() being called. This block copies pointers to
38 ** the default implementation into the sqlite3GlobalConfig structure.
39 */
dan558814f2010-06-02 05:53:53 +000040 sqlite3_mutex_methods const *pFrom;
drh92d76522010-05-05 00:05:24 +000041 sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
drhe64ca7b2009-07-16 18:21:17 +000042
drh92d76522010-05-05 00:05:24 +000043 if( sqlite3GlobalConfig.bCoreMutex ){
44 pFrom = sqlite3DefaultMutex();
45 }else{
46 pFrom = sqlite3NoopMutex();
danielk19776d2ab0e2008-06-17 17:21:18 +000047 }
drhf5ed7ad2015-06-15 14:43:25 +000048 pTo->xMutexInit = pFrom->xMutexInit;
49 pTo->xMutexEnd = pFrom->xMutexEnd;
50 pTo->xMutexFree = pFrom->xMutexFree;
51 pTo->xMutexEnter = pFrom->xMutexEnter;
52 pTo->xMutexTry = pFrom->xMutexTry;
53 pTo->xMutexLeave = pFrom->xMutexLeave;
54 pTo->xMutexHeld = pFrom->xMutexHeld;
55 pTo->xMutexNotheld = pFrom->xMutexNotheld;
drh6081c1d2015-09-06 02:51:04 +000056 sqlite3MemoryBarrier();
drh92d76522010-05-05 00:05:24 +000057 pTo->xMutexAlloc = pFrom->xMutexAlloc;
danielk19776d2ab0e2008-06-17 17:21:18 +000058 }
drh92d76522010-05-05 00:05:24 +000059 rc = sqlite3GlobalConfig.mutex.xMutexInit();
danielk19776d2ab0e2008-06-17 17:21:18 +000060
drhfe5bdb32009-09-10 17:45:00 +000061#ifdef SQLITE_DEBUG
62 GLOBAL(int, mutexIsInit) = 1;
63#endif
64
danielk19776d2ab0e2008-06-17 17:21:18 +000065 return rc;
66}
67
68/*
69** Shutdown the mutex system. This call frees resources allocated by
danielk1977d0251742008-06-18 18:57:42 +000070** sqlite3MutexInit().
danielk19776d2ab0e2008-06-17 17:21:18 +000071*/
danielk1977d0251742008-06-18 18:57:42 +000072int sqlite3MutexEnd(void){
danielk19776d2ab0e2008-06-17 17:21:18 +000073 int rc = SQLITE_OK;
danielk19770a549072009-02-17 16:29:10 +000074 if( sqlite3GlobalConfig.mutex.xMutexEnd ){
75 rc = sqlite3GlobalConfig.mutex.xMutexEnd();
76 }
drhfe5bdb32009-09-10 17:45:00 +000077
78#ifdef SQLITE_DEBUG
79 GLOBAL(int, mutexIsInit) = 0;
80#endif
81
danielk19776d2ab0e2008-06-17 17:21:18 +000082 return rc;
83}
84
85/*
86** Retrieve a pointer to a static mutex or allocate a new dynamic one.
87*/
88sqlite3_mutex *sqlite3_mutex_alloc(int id){
danielk1977bc10d772008-06-18 18:08:39 +000089#ifndef SQLITE_OMIT_AUTOINIT
drhd42d0be2014-07-30 21:10:12 +000090 if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
mistachkin2d8ad512014-10-27 22:06:21 +000091 if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
danielk1977bc10d772008-06-18 18:08:39 +000092#endif
danielk1977075c23a2008-09-01 18:34:20 +000093 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
danielk19776d2ab0e2008-06-17 17:21:18 +000094}
95
danielk197759f8c082008-06-18 17:09:10 +000096sqlite3_mutex *sqlite3MutexAlloc(int id){
danielk1977075c23a2008-09-01 18:34:20 +000097 if( !sqlite3GlobalConfig.bCoreMutex ){
danielk197759f8c082008-06-18 17:09:10 +000098 return 0;
99 }
drhfe5bdb32009-09-10 17:45:00 +0000100 assert( GLOBAL(int, mutexIsInit) );
danielk1977075c23a2008-09-01 18:34:20 +0000101 return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
danielk197759f8c082008-06-18 17:09:10 +0000102}
103
danielk19776d2ab0e2008-06-17 17:21:18 +0000104/*
105** Free a dynamic mutex.
106*/
107void sqlite3_mutex_free(sqlite3_mutex *p){
108 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000109 sqlite3GlobalConfig.mutex.xMutexFree(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000110 }
111}
112
113/*
114** Obtain the mutex p. If some other thread already has the mutex, block
115** until it can be obtained.
116*/
117void sqlite3_mutex_enter(sqlite3_mutex *p){
118 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000119 sqlite3GlobalConfig.mutex.xMutexEnter(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000120 }
121}
122
123/*
124** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
125** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
126*/
127int sqlite3_mutex_try(sqlite3_mutex *p){
128 int rc = SQLITE_OK;
129 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000130 return sqlite3GlobalConfig.mutex.xMutexTry(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000131 }
132 return rc;
133}
134
135/*
136** The sqlite3_mutex_leave() routine exits a mutex that was previously
137** entered by the same thread. The behavior is undefined if the mutex
138** is not currently entered. If a NULL pointer is passed as an argument
139** this function is a no-op.
140*/
141void sqlite3_mutex_leave(sqlite3_mutex *p){
142 if( p ){
danielk1977075c23a2008-09-01 18:34:20 +0000143 sqlite3GlobalConfig.mutex.xMutexLeave(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000144 }
145}
146
147#ifndef NDEBUG
148/*
149** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
150** intended for use inside assert() statements.
151*/
152int sqlite3_mutex_held(sqlite3_mutex *p){
danielk1977075c23a2008-09-01 18:34:20 +0000153 return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000154}
155int sqlite3_mutex_notheld(sqlite3_mutex *p){
danielk1977075c23a2008-09-01 18:34:20 +0000156 return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
danielk19776d2ab0e2008-06-17 17:21:18 +0000157}
158#endif
159
drhe4c88c02012-01-04 12:57:45 +0000160#endif /* !defined(SQLITE_MUTEX_OMIT) */