AryaWu/sqlite
0
1/*2** 2007 August 143**4** The author disclaims copyright to this source code. In place of5** 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#if SQLITE_OS_WIN17/*18** Include code that is common to all os_*.c files19*/20#include "os_common.h"21 22/*23** Include the header file for the Windows VFS.24*/25#include "os_win.h"26#endif27 28/*29** The code in this file is only used if we are compiling multithreaded30** on a Win32 system.31*/32#ifdef SQLITE_MUTEX_W3233 34/*35** Each recursive mutex is an instance of the following structure.36*/37struct sqlite3_mutex {38 CRITICAL_SECTION mutex; /* Mutex controlling the lock */39 int id; /* Mutex type */40#ifdef SQLITE_DEBUG41 volatile int nRef; /* Number of entrances */42 volatile DWORD owner; /* Thread holding this mutex */43 volatile LONG trace; /* True to trace changes */44#endif45};46 47/*48** These are the initializer values used when declaring a "static" mutex49** on Win32. It should be noted that all mutexes require initialization50** on the Win32 platform.51*/52#define SQLITE_W32_MUTEX_INITIALIZER { 0 }53 54#ifdef SQLITE_DEBUG55#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \56 0L, (DWORD)0, 0 }57#else58#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }59#endif60 61#ifdef SQLITE_DEBUG62/*63** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are64** intended for use only inside assert() statements.65*/66static int winMutexHeld(sqlite3_mutex *p){67 return p->nRef!=0 && p->owner==GetCurrentThreadId();68}69 70static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){71 return p->nRef==0 || p->owner!=tid;72}73 74static int winMutexNotheld(sqlite3_mutex *p){75 DWORD tid = GetCurrentThreadId();76 return winMutexNotheld2(p, tid);77}78#endif79 80/*81** Try to provide a memory barrier operation, needed for initialization82** and also for the xShmBarrier method of the VFS in cases when SQLite is83** compiled without mutexes (SQLITE_THREADSAFE=0).84*/85void sqlite3MemoryBarrier(void){86#if defined(SQLITE_MEMORY_BARRIER)87 SQLITE_MEMORY_BARRIER;88#elif defined(__GNUC__)89 __sync_synchronize();90#elif MSVC_VERSION>=140091 _ReadWriteBarrier();92#elif defined(MemoryBarrier)93 MemoryBarrier();94#endif95}96 97/*98** Initialize and deinitialize the mutex subsystem.99*/100static sqlite3_mutex winMutex_staticMutexes[] = {101 SQLITE3_MUTEX_INITIALIZER(2),102 SQLITE3_MUTEX_INITIALIZER(3),103 SQLITE3_MUTEX_INITIALIZER(4),104 SQLITE3_MUTEX_INITIALIZER(5),105 SQLITE3_MUTEX_INITIALIZER(6),106 SQLITE3_MUTEX_INITIALIZER(7),107 SQLITE3_MUTEX_INITIALIZER(8),108 SQLITE3_MUTEX_INITIALIZER(9),109 SQLITE3_MUTEX_INITIALIZER(10),110 SQLITE3_MUTEX_INITIALIZER(11),111 SQLITE3_MUTEX_INITIALIZER(12),112 SQLITE3_MUTEX_INITIALIZER(13)113};114 115static int winMutex_isInit = 0;116static int winMutex_isNt = -1; /* <0 means "need to query" */117 118/* As the winMutexInit() and winMutexEnd() functions are called as part119** of the sqlite3_initialize() and sqlite3_shutdown() processing, the120** "interlocked" magic used here is probably not strictly necessary.121*/122static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;123 124int sqlite3_win32_is_nt(void); /* os_win.c */125void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */126 127static int winMutexInit(void){128 /* The first to increment to 1 does actual initialization */129 if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){130 int i;131 for(i=0; i<ArraySize(winMutex_staticMutexes); i++){132 InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);133 }134 winMutex_isInit = 1;135 }else{136 /* Another thread is (in the process of) initializing the static137 ** mutexes */138 while( !winMutex_isInit ){139 sqlite3_win32_sleep(1);140 }141 }142 return SQLITE_OK;143}144 145static int winMutexEnd(void){146 /* The first to decrement to 0 does actual shutdown147 ** (which should be the last to shutdown.) */148 if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){149 if( winMutex_isInit==1 ){150 int i;151 for(i=0; i<ArraySize(winMutex_staticMutexes); i++){152 DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);153 }154 winMutex_isInit = 0;155 }156 }157 return SQLITE_OK;158}159 160/*161** The sqlite3_mutex_alloc() routine allocates a new162** mutex and returns a pointer to it. If it returns NULL163** that means that a mutex could not be allocated. SQLite164** will unwind its stack and return an error. The argument165** to sqlite3_mutex_alloc() is one of these integer constants:166**167** <ul>168** <li> SQLITE_MUTEX_FAST169** <li> SQLITE_MUTEX_RECURSIVE170** <li> SQLITE_MUTEX_STATIC_MAIN171** <li> SQLITE_MUTEX_STATIC_MEM172** <li> SQLITE_MUTEX_STATIC_OPEN173** <li> SQLITE_MUTEX_STATIC_PRNG174** <li> SQLITE_MUTEX_STATIC_LRU175** <li> SQLITE_MUTEX_STATIC_PMEM176** <li> SQLITE_MUTEX_STATIC_APP1177** <li> SQLITE_MUTEX_STATIC_APP2178** <li> SQLITE_MUTEX_STATIC_APP3179** <li> SQLITE_MUTEX_STATIC_VFS1180** <li> SQLITE_MUTEX_STATIC_VFS2181** <li> SQLITE_MUTEX_STATIC_VFS3182** </ul>183**184** The first two constants cause sqlite3_mutex_alloc() to create185** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE186** is used but not necessarily so when SQLITE_MUTEX_FAST is used.187** The mutex implementation does not need to make a distinction188** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does189** not want to. But SQLite will only request a recursive mutex in190** cases where it really needs one. If a faster non-recursive mutex191** implementation is available on the host platform, the mutex subsystem192** might return such a mutex in response to SQLITE_MUTEX_FAST.193**194** The other allowed parameters to sqlite3_mutex_alloc() each return195** a pointer to a static preexisting mutex. Six static mutexes are196** used by the current version of SQLite. Future versions of SQLite197** may add additional static mutexes. Static mutexes are for internal198** use by SQLite only. Applications that use SQLite mutexes should199** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or200** SQLITE_MUTEX_RECURSIVE.201**202** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST203** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()204** returns a different mutex on every call. But for the static205** mutex types, the same mutex is returned on every call that has206** the same type number.207*/208static sqlite3_mutex *winMutexAlloc(int iType){209 sqlite3_mutex *p;210 211 switch( iType ){212 case SQLITE_MUTEX_FAST:213 case SQLITE_MUTEX_RECURSIVE: {214 p = sqlite3MallocZero( sizeof(*p) );215 if( p ){216 p->id = iType;217#ifdef SQLITE_DEBUG218#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC219 p->trace = 1;220#endif221#endif222 InitializeCriticalSection(&p->mutex);223 }224 break;225 }226 default: {227#ifdef SQLITE_ENABLE_API_ARMOR228 if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){229 (void)SQLITE_MISUSE_BKPT;230 return 0;231 }232#endif233 p = &winMutex_staticMutexes[iType-2];234#ifdef SQLITE_DEBUG235#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC236 InterlockedCompareExchange(&p->trace, 1, 0);237#endif238#endif239 break;240 }241 }242 assert( p==0 || p->id==iType );243 return p;244}245 246 247/*248** This routine deallocates a previously249** allocated mutex. SQLite is careful to deallocate every250** mutex that it allocates.251*/252static void winMutexFree(sqlite3_mutex *p){253 assert( p );254 assert( p->nRef==0 && p->owner==0 );255 if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){256 DeleteCriticalSection(&p->mutex);257 sqlite3_free(p);258 }else{259#ifdef SQLITE_ENABLE_API_ARMOR260 (void)SQLITE_MISUSE_BKPT;261#endif262 }263}264 265/*266** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt267** to enter a mutex. If another thread is already within the mutex,268** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return269** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK270** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can271** be entered multiple times by the same thread. In such cases the,272** mutex must be exited an equal number of times before another thread273** can enter. If the same thread tries to enter any other kind of mutex274** more than once, the behavior is undefined.275*/276static void winMutexEnter(sqlite3_mutex *p){277#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)278 DWORD tid = GetCurrentThreadId();279#endif280#ifdef SQLITE_DEBUG281 assert( p );282 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );283#else284 assert( p );285#endif286 assert( winMutex_isInit==1 );287 EnterCriticalSection(&p->mutex);288#ifdef SQLITE_DEBUG289 assert( p->nRef>0 || p->owner==0 );290 p->owner = tid;291 p->nRef++;292 if( p->trace ){293 OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",294 tid, p->id, p, p->trace, p->nRef));295 }296#endif297}298 299static int winMutexTry(sqlite3_mutex *p){300#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)301 DWORD tid = GetCurrentThreadId();302#endif303 int rc = SQLITE_BUSY;304 assert( p );305 assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );306 /*307 ** The sqlite3_mutex_try() routine is very rarely used, and when it308 ** is used it is merely an optimization. So it is OK for it to always309 ** fail.310 **311 ** The TryEnterCriticalSection() interface is only available on WinNT.312 ** And some windows compilers complain if you try to use it without313 ** first doing some #defines that prevent SQLite from building on Win98.314 ** For that reason, we will omit this optimization for now. See315 ** ticket #2685.316 */317#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400318 assert( winMutex_isInit==1 );319 assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );320 if( winMutex_isNt<0 ){321 winMutex_isNt = sqlite3_win32_is_nt();322 }323 assert( winMutex_isNt==0 || winMutex_isNt==1 );324 if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){325#ifdef SQLITE_DEBUG326 p->owner = tid;327 p->nRef++;328#endif329 rc = SQLITE_OK;330 }331#else332 UNUSED_PARAMETER(p);333#endif334#ifdef SQLITE_DEBUG335 if( p->trace ){336 OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",337 tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));338 }339#endif340 return rc;341}342 343/*344** The sqlite3_mutex_leave() routine exits a mutex that was345** previously entered by the same thread. The behavior346** is undefined if the mutex is not currently entered or347** is not currently allocated. SQLite will never do either.348*/349static void winMutexLeave(sqlite3_mutex *p){350#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)351 DWORD tid = GetCurrentThreadId();352#endif353 assert( p );354#ifdef SQLITE_DEBUG355 assert( p->nRef>0 );356 assert( p->owner==tid );357 p->nRef--;358 if( p->nRef==0 ) p->owner = 0;359 assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );360#endif361 assert( winMutex_isInit==1 );362 LeaveCriticalSection(&p->mutex);363#ifdef SQLITE_DEBUG364 if( p->trace ){365 OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",366 tid, p->id, p, p->trace, p->nRef));367 }368#endif369}370 371sqlite3_mutex_methods const *sqlite3DefaultMutex(void){372 static const sqlite3_mutex_methods sMutex = {373 winMutexInit,374 winMutexEnd,375 winMutexAlloc,376 winMutexFree,377 winMutexEnter,378 winMutexTry,379 winMutexLeave,380#ifdef SQLITE_DEBUG381 winMutexHeld,382 winMutexNotheld383#else384 0,385 0386#endif387 };388 return &sMutex;389}390 391#endif /* SQLITE_MUTEX_W32 */392 