xref: /sqlite-3.40.0/src/mutex.c (revision 8385becf)
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 #include "sqliteInt.h"
17 
18 #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
19 /*
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 */
24 static SQLITE_WSD int mutexIsInit = 0;
25 #endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */
26 
27 
28 #ifndef SQLITE_MUTEX_OMIT
29 
30 #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
31 /*
32 ** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
33 ** the implementation of a wrapper around the system default mutex
34 ** implementation (sqlite3DefaultMutex()).
35 **
36 ** Most calls are passed directly through to the underlying default
37 ** mutex implementation. Except, if a mutex is configured by calling
38 ** sqlite3MutexWarnOnContention() on it, then if contention is ever
39 ** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
40 **
41 ** This type of mutex is used as the database handle mutex when testing
42 ** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
43 */
44 
45 /*
46 ** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
47 ** is defined.
48 */
49 typedef struct CheckMutex CheckMutex;
50 struct CheckMutex {
51   int iType;
52   sqlite3_mutex *mutex;
53 };
54 
55 /*
56 ** Pointer to real mutex methods object used by the CheckMutex
57 ** implementation. Set by checkMutexInit().
58 */
59 static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
60 
61 #ifdef SQLITE_DEBUG
62 static int checkMutexHeld(sqlite3_mutex *p){
63   return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex);
64 }
65 static int checkMutexNotheld(sqlite3_mutex *p){
66   return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex);
67 }
68 #endif
69 
70 /*
71 ** Initialize and deinitialize the mutex subsystem.
72 */
73 static int checkMutexInit(void){
74   pGlobalMutexMethods = sqlite3DefaultMutex();
75   return SQLITE_OK;
76 }
77 static int checkMutexEnd(void){
78   pGlobalMutexMethods = 0;
79   return SQLITE_OK;
80 }
81 
82 /*
83 ** Allocate a mutex.
84 */
85 static sqlite3_mutex *checkMutexAlloc(int iType){
86   static CheckMutex staticMutexes[] = {
87     {2, 0}, {3, 0}, {4, 0}, {5, 0},
88     {6, 0}, {7, 0}, {8, 0}, {9, 0},
89     {10, 0}, {11, 0}, {12, 0}, {13, 0}
90   };
91   CheckMutex *p = 0;
92 
93   assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 );
94   if( iType<2 ){
95     p = sqlite3MallocZero(sizeof(CheckMutex));
96     if( p==0 ) return 0;
97     p->iType = iType;
98   }else{
99 #ifdef SQLITE_ENABLE_API_ARMOR
100     if( iType-2>=ArraySize(staticMutexes) ){
101       (void)SQLITE_MISUSE_BKPT;
102       return 0;
103     }
104 #endif
105     p = &staticMutexes[iType-2];
106   }
107 
108   if( p->mutex==0 ){
109     p->mutex = pGlobalMutexMethods->xMutexAlloc(iType);
110     if( p->mutex==0 ){
111       if( iType<2 ){
112         sqlite3_free(p);
113       }
114       p = 0;
115     }
116   }
117 
118   return (sqlite3_mutex*)p;
119 }
120 
121 /*
122 ** Free a mutex.
123 */
124 static void checkMutexFree(sqlite3_mutex *p){
125 #if SQLITE_ENABLE_API_ARMOR
126   if( p->iType<2 ){
127 #endif
128   {
129     CheckMutex *pCheck = (CheckMutex*)p;
130     pGlobalMutexMethods->xMutexFree(pCheck->mutex);
131     sqlite3_free(pCheck);
132   }
133 #ifdef SQLITE_ENABLE_API_ARMOR
134   else{
135     (void)SQLITE_MISUSE_BKPT;
136   }
137 #endif
138 }
139 
140 /*
141 ** Enter the mutex.
142 */
143 static void checkMutexEnter(sqlite3_mutex *p){
144   CheckMutex *pCheck = (CheckMutex*)p;
145   if( pCheck->iType<0 ){
146     if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
147       return;
148     }
149     sqlite3_log(SQLITE_MISUSE,
150         "illegal multi-threaded access to database connection"
151     );
152   }
153   pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
154 }
155 
156 /*
157 ** Enter the mutex (do not block).
158 */
159 static int checkMutexTry(sqlite3_mutex *p){
160   CheckMutex *pCheck = (CheckMutex*)p;
161   return pGlobalMutexMethods->xMutexTry(pCheck->mutex);
162 }
163 
164 /*
165 ** Leave the mutex.
166 */
167 static void checkMutexLeave(sqlite3_mutex *p){
168   CheckMutex *pCheck = (CheckMutex*)p;
169   pGlobalMutexMethods->xMutexLeave(pCheck->mutex);
170 }
171 
172 sqlite3_mutex_methods const *multiThreadedCheckMutex(void){
173   static const sqlite3_mutex_methods sMutex = {
174     checkMutexInit,
175     checkMutexEnd,
176     checkMutexAlloc,
177     checkMutexFree,
178     checkMutexEnter,
179     checkMutexTry,
180     checkMutexLeave,
181 #ifdef SQLITE_DEBUG
182     checkMutexHeld,
183     checkMutexNotheld
184 #else
185     0,
186     0
187 #endif
188   };
189   return &sMutex;
190 }
191 
192 /*
193 ** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as
194 ** one on which there should be no contention.
195 */
196 void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
197   if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){
198     CheckMutex *pCheck = (CheckMutex*)p;
199     assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE );
200     pCheck->iType = -1;
201   }
202 }
203 #endif   /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
204 
205 /*
206 ** Initialize the mutex system.
207 */
208 int sqlite3MutexInit(void){
209   int rc = SQLITE_OK;
210   if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
211     /* If the xMutexAlloc method has not been set, then the user did not
212     ** install a mutex implementation via sqlite3_config() prior to
213     ** sqlite3_initialize() being called. This block copies pointers to
214     ** the default implementation into the sqlite3GlobalConfig structure.
215     */
216     sqlite3_mutex_methods const *pFrom;
217     sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
218 
219     if( sqlite3GlobalConfig.bCoreMutex ){
220 #ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
221       pFrom = multiThreadedCheckMutex();
222 #else
223       pFrom = sqlite3DefaultMutex();
224 #endif
225     }else{
226       pFrom = sqlite3NoopMutex();
227     }
228     pTo->xMutexInit = pFrom->xMutexInit;
229     pTo->xMutexEnd = pFrom->xMutexEnd;
230     pTo->xMutexFree = pFrom->xMutexFree;
231     pTo->xMutexEnter = pFrom->xMutexEnter;
232     pTo->xMutexTry = pFrom->xMutexTry;
233     pTo->xMutexLeave = pFrom->xMutexLeave;
234     pTo->xMutexHeld = pFrom->xMutexHeld;
235     pTo->xMutexNotheld = pFrom->xMutexNotheld;
236     sqlite3MemoryBarrier();
237     pTo->xMutexAlloc = pFrom->xMutexAlloc;
238   }
239   assert( sqlite3GlobalConfig.mutex.xMutexInit );
240   rc = sqlite3GlobalConfig.mutex.xMutexInit();
241 
242 #ifdef SQLITE_DEBUG
243   GLOBAL(int, mutexIsInit) = 1;
244 #endif
245 
246   return rc;
247 }
248 
249 /*
250 ** Shutdown the mutex system. This call frees resources allocated by
251 ** sqlite3MutexInit().
252 */
253 int sqlite3MutexEnd(void){
254   int rc = SQLITE_OK;
255   if( sqlite3GlobalConfig.mutex.xMutexEnd ){
256     rc = sqlite3GlobalConfig.mutex.xMutexEnd();
257   }
258 
259 #ifdef SQLITE_DEBUG
260   GLOBAL(int, mutexIsInit) = 0;
261 #endif
262 
263   return rc;
264 }
265 
266 /*
267 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
268 */
269 sqlite3_mutex *sqlite3_mutex_alloc(int id){
270 #ifndef SQLITE_OMIT_AUTOINIT
271   if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
272   if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
273 #endif
274   assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
275   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
276 }
277 
278 sqlite3_mutex *sqlite3MutexAlloc(int id){
279   if( !sqlite3GlobalConfig.bCoreMutex ){
280     return 0;
281   }
282   assert( GLOBAL(int, mutexIsInit) );
283   assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
284   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
285 }
286 
287 /*
288 ** Free a dynamic mutex.
289 */
290 void sqlite3_mutex_free(sqlite3_mutex *p){
291   if( p ){
292     assert( sqlite3GlobalConfig.mutex.xMutexFree );
293     sqlite3GlobalConfig.mutex.xMutexFree(p);
294   }
295 }
296 
297 /*
298 ** Obtain the mutex p. If some other thread already has the mutex, block
299 ** until it can be obtained.
300 */
301 void sqlite3_mutex_enter(sqlite3_mutex *p){
302   if( p ){
303     assert( sqlite3GlobalConfig.mutex.xMutexEnter );
304     sqlite3GlobalConfig.mutex.xMutexEnter(p);
305   }
306 }
307 
308 /*
309 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
310 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
311 */
312 int sqlite3_mutex_try(sqlite3_mutex *p){
313   int rc = SQLITE_OK;
314   if( p ){
315     assert( sqlite3GlobalConfig.mutex.xMutexTry );
316     return sqlite3GlobalConfig.mutex.xMutexTry(p);
317   }
318   return rc;
319 }
320 
321 /*
322 ** The sqlite3_mutex_leave() routine exits a mutex that was previously
323 ** entered by the same thread.  The behavior is undefined if the mutex
324 ** is not currently entered. If a NULL pointer is passed as an argument
325 ** this function is a no-op.
326 */
327 void sqlite3_mutex_leave(sqlite3_mutex *p){
328   if( p ){
329     assert( sqlite3GlobalConfig.mutex.xMutexLeave );
330     sqlite3GlobalConfig.mutex.xMutexLeave(p);
331   }
332 }
333 
334 #ifndef NDEBUG
335 /*
336 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
337 ** intended for use inside assert() statements.
338 */
339 int sqlite3_mutex_held(sqlite3_mutex *p){
340   assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
341   return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
342 }
343 int sqlite3_mutex_notheld(sqlite3_mutex *p){
344   assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
345   return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
346 }
347 #endif
348 
349 #endif /* !defined(SQLITE_MUTEX_OMIT) */
350 
351