xref: /sqlite-3.40.0/src/mutex.c (revision d025174f)
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 ** The implementation in this file does not provide any mutual
15 ** exclusion and is thus suitable for use only in applications
16 ** that use SQLite in a single thread.  But this implementation
17 ** does do a lot of error checking on mutexes to make sure they
18 ** are called correctly and at appropriate times.  Hence, this
19 ** implementation is suitable for testing.
20 ** debugging purposes
21 **
22 ** $Id: mutex.c,v 1.26 2008/06/18 18:57:42 danielk1977 Exp $
23 */
24 #include "sqliteInt.h"
25 
26 #ifndef SQLITE_MUTEX_NOOP
27 /*
28 ** Initialize the mutex system.
29 */
30 int sqlite3MutexInit(void){
31   int rc = SQLITE_OK;
32   if( sqlite3Config.bCoreMutex ){
33     if( !sqlite3Config.mutex.xMutexAlloc ){
34       /* If the xMutexAlloc method has not been set, then the user did not
35       ** install a mutex implementation via sqlite3_config() prior to
36       ** sqlite3_initialize() being called. This block copies pointers to
37       ** the default implementation into the sqlite3Config structure.
38       **
39       ** The danger is that although sqlite3_config() is not a threadsafe
40       ** API, sqlite3_initialize() is, and so multiple threads may be
41       ** attempting to run this function simultaneously. To guard write
42       ** access to the sqlite3Config structure, the 'MASTER' static mutex
43       ** is obtained before modifying it.
44       */
45       sqlite3_mutex_methods *p = sqlite3DefaultMutex();
46       sqlite3_mutex *pMaster = 0;
47 
48       rc = p->xMutexInit();
49       if( rc==SQLITE_OK ){
50         pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
51         assert(pMaster);
52         p->xMutexEnter(pMaster);
53         assert( sqlite3Config.mutex.xMutexAlloc==0
54              || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc
55         );
56         if( !sqlite3Config.mutex.xMutexAlloc ){
57           sqlite3Config.mutex = *p;
58         }
59         p->xMutexLeave(pMaster);
60       }
61     }else{
62       rc = sqlite3Config.mutex.xMutexInit();
63     }
64   }
65 
66   return rc;
67 }
68 
69 /*
70 ** Shutdown the mutex system. This call frees resources allocated by
71 ** sqlite3MutexInit().
72 */
73 int sqlite3MutexEnd(void){
74   int rc = SQLITE_OK;
75   rc = sqlite3Config.mutex.xMutexEnd();
76   return rc;
77 }
78 
79 /*
80 ** Retrieve a pointer to a static mutex or allocate a new dynamic one.
81 */
82 sqlite3_mutex *sqlite3_mutex_alloc(int id){
83 #ifndef SQLITE_OMIT_AUTOINIT
84   if( sqlite3_initialize() ) return 0;
85 #endif
86   return sqlite3Config.mutex.xMutexAlloc(id);
87 }
88 
89 sqlite3_mutex *sqlite3MutexAlloc(int id){
90   if( !sqlite3Config.bCoreMutex ){
91     return 0;
92   }
93   return sqlite3Config.mutex.xMutexAlloc(id);
94 }
95 
96 /*
97 ** Free a dynamic mutex.
98 */
99 void sqlite3_mutex_free(sqlite3_mutex *p){
100   if( p ){
101     sqlite3Config.mutex.xMutexFree(p);
102   }
103 }
104 
105 /*
106 ** Obtain the mutex p. If some other thread already has the mutex, block
107 ** until it can be obtained.
108 */
109 void sqlite3_mutex_enter(sqlite3_mutex *p){
110   if( p ){
111     sqlite3Config.mutex.xMutexEnter(p);
112   }
113 }
114 
115 /*
116 ** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
117 ** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
118 */
119 int sqlite3_mutex_try(sqlite3_mutex *p){
120   int rc = SQLITE_OK;
121   if( p ){
122     return sqlite3Config.mutex.xMutexTry(p);
123   }
124   return rc;
125 }
126 
127 /*
128 ** The sqlite3_mutex_leave() routine exits a mutex that was previously
129 ** entered by the same thread.  The behavior is undefined if the mutex
130 ** is not currently entered. If a NULL pointer is passed as an argument
131 ** this function is a no-op.
132 */
133 void sqlite3_mutex_leave(sqlite3_mutex *p){
134   if( p ){
135     sqlite3Config.mutex.xMutexLeave(p);
136   }
137 }
138 
139 #ifndef NDEBUG
140 /*
141 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
142 ** intended for use inside assert() statements.
143 */
144 int sqlite3_mutex_held(sqlite3_mutex *p){
145   return p==0 || sqlite3Config.mutex.xMutexHeld(p);
146 }
147 int sqlite3_mutex_notheld(sqlite3_mutex *p){
148   return p==0 || sqlite3Config.mutex.xMutexNotheld(p);
149 }
150 #endif
151 
152 #endif
153 
154 #ifdef SQLITE_MUTEX_NOOP_DEBUG
155 /*
156 ** In this implementation, mutexes do not provide any mutual exclusion.
157 ** But the error checking is provided.  This implementation is useful
158 ** for test purposes.
159 */
160 
161 /*
162 ** The mutex object
163 */
164 struct sqlite3_mutex {
165   int id;     /* The mutex type */
166   int cnt;    /* Number of entries without a matching leave */
167 };
168 
169 /*
170 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
171 ** intended for use inside assert() statements.
172 */
173 static int noopMutexHeld(sqlite3_mutex *p){
174   return p==0 || p->cnt>0;
175 }
176 static int noopMutexNotheld(sqlite3_mutex *p){
177   return p==0 || p->cnt==0;
178 }
179 
180 /*
181 ** Initialize and deinitialize the mutex subsystem.
182 */
183 static int noopMutexInit(void){ return SQLITE_OK; }
184 static int noopMutexEnd(void){ return SQLITE_OK; }
185 
186 /*
187 ** The sqlite3_mutex_alloc() routine allocates a new
188 ** mutex and returns a pointer to it.  If it returns NULL
189 ** that means that a mutex could not be allocated.
190 */
191 static sqlite3_mutex *noopMutexAlloc(int id){
192   static sqlite3_mutex aStatic[6];
193   sqlite3_mutex *pNew = 0;
194   switch( id ){
195     case SQLITE_MUTEX_FAST:
196     case SQLITE_MUTEX_RECURSIVE: {
197       pNew = sqlite3Malloc(sizeof(*pNew));
198       if( pNew ){
199         pNew->id = id;
200         pNew->cnt = 0;
201       }
202       break;
203     }
204     default: {
205       assert( id-2 >= 0 );
206       assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) );
207       pNew = &aStatic[id-2];
208       pNew->id = id;
209       break;
210     }
211   }
212   return pNew;
213 }
214 
215 /*
216 ** This routine deallocates a previously allocated mutex.
217 */
218 static void noopMutexFree(sqlite3_mutex *p){
219   assert( p->cnt==0 );
220   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
221   sqlite3_free(p);
222 }
223 
224 /*
225 ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
226 ** to enter a mutex.  If another thread is already within the mutex,
227 ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
228 ** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
229 ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
230 ** be entered multiple times by the same thread.  In such cases the,
231 ** mutex must be exited an equal number of times before another thread
232 ** can enter.  If the same thread tries to enter any other kind of mutex
233 ** more than once, the behavior is undefined.
234 */
235 static void noopMutexEnter(sqlite3_mutex *p){
236   assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) );
237   p->cnt++;
238 }
239 static int noopMutexTry(sqlite3_mutex *p){
240   assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) );
241   p->cnt++;
242   return SQLITE_OK;
243 }
244 
245 /*
246 ** The sqlite3_mutex_leave() routine exits a mutex that was
247 ** previously entered by the same thread.  The behavior
248 ** is undefined if the mutex is not currently entered or
249 ** is not currently allocated.  SQLite will never do either.
250 */
251 static void noopMutexLeave(sqlite3_mutex *p){
252   assert( noopMutexHeld(p) );
253   p->cnt--;
254   assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) );
255 }
256 
257 sqlite3_mutex_methods *sqlite3DefaultMutex(void){
258   static sqlite3_mutex_methods sMutex = {
259     noopMutexInit,
260     noopMutexAlloc,
261     noopMutexFree,
262     noopMutexEnter,
263     noopMutexTry,
264     noopMutexLeave,
265     noopMutexEnd,
266 
267     noopMutexHeld,
268     noopMutexNotheld
269   };
270 
271   return &sMutex;
272 }
273 #endif /* SQLITE_MUTEX_NOOP_DEBUG */
274