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