Index: third_party/sqlite/src/src/mutex_w32.c |
diff --git a/third_party/sqlite/src/src/mutex_w32.c b/third_party/sqlite/src/src/mutex_w32.c |
index bfd9dacf6c2c4ff8da57c03600977194a0d9a595..da7d73f7c5896931836a7315cc444001fff24f2b 100644 |
--- a/third_party/sqlite/src/src/mutex_w32.c |
+++ b/third_party/sqlite/src/src/mutex_w32.c |
@@ -9,13 +9,25 @@ |
** May you share freely, never taking more than you give. |
** |
************************************************************************* |
-** This file contains the C functions that implement mutexes for win32 |
+** This file contains the C functions that implement mutexes for Win32. |
*/ |
#include "sqliteInt.h" |
+#if SQLITE_OS_WIN |
+/* |
+** Include code that is common to all os_*.c files |
+*/ |
+#include "os_common.h" |
+ |
+/* |
+** Include the header file for the Windows VFS. |
+*/ |
+#include "os_win.h" |
+#endif |
+ |
/* |
** The code in this file is only used if we are compiling multithreaded |
-** on a win32 system. |
+** on a Win32 system. |
*/ |
#ifdef SQLITE_MUTEX_W32 |
@@ -28,48 +40,22 @@ struct sqlite3_mutex { |
#ifdef SQLITE_DEBUG |
volatile int nRef; /* Number of enterances */ |
volatile DWORD owner; /* Thread holding this mutex */ |
- int trace; /* True to trace changes */ |
+ volatile int trace; /* True to trace changes */ |
#endif |
}; |
-#define SQLITE_W32_MUTEX_INITIALIZER { 0 } |
-#ifdef SQLITE_DEBUG |
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 } |
-#else |
-#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } |
-#endif |
/* |
-** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |
-** or WinCE. Return false (zero) for Win95, Win98, or WinME. |
-** |
-** Here is an interesting observation: Win95, Win98, and WinME lack |
-** the LockFileEx() API. But we can still statically link against that |
-** API as long as we don't call it win running Win95/98/ME. A call to |
-** this routine is used to determine if the host is Win95/98/ME or |
-** WinNT/2K/XP so that we will know whether or not we can safely call |
-** the LockFileEx() API. |
-** |
-** mutexIsNT() is only used for the TryEnterCriticalSection() API call, |
-** which is only available if your application was compiled with |
-** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only |
-** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef |
-** this out as well. |
+** These are the initializer values used when declaring a "static" mutex |
+** on Win32. It should be noted that all mutexes require initialization |
+** on the Win32 platform. |
*/ |
-#if 0 |
-#if SQLITE_OS_WINCE |
-# define mutexIsNT() (1) |
+#define SQLITE_W32_MUTEX_INITIALIZER { 0 } |
+ |
+#ifdef SQLITE_DEBUG |
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ |
+ 0L, (DWORD)0, 0 } |
#else |
- static int mutexIsNT(void){ |
- static int osType = 0; |
- if( osType==0 ){ |
- OSVERSIONINFO sInfo; |
- sInfo.dwOSVersionInfoSize = sizeof(sInfo); |
- GetVersionEx(&sInfo); |
- osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; |
- } |
- return osType==2; |
- } |
-#endif /* SQLITE_OS_WINCE */ |
+#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } |
#endif |
#ifdef SQLITE_DEBUG |
@@ -80,20 +66,24 @@ struct sqlite3_mutex { |
static int winMutexHeld(sqlite3_mutex *p){ |
return p->nRef!=0 && p->owner==GetCurrentThreadId(); |
} |
+ |
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){ |
return p->nRef==0 || p->owner!=tid; |
} |
+ |
static int winMutexNotheld(sqlite3_mutex *p){ |
- DWORD tid = GetCurrentThreadId(); |
+ DWORD tid = GetCurrentThreadId(); |
return winMutexNotheld2(p, tid); |
} |
#endif |
- |
/* |
** Initialize and deinitialize the mutex subsystem. |
*/ |
-static sqlite3_mutex winMutex_staticMutexes[6] = { |
+static sqlite3_mutex winMutex_staticMutexes[] = { |
+ SQLITE3_MUTEX_INITIALIZER, |
+ SQLITE3_MUTEX_INITIALIZER, |
+ SQLITE3_MUTEX_INITIALIZER, |
SQLITE3_MUTEX_INITIALIZER, |
SQLITE3_MUTEX_INITIALIZER, |
SQLITE3_MUTEX_INITIALIZER, |
@@ -101,33 +91,43 @@ static sqlite3_mutex winMutex_staticMutexes[6] = { |
SQLITE3_MUTEX_INITIALIZER, |
SQLITE3_MUTEX_INITIALIZER |
}; |
+ |
static int winMutex_isInit = 0; |
-/* As winMutexInit() and winMutexEnd() are called as part |
-** of the sqlite3_initialize and sqlite3_shutdown() |
-** processing, the "interlocked" magic is probably not |
-** strictly necessary. |
+static int winMutex_isNt = -1; /* <0 means "need to query" */ |
+ |
+/* As the winMutexInit() and winMutexEnd() functions are called as part |
+** of the sqlite3_initialize() and sqlite3_shutdown() processing, the |
+** "interlocked" magic used here is probably not strictly necessary. |
*/ |
-static long winMutex_lock = 0; |
+static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; |
-static int winMutexInit(void){ |
+int sqlite3_win32_is_nt(void); /* os_win.c */ |
+void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ |
+ |
+static int winMutexInit(void){ |
/* The first to increment to 1 does actual initialization */ |
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ |
int i; |
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ |
+#if SQLITE_OS_WINRT |
+ InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0); |
+#else |
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex); |
+#endif |
} |
winMutex_isInit = 1; |
}else{ |
- /* Someone else is in the process of initing the static mutexes */ |
+ /* Another thread is (in the process of) initializing the static |
+ ** mutexes */ |
while( !winMutex_isInit ){ |
- Sleep(1); |
+ sqlite3_win32_sleep(1); |
} |
} |
- return SQLITE_OK; |
+ return SQLITE_OK; |
} |
-static int winMutexEnd(void){ |
- /* The first to decrement to 0 does actual shutdown |
+static int winMutexEnd(void){ |
+ /* The first to decrement to 0 does actual shutdown |
** (which should be the last to shutdown.) */ |
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){ |
if( winMutex_isInit==1 ){ |
@@ -138,7 +138,7 @@ static int winMutexEnd(void){ |
winMutex_isInit = 0; |
} |
} |
- return SQLITE_OK; |
+ return SQLITE_OK; |
} |
/* |
@@ -153,10 +153,13 @@ static int winMutexEnd(void){ |
** <li> SQLITE_MUTEX_RECURSIVE |
** <li> SQLITE_MUTEX_STATIC_MASTER |
** <li> SQLITE_MUTEX_STATIC_MEM |
-** <li> SQLITE_MUTEX_STATIC_MEM2 |
+** <li> SQLITE_MUTEX_STATIC_OPEN |
** <li> SQLITE_MUTEX_STATIC_PRNG |
** <li> SQLITE_MUTEX_STATIC_LRU |
** <li> SQLITE_MUTEX_STATIC_PMEM |
+** <li> SQLITE_MUTEX_STATIC_APP1 |
+** <li> SQLITE_MUTEX_STATIC_APP2 |
+** <li> SQLITE_MUTEX_STATIC_APP3 |
** </ul> |
** |
** The first two constants cause sqlite3_mutex_alloc() to create |
@@ -179,7 +182,7 @@ static int winMutexEnd(void){ |
** |
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST |
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() |
-** returns a different mutex on every call. But for the static |
+** returns a different mutex on every call. But for the static |
** mutex types, the same mutex is returned on every call that has |
** the same type number. |
*/ |
@@ -190,21 +193,31 @@ static sqlite3_mutex *winMutexAlloc(int iType){ |
case SQLITE_MUTEX_FAST: |
case SQLITE_MUTEX_RECURSIVE: { |
p = sqlite3MallocZero( sizeof(*p) ); |
- if( p ){ |
+ if( p ){ |
#ifdef SQLITE_DEBUG |
p->id = iType; |
+#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC |
+ p->trace = 1; |
+#endif |
#endif |
+#if SQLITE_OS_WINRT |
+ InitializeCriticalSectionEx(&p->mutex, 0, 0); |
+#else |
InitializeCriticalSection(&p->mutex); |
+#endif |
} |
break; |
} |
default: { |
- assert( winMutex_isInit==1 ); |
assert( iType-2 >= 0 ); |
assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
+ assert( winMutex_isInit==1 ); |
p = &winMutex_staticMutexes[iType-2]; |
#ifdef SQLITE_DEBUG |
p->id = iType; |
+#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC |
+ p->trace = 1; |
+#endif |
#endif |
break; |
} |
@@ -220,8 +233,11 @@ static sqlite3_mutex *winMutexAlloc(int iType){ |
*/ |
static void winMutexFree(sqlite3_mutex *p){ |
assert( p ); |
+#ifdef SQLITE_DEBUG |
assert( p->nRef==0 && p->owner==0 ); |
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); |
+#endif |
+ assert( winMutex_isInit==1 ); |
DeleteCriticalSection(&p->mutex); |
sqlite3_free(p); |
} |
@@ -238,30 +254,39 @@ static void winMutexFree(sqlite3_mutex *p){ |
** more than once, the behavior is undefined. |
*/ |
static void winMutexEnter(sqlite3_mutex *p){ |
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
+ DWORD tid = GetCurrentThreadId(); |
+#endif |
#ifdef SQLITE_DEBUG |
- DWORD tid = GetCurrentThreadId(); |
+ assert( p ); |
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); |
+#else |
+ assert( p ); |
#endif |
+ assert( winMutex_isInit==1 ); |
EnterCriticalSection(&p->mutex); |
#ifdef SQLITE_DEBUG |
assert( p->nRef>0 || p->owner==0 ); |
- p->owner = tid; |
+ p->owner = tid; |
p->nRef++; |
if( p->trace ){ |
- printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
+ OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", |
+ tid, p, p->trace, p->nRef)); |
} |
#endif |
} |
+ |
static int winMutexTry(sqlite3_mutex *p){ |
-#ifndef NDEBUG |
- DWORD tid = GetCurrentThreadId(); |
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
+ DWORD tid = GetCurrentThreadId(); |
#endif |
int rc = SQLITE_BUSY; |
+ assert( p ); |
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) ); |
/* |
** The sqlite3_mutex_try() routine is very rarely used, and when it |
** is used it is merely an optimization. So it is OK for it to always |
- ** fail. |
+ ** fail. |
** |
** The TryEnterCriticalSection() interface is only available on WinNT. |
** And some windows compilers complain if you try to use it without |
@@ -269,18 +294,27 @@ static int winMutexTry(sqlite3_mutex *p){ |
** For that reason, we will omit this optimization for now. See |
** ticket #2685. |
*/ |
-#if 0 |
- if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ |
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400 |
+ assert( winMutex_isInit==1 ); |
+ assert( winMutex_isNt>=-1 && winMutex_isNt<=1 ); |
+ if( winMutex_isNt<0 ){ |
+ winMutex_isNt = sqlite3_win32_is_nt(); |
+ } |
+ assert( winMutex_isNt==0 || winMutex_isNt==1 ); |
+ if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){ |
+#ifdef SQLITE_DEBUG |
p->owner = tid; |
p->nRef++; |
+#endif |
rc = SQLITE_OK; |
} |
#else |
UNUSED_PARAMETER(p); |
#endif |
#ifdef SQLITE_DEBUG |
- if( rc==SQLITE_OK && p->trace ){ |
- printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
+ if( p->trace ){ |
+ OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n", |
+ tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); |
} |
#endif |
return rc; |
@@ -293,18 +327,23 @@ static int winMutexTry(sqlite3_mutex *p){ |
** is not currently allocated. SQLite will never do either. |
*/ |
static void winMutexLeave(sqlite3_mutex *p){ |
-#ifndef NDEBUG |
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
DWORD tid = GetCurrentThreadId(); |
+#endif |
+ assert( p ); |
+#ifdef SQLITE_DEBUG |
assert( p->nRef>0 ); |
assert( p->owner==tid ); |
p->nRef--; |
if( p->nRef==0 ) p->owner = 0; |
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); |
#endif |
+ assert( winMutex_isInit==1 ); |
LeaveCriticalSection(&p->mutex); |
#ifdef SQLITE_DEBUG |
if( p->trace ){ |
- printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); |
+ OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n", |
+ tid, p, p->trace, p->nRef)); |
} |
#endif |
} |
@@ -326,7 +365,7 @@ sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ |
0 |
#endif |
}; |
- |
return &sMutex; |
} |
+ |
#endif /* SQLITE_MUTEX_W32 */ |