1 | /* |
2 | ** 2008 October 07 |
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 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. The routines defined |
17 | ** here are place-holders. Applications can substitute working |
18 | ** mutex routines at start-time using the |
19 | ** |
20 | ** sqlite3_config(SQLITE_CONFIG_MUTEX,...) |
21 | ** |
22 | ** interface. |
23 | ** |
24 | ** If compiled with SQLITE_DEBUG, then additional logic is inserted |
25 | ** that does error checking on mutexes to make sure they are being |
26 | ** called correctly. |
27 | */ |
28 | #include "sqliteInt.h" |
29 | |
30 | #ifndef SQLITE_MUTEX_OMIT |
31 | |
32 | #ifndef SQLITE_DEBUG |
33 | /* |
34 | ** Stub routines for all mutex methods. |
35 | ** |
36 | ** This routines provide no mutual exclusion or error checking. |
37 | */ |
38 | static int noopMutexInit(void){ return SQLITE_OK; } |
39 | static int noopMutexEnd(void){ return SQLITE_OK; } |
40 | static sqlite3_mutex *noopMutexAlloc(int id){ |
41 | UNUSED_PARAMETER(id); |
42 | return (sqlite3_mutex*)8; |
43 | } |
44 | static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } |
45 | static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } |
46 | static int noopMutexTry(sqlite3_mutex *p){ |
47 | UNUSED_PARAMETER(p); |
48 | return SQLITE_OK; |
49 | } |
50 | static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } |
51 | |
52 | sqlite3_mutex_methods const *sqlite3NoopMutex(void){ |
53 | static const sqlite3_mutex_methods sMutex = { |
54 | noopMutexInit, |
55 | noopMutexEnd, |
56 | noopMutexAlloc, |
57 | noopMutexFree, |
58 | noopMutexEnter, |
59 | noopMutexTry, |
60 | noopMutexLeave, |
61 | |
62 | 0, |
63 | 0, |
64 | }; |
65 | |
66 | return &sMutex; |
67 | } |
68 | #endif /* !SQLITE_DEBUG */ |
69 | |
70 | #ifdef SQLITE_DEBUG |
71 | /* |
72 | ** In this implementation, error checking is provided for testing |
73 | ** and debugging purposes. The mutexes still do not provide any |
74 | ** mutual exclusion. |
75 | */ |
76 | |
77 | /* |
78 | ** The mutex object |
79 | */ |
80 | typedef struct sqlite3_debug_mutex { |
81 | int id; /* The mutex type */ |
82 | int cnt; /* Number of entries without a matching leave */ |
83 | } sqlite3_debug_mutex; |
84 | |
85 | /* |
86 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are |
87 | ** intended for use inside assert() statements. |
88 | */ |
89 | static int debugMutexHeld(sqlite3_mutex *pX){ |
90 | sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; |
91 | return p==0 || p->cnt>0; |
92 | } |
93 | static int debugMutexNotheld(sqlite3_mutex *pX){ |
94 | sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; |
95 | return p==0 || p->cnt==0; |
96 | } |
97 | |
98 | /* |
99 | ** Initialize and deinitialize the mutex subsystem. |
100 | */ |
101 | static int debugMutexInit(void){ return SQLITE_OK; } |
102 | static int debugMutexEnd(void){ return SQLITE_OK; } |
103 | |
104 | /* |
105 | ** The sqlite3_mutex_alloc() routine allocates a new |
106 | ** mutex and returns a pointer to it. If it returns NULL |
107 | ** that means that a mutex could not be allocated. |
108 | */ |
109 | static sqlite3_mutex *debugMutexAlloc(int id){ |
110 | static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1]; |
111 | sqlite3_debug_mutex *pNew = 0; |
112 | switch( id ){ |
113 | case SQLITE_MUTEX_FAST: |
114 | case SQLITE_MUTEX_RECURSIVE: { |
115 | pNew = sqlite3Malloc(sizeof(*pNew)); |
116 | if( pNew ){ |
117 | pNew->id = id; |
118 | pNew->cnt = 0; |
119 | } |
120 | break; |
121 | } |
122 | default: { |
123 | #ifdef SQLITE_ENABLE_API_ARMOR |
124 | if( id-2<0 || id-2>=ArraySize(aStatic) ){ |
125 | (void)SQLITE_MISUSE_BKPT; |
126 | return 0; |
127 | } |
128 | #endif |
129 | pNew = &aStatic[id-2]; |
130 | pNew->id = id; |
131 | break; |
132 | } |
133 | } |
134 | return (sqlite3_mutex*)pNew; |
135 | } |
136 | |
137 | /* |
138 | ** This routine deallocates a previously allocated mutex. |
139 | */ |
140 | static void debugMutexFree(sqlite3_mutex *pX){ |
141 | sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; |
142 | assert( p->cnt==0 ); |
143 | if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ |
144 | sqlite3_free(p); |
145 | }else{ |
146 | #ifdef SQLITE_ENABLE_API_ARMOR |
147 | (void)SQLITE_MISUSE_BKPT; |
148 | #endif |
149 | } |
150 | } |
151 | |
152 | /* |
153 | ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt |
154 | ** to enter a mutex. If another thread is already within the mutex, |
155 | ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return |
156 | ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK |
157 | ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can |
158 | ** be entered multiple times by the same thread. In such cases the, |
159 | ** mutex must be exited an equal number of times before another thread |
160 | ** can enter. If the same thread tries to enter any other kind of mutex |
161 | ** more than once, the behavior is undefined. |
162 | */ |
163 | static void debugMutexEnter(sqlite3_mutex *pX){ |
164 | sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; |
165 | assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); |
166 | p->cnt++; |
167 | } |
168 | static int debugMutexTry(sqlite3_mutex *pX){ |
169 | sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; |
170 | assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); |
171 | p->cnt++; |
172 | return SQLITE_OK; |
173 | } |
174 | |
175 | /* |
176 | ** The sqlite3_mutex_leave() routine exits a mutex that was |
177 | ** previously entered by the same thread. The behavior |
178 | ** is undefined if the mutex is not currently entered or |
179 | ** is not currently allocated. SQLite will never do either. |
180 | */ |
181 | static void debugMutexLeave(sqlite3_mutex *pX){ |
182 | sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; |
183 | assert( debugMutexHeld(pX) ); |
184 | p->cnt--; |
185 | assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) ); |
186 | } |
187 | |
188 | sqlite3_mutex_methods const *sqlite3NoopMutex(void){ |
189 | static const sqlite3_mutex_methods sMutex = { |
190 | debugMutexInit, |
191 | debugMutexEnd, |
192 | debugMutexAlloc, |
193 | debugMutexFree, |
194 | debugMutexEnter, |
195 | debugMutexTry, |
196 | debugMutexLeave, |
197 | |
198 | debugMutexHeld, |
199 | debugMutexNotheld |
200 | }; |
201 | |
202 | return &sMutex; |
203 | } |
204 | #endif /* SQLITE_DEBUG */ |
205 | |
206 | /* |
207 | ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation |
208 | ** is used regardless of the run-time threadsafety setting. |
209 | */ |
210 | #ifdef SQLITE_MUTEX_NOOP |
211 | sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ |
212 | return sqlite3NoopMutex(); |
213 | } |
214 | #endif /* defined(SQLITE_MUTEX_NOOP) */ |
215 | #endif /* !defined(SQLITE_MUTEX_OMIT) */ |
216 | |