| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include "sqliteInt.h" |
|
|
| #if SQLITE_OS_WIN |
| |
| |
| |
| #include "os_common.h" |
|
|
| |
| |
| |
| #include "os_win.h" |
| #endif |
|
|
| |
| |
| |
| |
| #ifdef SQLITE_MUTEX_W32 |
|
|
| |
| |
| |
| struct sqlite3_mutex { |
| CRITICAL_SECTION mutex; |
| int id; |
| #ifdef SQLITE_DEBUG |
| volatile int nRef; |
| volatile DWORD owner; |
| volatile LONG trace; |
| #endif |
| }; |
|
|
| |
| |
| |
| |
| |
| #define SQLITE_W32_MUTEX_INITIALIZER { 0 } |
|
|
| #ifdef SQLITE_DEBUG |
| #define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \ |
| 0L, (DWORD)0, 0 } |
| #else |
| #define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id } |
| #endif |
|
|
| #ifdef SQLITE_DEBUG |
| |
| |
| |
| |
| 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(); |
| return winMutexNotheld2(p, tid); |
| } |
| #endif |
|
|
| |
| |
| |
| |
| |
| void sqlite3MemoryBarrier(void){ |
| #if defined(SQLITE_MEMORY_BARRIER) |
| SQLITE_MEMORY_BARRIER; |
| #elif defined(__GNUC__) |
| __sync_synchronize(); |
| #elif MSVC_VERSION>=1400 |
| _ReadWriteBarrier(); |
| #elif defined(MemoryBarrier) |
| MemoryBarrier(); |
| #endif |
| } |
|
|
| |
| |
| |
| static sqlite3_mutex winMutex_staticMutexes[] = { |
| SQLITE3_MUTEX_INITIALIZER(2), |
| SQLITE3_MUTEX_INITIALIZER(3), |
| SQLITE3_MUTEX_INITIALIZER(4), |
| SQLITE3_MUTEX_INITIALIZER(5), |
| SQLITE3_MUTEX_INITIALIZER(6), |
| SQLITE3_MUTEX_INITIALIZER(7), |
| SQLITE3_MUTEX_INITIALIZER(8), |
| SQLITE3_MUTEX_INITIALIZER(9), |
| SQLITE3_MUTEX_INITIALIZER(10), |
| SQLITE3_MUTEX_INITIALIZER(11), |
| SQLITE3_MUTEX_INITIALIZER(12), |
| SQLITE3_MUTEX_INITIALIZER(13) |
| }; |
|
|
| static int winMutex_isInit = 0; |
| static int winMutex_isNt = -1; |
|
|
| |
| |
| |
| |
| static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0; |
|
|
| int sqlite3_win32_is_nt(void); |
| void sqlite3_win32_sleep(DWORD milliseconds); |
|
|
| static int winMutexInit(void){ |
| |
| if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ |
| int i; |
| for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ |
| InitializeCriticalSection(&winMutex_staticMutexes[i].mutex); |
| } |
| winMutex_isInit = 1; |
| }else{ |
| |
| |
| while( !winMutex_isInit ){ |
| sqlite3_win32_sleep(1); |
| } |
| } |
| return SQLITE_OK; |
| } |
|
|
| static int winMutexEnd(void){ |
| |
| |
| if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){ |
| if( winMutex_isInit==1 ){ |
| int i; |
| for(i=0; i<ArraySize(winMutex_staticMutexes); i++){ |
| DeleteCriticalSection(&winMutex_staticMutexes[i].mutex); |
| } |
| winMutex_isInit = 0; |
| } |
| } |
| return SQLITE_OK; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static sqlite3_mutex *winMutexAlloc(int iType){ |
| sqlite3_mutex *p; |
|
|
| switch( iType ){ |
| case SQLITE_MUTEX_FAST: |
| case SQLITE_MUTEX_RECURSIVE: { |
| p = sqlite3MallocZero( sizeof(*p) ); |
| if( p ){ |
| p->id = iType; |
| #ifdef SQLITE_DEBUG |
| #ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC |
| p->trace = 1; |
| #endif |
| #endif |
| InitializeCriticalSection(&p->mutex); |
| } |
| break; |
| } |
| default: { |
| #ifdef SQLITE_ENABLE_API_ARMOR |
| if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ |
| (void)SQLITE_MISUSE_BKPT; |
| return 0; |
| } |
| #endif |
| p = &winMutex_staticMutexes[iType-2]; |
| #ifdef SQLITE_DEBUG |
| #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC |
| InterlockedCompareExchange(&p->trace, 1, 0); |
| #endif |
| #endif |
| break; |
| } |
| } |
| assert( p==0 || p->id==iType ); |
| return p; |
| } |
|
|
|
|
| |
| |
| |
| |
| |
| static void winMutexFree(sqlite3_mutex *p){ |
| assert( p ); |
| assert( p->nRef==0 && p->owner==0 ); |
| if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){ |
| DeleteCriticalSection(&p->mutex); |
| sqlite3_free(p); |
| }else{ |
| #ifdef SQLITE_ENABLE_API_ARMOR |
| (void)SQLITE_MISUSE_BKPT; |
| #endif |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static void winMutexEnter(sqlite3_mutex *p){ |
| #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) |
| DWORD tid = GetCurrentThreadId(); |
| #endif |
| #ifdef SQLITE_DEBUG |
| 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->nRef++; |
| if( p->trace ){ |
| OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", |
| tid, p->id, p, p->trace, p->nRef)); |
| } |
| #endif |
| } |
|
|
| static int winMutexTry(sqlite3_mutex *p){ |
| #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) ); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #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( p->trace ){ |
| OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n", |
| tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc))); |
| } |
| #endif |
| return rc; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| static void winMutexLeave(sqlite3_mutex *p){ |
| #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 ){ |
| OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n", |
| tid, p->id, p, p->trace, p->nRef)); |
| } |
| #endif |
| } |
|
|
| sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ |
| static const sqlite3_mutex_methods sMutex = { |
| winMutexInit, |
| winMutexEnd, |
| winMutexAlloc, |
| winMutexFree, |
| winMutexEnter, |
| winMutexTry, |
| winMutexLeave, |
| #ifdef SQLITE_DEBUG |
| winMutexHeld, |
| winMutexNotheld |
| #else |
| 0, |
| 0 |
| #endif |
| }; |
| return &sMutex; |
| } |
|
|
| #endif |
|
|