-C Attempt\sto\salign\sinstances\sof\sthe\ssqlite3_mutex\sobject\sat\s128-byte\sboundaries\nto\sprevent\sfalse-sharing\sin\smulti-core\smachines.\sSee\sthe\sdiscussion\sat\sand\naround\s[forum:/forumpost/2026-03-25T23:15:03Z|forum\spost\s2026-03-25T23:15:03Z].
-D 2026-04-28T15:12:40.363
+C Updates\sand\ssimplifications\sto\sthe\smutex\simplementation\son\sWindows.\s\sUses\nSlim\sReader/Writer\sLocks\sfor\sperformance,\sfor\snon-reentrant\smutexes.\nRequires\sWindowsVista\sor\slater.
+D 2026-04-28T20:01:03.205
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c 9dce885059f9d2bb226e6e03bb2b41af4b89d40c323f908b58f5d05ff0565884
-F src/mutex_w32.c cd49a5772f1bfd174e22a0c783ba514a871a3a7089f90d7337019c32fecca94b
+F src/mutex_w32.c 6eb3fc28172d267c4a6a92ef09f557ac8bcebc01ac5638a2bb528c492011dff6
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P d64a1dbe0fb2d9286806d833a3146b21d5bf1636a650d5a64cf163c7f2356e98
-R e7f5576deb3afe7b12491989f716c8e2
+P 1786fcd5b4ee6cd9b4780f3687dfaec5b90ef0476e0da266a94e069b98e70514
+R 86e1ad059a85bf06401a6419341a6e82
+T *branch * win-mutex-revamp
+T *sym-win-mutex-revamp *
+T -sym-trunk *
U drh
-Z 8f2b29d8666e7ca0a228448a291e99d6
+Z 2cf5e98ef789e1ee6f49efcdd7196e10
# Remove this line to create a well-formed Fossil manifest.
# define ALIGN128
#endif
+#pragma warning(push)
+#pragma warning(disable: 4324)
/*
** Each SQLite mutex is an instance of the following structure.
**
** that 64 works just as well most of the time, but the internet says
** that 128-byte alignment works better.
*/
-struct ALIGN128 sqlite3_mutex {
- CRITICAL_SECTION mutex; /* Mutex controlling the lock */
+struct ALIGN128 sqlite3_mutex {
+ union {
+ CRITICAL_SECTION cs; /* The CRITICAL_SECTION mutex. id==1 */
+ SRWLOCK srwl; /* The Slim reader/writer lock. id!=1 */
+ } u;
int id; /* Mutex type */
#ifdef SQLITE_DEBUG
volatile int nRef; /* Number of entrances */
volatile LONG trace; /* True to trace changes */
#endif
};
-
-/*
-** 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.
-*/
-#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
+#pragma warning(pop)
#ifdef SQLITE_DEBUG
/*
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);
+ return p->nRef==0 || p->owner!=GetCurrentThreadId();
}
#endif
/*
** Initialize and deinitialize the mutex subsystem.
*/
-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 sqlite3_mutex winMutex_staticMutexes[12];
static int winMutex_isInit = 0;
-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
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
int i;
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
- InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
+ sqlite3_mutex *p = &winMutex_staticMutexes[i];
+ p->id = i+2;
+ InitializeSRWLock(&p->u.srwl);
+#ifdef SQLITE_DEBUG
+ p->nRef = 0;
+ p->owner = 0;
+ p->trace = 0;
+#endif
}
winMutex_isInit = 1;
}else{
** (which should be the last to shutdown.) */
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;
}
}
p->trace = 1;
#endif
#endif
- InitializeCriticalSection(&p->mutex);
+ if( iType==SQLITE_MUTEX_RECURSIVE ){
+ InitializeCriticalSection(&p->u.cs);
+ }else{
+ InitializeSRWLock(&p->u.srwl);
+ }
}
break;
}
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);
+ if( p->id==SQLITE_MUTEX_FAST ){
+ sqlite3_free(p);
+ }else if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ DeleteCriticalSection(&p->u.cs);
sqlite3_free(p);
}else{
#ifdef SQLITE_ENABLE_API_ARMOR
** 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
- assert( p );
- assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
-#else
assert( p );
+#ifdef SQLITE_DEBUG
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
#endif
assert( winMutex_isInit==1 );
- EnterCriticalSection(&p->mutex);
+ if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ EnterCriticalSection(&p->u.cs);
+ }else{
+ AcquireSRWLockExclusive(&p->u.srwl);
+ }
#ifdef SQLITE_DEBUG
assert( p->nRef>0 || p->owner==0 );
- p->owner = tid;
+ p->owner = GetCurrentThreadId();
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));
+ GetCurrentThreadId(), 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) );
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
/*
- ** 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
+ ** The sqlite3_mutex_try() routine is seldom used, and when it is
+ ** used it is merely an optimization. So it is OK for it to always
** fail.
- **
- ** The TryEnterCriticalSection() interface is only available on WinNT.
- ** And some windows compilers complain if you try to use it without
- ** first doing some #defines that prevent SQLite from building on Win98.
- ** For that reason, we will omit this optimization for now. See
- ** ticket #2685.
*/
-#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();
+ if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ rc = TryEnterCriticalSection(&p->u.cs);
+ }else{
+ rc = TryAcquireSRWLockExclusive(&p->u.srwl);
}
- assert( winMutex_isNt==0 || winMutex_isNt==1 );
- if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
+ if( rc ){
#ifdef SQLITE_DEBUG
- p->owner = tid;
+ p->owner = GetCurrentThreadId();
p->nRef++;
#endif
rc = SQLITE_OK;
+ }else{
+ rc = SQLITE_BUSY;
}
-#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)));
+ OSTRACE((
+ "TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
+ GetCurrentThreadId(), p->id, p, p->trace, p->owner, p->nRef,
+ sqlite3ErrName(rc)));
}
#endif
return rc;
** is not currently allocated. SQLite will never do either.
*/
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 );
+ assert( p->owner==GetCurrentThreadId() );
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);
+ if( p->id==SQLITE_MUTEX_RECURSIVE ){
+ LeaveCriticalSection(&p->u.cs);
+ }else{
+ ReleaseSRWLockExclusive(&p->u.srwl);
+ }
#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));
+ GetCurrentThreadId(), p->id, p, p->trace, p->nRef));
}
#endif
}