diff options
Diffstat (limited to 'libraries/sqlite/win32/mutex_w32.c')
-rwxr-xr-x | libraries/sqlite/win32/mutex_w32.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/libraries/sqlite/win32/mutex_w32.c b/libraries/sqlite/win32/mutex_w32.c new file mode 100755 index 0000000..3153cd0 --- /dev/null +++ b/libraries/sqlite/win32/mutex_w32.c | |||
@@ -0,0 +1,210 @@ | |||
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 | ** $Id: mutex_w32.c,v 1.4 2007/09/05 14:30:42 drh Exp $ | ||
15 | */ | ||
16 | #define _WIN32_WINNT 0x0400 | ||
17 | #include <Windows.h> | ||
18 | #include "sqliteInt.h" | ||
19 | |||
20 | /* | ||
21 | ** The code in this file is only used if we are compiling multithreaded | ||
22 | ** on a win32 system. | ||
23 | */ | ||
24 | #ifdef SQLITE_MUTEX_W32 | ||
25 | |||
26 | /* | ||
27 | ** Each recursive mutex is an instance of the following structure. | ||
28 | */ | ||
29 | struct sqlite3_mutex { | ||
30 | CRITICAL_SECTION mutex; /* Mutex controlling the lock */ | ||
31 | int id; /* Mutex type */ | ||
32 | int nRef; /* Number of enterances */ | ||
33 | DWORD owner; /* Thread holding this mutex */ | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, | ||
38 | ** or WinCE. Return false (zero) for Win95, Win98, or WinME. | ||
39 | ** | ||
40 | ** Here is an interesting observation: Win95, Win98, and WinME lack | ||
41 | ** the LockFileEx() API. But we can still statically link against that | ||
42 | ** API as long as we don't call it win running Win95/98/ME. A call to | ||
43 | ** this routine is used to determine if the host is Win95/98/ME or | ||
44 | ** WinNT/2K/XP so that we will know whether or not we can safely call | ||
45 | ** the LockFileEx() API. | ||
46 | */ | ||
47 | #if OS_WINCE | ||
48 | # define mutexIsNT() (1) | ||
49 | #else | ||
50 | static int mutexIsNT(void){ | ||
51 | static int osType = 0; | ||
52 | if( osType==0 ){ | ||
53 | OSVERSIONINFO sInfo; | ||
54 | sInfo.dwOSVersionInfoSize = sizeof(sInfo); | ||
55 | GetVersionEx(&sInfo); | ||
56 | osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; | ||
57 | } | ||
58 | return osType==2; | ||
59 | } | ||
60 | #endif /* OS_WINCE */ | ||
61 | |||
62 | |||
63 | /* | ||
64 | ** The sqlite3_mutex_alloc() routine allocates a new | ||
65 | ** mutex and returns a pointer to it. If it returns NULL | ||
66 | ** that means that a mutex could not be allocated. SQLite | ||
67 | ** will unwind its stack and return an error. The argument | ||
68 | ** to sqlite3_mutex_alloc() is one of these integer constants: | ||
69 | ** | ||
70 | ** <ul> | ||
71 | ** <li> SQLITE_MUTEX_FAST 0 | ||
72 | ** <li> SQLITE_MUTEX_RECURSIVE 1 | ||
73 | ** <li> SQLITE_MUTEX_STATIC_MASTER 2 | ||
74 | ** <li> SQLITE_MUTEX_STATIC_MEM 3 | ||
75 | ** <li> SQLITE_MUTEX_STATIC_PRNG 4 | ||
76 | ** </ul> | ||
77 | ** | ||
78 | ** The first two constants cause sqlite3_mutex_alloc() to create | ||
79 | ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE | ||
80 | ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. | ||
81 | ** The mutex implementation does not need to make a distinction | ||
82 | ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does | ||
83 | ** not want to. But SQLite will only request a recursive mutex in | ||
84 | ** cases where it really needs one. If a faster non-recursive mutex | ||
85 | ** implementation is available on the host platform, the mutex subsystem | ||
86 | ** might return such a mutex in response to SQLITE_MUTEX_FAST. | ||
87 | ** | ||
88 | ** The other allowed parameters to sqlite3_mutex_alloc() each return | ||
89 | ** a pointer to a static preexisting mutex. Three static mutexes are | ||
90 | ** used by the current version of SQLite. Future versions of SQLite | ||
91 | ** may add additional static mutexes. Static mutexes are for internal | ||
92 | ** use by SQLite only. Applications that use SQLite mutexes should | ||
93 | ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or | ||
94 | ** SQLITE_MUTEX_RECURSIVE. | ||
95 | ** | ||
96 | ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST | ||
97 | ** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() | ||
98 | ** returns a different mutex on every call. But for the static | ||
99 | ** mutex types, the same mutex is returned on every call that has | ||
100 | ** the same type number. | ||
101 | */ | ||
102 | sqlite3_mutex *sqlite3_mutex_alloc(int iType){ | ||
103 | sqlite3_mutex *p; | ||
104 | |||
105 | switch( iType ){ | ||
106 | case SQLITE_MUTEX_FAST: | ||
107 | case SQLITE_MUTEX_RECURSIVE: { | ||
108 | p = sqlite3MallocZero( sizeof(*p) ); | ||
109 | if( p ){ | ||
110 | p->id = iType; | ||
111 | InitializeCriticalSection(&p->mutex); | ||
112 | } | ||
113 | break; | ||
114 | } | ||
115 | default: { | ||
116 | static sqlite3_mutex staticMutexes[5]; | ||
117 | static int isInit = 0; | ||
118 | while( !isInit ){ | ||
119 | static long lock = 0; | ||
120 | if( InterlockedIncrement(&lock)==1 ){ | ||
121 | int i; | ||
122 | for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){ | ||
123 | InitializeCriticalSection(&staticMutexes[i].mutex); | ||
124 | } | ||
125 | isInit = 1; | ||
126 | }else{ | ||
127 | Sleep(1); | ||
128 | } | ||
129 | } | ||
130 | assert( iType-2 >= 0 ); | ||
131 | assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); | ||
132 | p = &staticMutexes[iType-2]; | ||
133 | p->id = iType; | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | return p; | ||
138 | } | ||
139 | |||
140 | |||
141 | /* | ||
142 | ** This routine deallocates a previously | ||
143 | ** allocated mutex. SQLite is careful to deallocate every | ||
144 | ** mutex that it allocates. | ||
145 | */ | ||
146 | void sqlite3_mutex_free(sqlite3_mutex *p){ | ||
147 | assert( p ); | ||
148 | assert( p->nRef==0 ); | ||
149 | assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); | ||
150 | DeleteCriticalSection(&p->mutex); | ||
151 | sqlite3_free(p); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt | ||
156 | ** to enter a mutex. If another thread is already within the mutex, | ||
157 | ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return | ||
158 | ** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK | ||
159 | ** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can | ||
160 | ** be entered multiple times by the same thread. In such cases the, | ||
161 | ** mutex must be exited an equal number of times before another thread | ||
162 | ** can enter. If the same thread tries to enter any other kind of mutex | ||
163 | ** more than once, the behavior is undefined. | ||
164 | */ | ||
165 | void sqlite3_mutex_enter(sqlite3_mutex *p){ | ||
166 | assert( p ); | ||
167 | assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); | ||
168 | EnterCriticalSection(&p->mutex); | ||
169 | p->owner = GetCurrentThreadId(); | ||
170 | p->nRef++; | ||
171 | } | ||
172 | int sqlite3_mutex_try(sqlite3_mutex *p){ | ||
173 | int rc; | ||
174 | assert( p ); | ||
175 | assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); | ||
176 | if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ | ||
177 | p->owner = GetCurrentThreadId(); | ||
178 | p->nRef++; | ||
179 | rc = SQLITE_OK; | ||
180 | }else{ | ||
181 | rc = SQLITE_BUSY; | ||
182 | } | ||
183 | return rc; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | ** The sqlite3_mutex_leave() routine exits a mutex that was | ||
188 | ** previously entered by the same thread. The behavior | ||
189 | ** is undefined if the mutex is not currently entered or | ||
190 | ** is not currently allocated. SQLite will never do either. | ||
191 | */ | ||
192 | void sqlite3_mutex_leave(sqlite3_mutex *p){ | ||
193 | assert( p->nRef>0 ); | ||
194 | assert( p->owner==GetCurrentThreadId() ); | ||
195 | p->nRef--; | ||
196 | assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); | ||
197 | LeaveCriticalSection(&p->mutex); | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are | ||
202 | ** intended for use only inside assert() statements. | ||
203 | */ | ||
204 | int sqlite3_mutex_held(sqlite3_mutex *p){ | ||
205 | return p==0 || (p->nRef!=0 && p->owner==GetCurrentThreadId()); | ||
206 | } | ||
207 | int sqlite3_mutex_notheld(sqlite3_mutex *p){ | ||
208 | return p==0 || p->nRef==0 || p->owner!=GetCurrentThreadId(); | ||
209 | } | ||
210 | #endif /* SQLITE_MUTEX_W32 */ | ||