xref: /sqlite-3.40.0/src/mutex.c (revision 18472fa7)
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 ** This file contains code that is common across all mutex implementations.
15 
16 **
17 ** $Id: mutex.c,v 1.29 2008/10/07 15:25:48 drh Exp $
18 */
19 #include "sqliteInt.h"
20 
21 #ifndef SQLITE_MUTEX_OMIT
22 /*
23 ** Initialize the mutex system.
24 */
25 int sqlite3MutexInit(void){
26   int rc = SQLITE_OK;
27   if( sqlite3GlobalConfig.bCoreMutex ){
28     if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
29       /* If the xMutexAlloc method has not been set, then the user did not
30       ** install a mutex implementation via sqlite3_config() prior to
31       ** sqlite3_initialize() being called. This block copies pointers to
32       ** the default implementation into the sqlite3GlobalConfig structure.
33       **
34       ** The danger is that although sqlite3_config() is not a threadsafe
35       ** API, sqlite3_initialize() is, and so multiple threads may be
36       ** attempting to run this function simultaneously. To guard write
37       ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex
38       ** is obtained before modifying it.
39       */
40       sqlite3_mutex_methods *p = sqlite3DefaultMutex();
41       sqlite3_mutex *pMaster = 0;
42 
43       rc = p->xMutexInit();
44       if( rc==SQLITE_OK ){
45         pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
46         assert(pMaster);
47         p->xMutexEnter(pMaster);
48         assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0
49              || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc
50         );
51         if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
52           sqlite3GlobalConfig.mutex = *p;
53         }
54         p->xMutexLeave(pMaster);
55       }
56     }else{
57       rc = sqlite3GlobalConfig.mutex.xMutexInit();
58     }
59   }
60 
61   return rc;
62 }
63 
64 /*
65 ** Shutdown the mutex system. This call frees resources allocated by
66 ** sqlite3MutexInit().
67 */
68 int sqlite3MutexEnd(void){
69   int rc = SQLITE_OK;
70   rc = sqlite3GlobalConfig.mutex.xMutexEnd();
71   return rc;
72 }
73 
74 /*
75 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
76 */
77 sqlite3_mutex *sqlite3_mutex_alloc(int id){
78 #ifndef SQLITE_OMIT_AUTOINIT
79   if( sqlite3_initialize() ) return 0;
80 #endif
81   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
82 }
83 
84 sqlite3_mutex *sqlite3MutexAlloc(int id){
85   if( !sqlite3GlobalConfig.bCoreMutex ){
86     return 0;
87   }
88   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
89 }
90 
91 /*
92 ** Free a dynamic mutex.
93 */
94 void sqlite3_mutex_free(sqlite3_mutex *p){
95   if( p ){
96     sqlite3GlobalConfig.mutex.xMutexFree(p);
97   }
98 }
99 
100 /*
101 ** Obtain the mutex p. If some other thread already has the mutex, block
102 ** until it can be obtained.
103 */
104 void sqlite3_mutex_enter(sqlite3_mutex *p){
105   if( p ){
106     sqlite3GlobalConfig.mutex.xMutexEnter(p);
107   }
108 }
109 
110 /*
111 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
112 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
113 */
114 int sqlite3_mutex_try(sqlite3_mutex *p){
115   int rc = SQLITE_OK;
116   if( p ){
117     return sqlite3GlobalConfig.mutex.xMutexTry(p);
118   }
119   return rc;
120 }
121 
122 /*
123 ** The sqlite3_mutex_leave() routine exits a mutex that was previously
124 ** entered by the same thread.  The behavior is undefined if the mutex
125 ** is not currently entered. If a NULL pointer is passed as an argument
126 ** this function is a no-op.
127 */
128 void sqlite3_mutex_leave(sqlite3_mutex *p){
129   if( p ){
130     sqlite3GlobalConfig.mutex.xMutexLeave(p);
131   }
132 }
133 
134 #ifndef NDEBUG
135 /*
136 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
137 ** intended for use inside assert() statements.
138 */
139 int sqlite3_mutex_held(sqlite3_mutex *p){
140   return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
141 }
142 int sqlite3_mutex_notheld(sqlite3_mutex *p){
143   return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
144 }
145 #endif
146 
147 #endif /* SQLITE_OMIT_MUTEX */
148