|
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 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 */ |