Initial import of Scalos. To decrease size I have
[AROS-Contrib.git] / scalos / libraries / sqlite / src / mutex_w32.c
blobbfd9dacf6c2c4ff8da57c03600977194a0d9a595
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.
11 *************************************************************************
12 ** This file contains the C functions that implement mutexes for win32
14 #include "sqliteInt.h"
17 ** The code in this file is only used if we are compiling multithreaded
18 ** on a win32 system.
20 #ifdef SQLITE_MUTEX_W32
23 ** Each recursive mutex is an instance of the following structure.
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
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
42 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
43 ** or WinCE. Return false (zero) for Win95, Win98, or WinME.
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.
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.
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;
70 return osType==2;
72 #endif /* SQLITE_OS_WINCE */
73 #endif
75 #ifdef SQLITE_DEBUG
77 ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
78 ** intended for use only inside assert() statements.
80 static int winMutexHeld(sqlite3_mutex *p){
81 return p->nRef!=0 && p->owner==GetCurrentThreadId();
83 static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
84 return p->nRef==0 || p->owner!=tid;
86 static int winMutexNotheld(sqlite3_mutex *p){
87 DWORD tid = GetCurrentThreadId();
88 return winMutexNotheld2(p, tid);
90 #endif
94 ** Initialize and deinitialize the mutex subsystem.
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
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.
110 static long winMutex_lock = 0;
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);
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);
126 return SQLITE_OK;
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);
138 winMutex_isInit = 0;
141 return SQLITE_OK;
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:
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>
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.
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.
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.
186 static sqlite3_mutex *winMutexAlloc(int iType){
187 sqlite3_mutex *p;
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);
199 break;
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;
212 return p;
217 ** This routine deallocates a previously
218 ** allocated mutex. SQLite is careful to deallocate every
219 ** mutex that it allocates.
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);
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.
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);
253 #endif
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) );
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.
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.
272 #if 0
273 if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
274 p->owner = tid;
275 p->nRef++;
276 rc = SQLITE_OK;
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);
285 #endif
286 return rc;
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.
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);
309 #endif
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
327 #endif
330 return &sMutex;
332 #endif /* SQLITE_MUTEX_W32 */