xref: /sqlite-3.40.0/src/mutex.c (revision a3f06598)
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.30 2009/02/17 16:29:11 danielk1977 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   if( sqlite3GlobalConfig.mutex.xMutexEnd ){
71     rc = sqlite3GlobalConfig.mutex.xMutexEnd();
72   }
73   return rc;
74 }
75 
76 /*
77 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
78 */
79 sqlite3_mutex *sqlite3_mutex_alloc(int id){
80 #ifndef SQLITE_OMIT_AUTOINIT
81   if( sqlite3_initialize() ) return 0;
82 #endif
83   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
84 }
85 
86 sqlite3_mutex *sqlite3MutexAlloc(int id){
87   if( !sqlite3GlobalConfig.bCoreMutex ){
88     return 0;
89   }
90   return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
91 }
92 
93 /*
94 ** Free a dynamic mutex.
95 */
96 void sqlite3_mutex_free(sqlite3_mutex *p){
97   if( p ){
98     sqlite3GlobalConfig.mutex.xMutexFree(p);
99   }
100 }
101 
102 /*
103 ** Obtain the mutex p. If some other thread already has the mutex, block
104 ** until it can be obtained.
105 */
106 void sqlite3_mutex_enter(sqlite3_mutex *p){
107   if( p ){
108     sqlite3GlobalConfig.mutex.xMutexEnter(p);
109   }
110 }
111 
112 /*
113 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
114 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
115 */
116 int sqlite3_mutex_try(sqlite3_mutex *p){
117   int rc = SQLITE_OK;
118   if( p ){
119     return sqlite3GlobalConfig.mutex.xMutexTry(p);
120   }
121   return rc;
122 }
123 
124 /*
125 ** The sqlite3_mutex_leave() routine exits a mutex that was previously
126 ** entered by the same thread.  The behavior is undefined if the mutex
127 ** is not currently entered. If a NULL pointer is passed as an argument
128 ** this function is a no-op.
129 */
130 void sqlite3_mutex_leave(sqlite3_mutex *p){
131   if( p ){
132     sqlite3GlobalConfig.mutex.xMutexLeave(p);
133   }
134 }
135 
136 #ifndef NDEBUG
137 /*
138 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
139 ** intended for use inside assert() statements.
140 */
141 int sqlite3_mutex_held(sqlite3_mutex *p){
142   return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
143 }
144 int sqlite3_mutex_notheld(sqlite3_mutex *p){
145   return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
146 }
147 #endif
148 
149 #endif /* SQLITE_OMIT_MUTEX */
150