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 */ 333