Annotation of embedaddon/sqlite3/src/mutex_w32.c, revision 1.1.1.1
1.1 misho 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 for win32
13: */
14: #include "sqliteInt.h"
15:
16: /*
17: ** The code in this file is only used if we are compiling multithreaded
18: ** on a win32 system.
19: */
20: #ifdef SQLITE_MUTEX_W32
21:
22: /*
23: ** Each recursive mutex is an instance of the following structure.
24: */
25: struct sqlite3_mutex {
26: CRITICAL_SECTION mutex; /* Mutex controlling the lock */
27: int id; /* Mutex type */
28: #ifdef SQLITE_DEBUG
29: volatile int nRef; /* Number of enterances */
30: volatile DWORD owner; /* Thread holding this mutex */
31: int trace; /* True to trace changes */
32: #endif
33: };
34: #define SQLITE_W32_MUTEX_INITIALIZER { 0 }
35: #ifdef SQLITE_DEBUG
36: #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
37: #else
38: #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
39: #endif
40:
41: /*
42: ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
43: ** or WinCE. Return false (zero) for Win95, Win98, or WinME.
44: **
45: ** Here is an interesting observation: Win95, Win98, and WinME lack
46: ** the LockFileEx() API. But we can still statically link against that
47: ** API as long as we don't call it win running Win95/98/ME. A call to
48: ** this routine is used to determine if the host is Win95/98/ME or
49: ** WinNT/2K/XP so that we will know whether or not we can safely call
50: ** the LockFileEx() API.
51: **
52: ** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
53: ** which is only available if your application was compiled with
54: ** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
55: ** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
56: ** this out as well.
57: */
58: #if 0
59: #if SQLITE_OS_WINCE
60: # define mutexIsNT() (1)
61: #else
62: static int mutexIsNT(void){
63: static int osType = 0;
64: if( osType==0 ){
65: OSVERSIONINFO sInfo;
66: sInfo.dwOSVersionInfoSize = sizeof(sInfo);
67: GetVersionEx(&sInfo);
68: osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
69: }
70: return osType==2;
71: }
72: #endif /* SQLITE_OS_WINCE */
73: #endif
74:
75: #ifdef SQLITE_DEBUG
76: /*
77: ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
78: ** intended for use only inside assert() statements.
79: */
80: static int winMutexHeld(sqlite3_mutex *p){
81: return p->nRef!=0 && p->owner==GetCurrentThreadId();
82: }
83: static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
84: return p->nRef==0 || p->owner!=tid;
85: }
86: static int winMutexNotheld(sqlite3_mutex *p){
87: DWORD tid = GetCurrentThreadId();
88: return winMutexNotheld2(p, tid);
89: }
90: #endif
91:
92:
93: /*
94: ** Initialize and deinitialize the mutex subsystem.
95: */
96: static sqlite3_mutex winMutex_staticMutexes[6] = {
97: SQLITE3_MUTEX_INITIALIZER,
98: SQLITE3_MUTEX_INITIALIZER,
99: SQLITE3_MUTEX_INITIALIZER,
100: SQLITE3_MUTEX_INITIALIZER,
101: SQLITE3_MUTEX_INITIALIZER,
102: SQLITE3_MUTEX_INITIALIZER
103: };
104: static int winMutex_isInit = 0;
105: /* As winMutexInit() and winMutexEnd() are called as part
106: ** of the sqlite3_initialize and sqlite3_shutdown()
107: ** processing, the "interlocked" magic is probably not
108: ** strictly necessary.
109: */
110: static long winMutex_lock = 0;
111:
112: static int winMutexInit(void){
113: /* The first to increment to 1 does actual initialization */
114: if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
115: int i;
116: for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
117: InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
118: }
119: winMutex_isInit = 1;
120: }else{
121: /* Someone else is in the process of initing the static mutexes */
122: while( !winMutex_isInit ){
123: Sleep(1);
124: }
125: }
126: return SQLITE_OK;
127: }
128:
129: static int winMutexEnd(void){
130: /* The first to decrement to 0 does actual shutdown
131: ** (which should be the last to shutdown.) */
132: if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
133: if( winMutex_isInit==1 ){
134: int i;
135: for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
136: DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
137: }
138: winMutex_isInit = 0;
139: }
140: }
141: return SQLITE_OK;
142: }
143:
144: /*
145: ** The sqlite3_mutex_alloc() routine allocates a new
146: ** mutex and returns a pointer to it. If it returns NULL
147: ** that means that a mutex could not be allocated. SQLite
148: ** will unwind its stack and return an error. The argument
149: ** to sqlite3_mutex_alloc() is one of these integer constants:
150: **
151: ** <ul>
152: ** <li> SQLITE_MUTEX_FAST
153: ** <li> SQLITE_MUTEX_RECURSIVE
154: ** <li> SQLITE_MUTEX_STATIC_MASTER
155: ** <li> SQLITE_MUTEX_STATIC_MEM
156: ** <li> SQLITE_MUTEX_STATIC_MEM2
157: ** <li> SQLITE_MUTEX_STATIC_PRNG
158: ** <li> SQLITE_MUTEX_STATIC_LRU
159: ** <li> SQLITE_MUTEX_STATIC_PMEM
160: ** </ul>
161: **
162: ** The first two constants cause sqlite3_mutex_alloc() to create
163: ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
164: ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
165: ** The mutex implementation does not need to make a distinction
166: ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
167: ** not want to. But SQLite will only request a recursive mutex in
168: ** cases where it really needs one. If a faster non-recursive mutex
169: ** implementation is available on the host platform, the mutex subsystem
170: ** might return such a mutex in response to SQLITE_MUTEX_FAST.
171: **
172: ** The other allowed parameters to sqlite3_mutex_alloc() each return
173: ** a pointer to a static preexisting mutex. Six static mutexes are
174: ** used by the current version of SQLite. Future versions of SQLite
175: ** may add additional static mutexes. Static mutexes are for internal
176: ** use by SQLite only. Applications that use SQLite mutexes should
177: ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
178: ** SQLITE_MUTEX_RECURSIVE.
179: **
180: ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
181: ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
182: ** returns a different mutex on every call. But for the static
183: ** mutex types, the same mutex is returned on every call that has
184: ** the same type number.
185: */
186: static sqlite3_mutex *winMutexAlloc(int iType){
187: sqlite3_mutex *p;
188:
189: switch( iType ){
190: case SQLITE_MUTEX_FAST:
191: case SQLITE_MUTEX_RECURSIVE: {
192: p = sqlite3MallocZero( sizeof(*p) );
193: if( p ){
194: #ifdef SQLITE_DEBUG
195: p->id = iType;
196: #endif
197: InitializeCriticalSection(&p->mutex);
198: }
199: break;
200: }
201: default: {
202: assert( winMutex_isInit==1 );
203: assert( iType-2 >= 0 );
204: assert( iType-2 < ArraySize(winMutex_staticMutexes) );
205: p = &winMutex_staticMutexes[iType-2];
206: #ifdef SQLITE_DEBUG
207: p->id = iType;
208: #endif
209: break;
210: }
211: }
212: return p;
213: }
214:
215:
216: /*
217: ** This routine deallocates a previously
218: ** allocated mutex. SQLite is careful to deallocate every
219: ** mutex that it allocates.
220: */
221: static void winMutexFree(sqlite3_mutex *p){
222: assert( p );
223: assert( p->nRef==0 && p->owner==0 );
224: assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
225: DeleteCriticalSection(&p->mutex);
226: sqlite3_free(p);
227: }
228:
229: /*
230: ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
231: ** to enter a mutex. If another thread is already within the mutex,
232: ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
233: ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
234: ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
235: ** be entered multiple times by the same thread. In such cases the,
236: ** mutex must be exited an equal number of times before another thread
237: ** can enter. If the same thread tries to enter any other kind of mutex
238: ** more than once, the behavior is undefined.
239: */
240: static void winMutexEnter(sqlite3_mutex *p){
241: #ifdef SQLITE_DEBUG
242: DWORD tid = GetCurrentThreadId();
243: assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
244: #endif
245: EnterCriticalSection(&p->mutex);
246: #ifdef SQLITE_DEBUG
247: assert( p->nRef>0 || p->owner==0 );
248: p->owner = tid;
249: p->nRef++;
250: if( p->trace ){
251: printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
252: }
253: #endif
254: }
255: static int winMutexTry(sqlite3_mutex *p){
256: #ifndef NDEBUG
257: DWORD tid = GetCurrentThreadId();
258: #endif
259: int rc = SQLITE_BUSY;
260: assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
261: /*
262: ** The sqlite3_mutex_try() routine is very rarely used, and when it
263: ** is used it is merely an optimization. So it is OK for it to always
264: ** fail.
265: **
266: ** The TryEnterCriticalSection() interface is only available on WinNT.
267: ** And some windows compilers complain if you try to use it without
268: ** first doing some #defines that prevent SQLite from building on Win98.
269: ** For that reason, we will omit this optimization for now. See
270: ** ticket #2685.
271: */
272: #if 0
273: if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
274: p->owner = tid;
275: p->nRef++;
276: rc = SQLITE_OK;
277: }
278: #else
279: UNUSED_PARAMETER(p);
280: #endif
281: #ifdef SQLITE_DEBUG
282: if( rc==SQLITE_OK && p->trace ){
283: printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
284: }
285: #endif
286: return rc;
287: }
288:
289: /*
290: ** The sqlite3_mutex_leave() routine exits a mutex that was
291: ** previously entered by the same thread. The behavior
292: ** is undefined if the mutex is not currently entered or
293: ** is not currently allocated. SQLite will never do either.
294: */
295: static void winMutexLeave(sqlite3_mutex *p){
296: #ifndef NDEBUG
297: DWORD tid = GetCurrentThreadId();
298: assert( p->nRef>0 );
299: assert( p->owner==tid );
300: p->nRef--;
301: if( p->nRef==0 ) p->owner = 0;
302: assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
303: #endif
304: LeaveCriticalSection(&p->mutex);
305: #ifdef SQLITE_DEBUG
306: if( p->trace ){
307: printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
308: }
309: #endif
310: }
311:
312: sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
313: static const sqlite3_mutex_methods sMutex = {
314: winMutexInit,
315: winMutexEnd,
316: winMutexAlloc,
317: winMutexFree,
318: winMutexEnter,
319: winMutexTry,
320: winMutexLeave,
321: #ifdef SQLITE_DEBUG
322: winMutexHeld,
323: winMutexNotheld
324: #else
325: 0,
326: 0
327: #endif
328: };
329:
330: return &sMutex;
331: }
332: #endif /* SQLITE_MUTEX_W32 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>