diff options
-rw-r--r-- | plugins/Dbx_mdbx/src/libmdbx/src/bits.h | 2 | ||||
-rw-r--r-- | plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c | 70 | ||||
-rw-r--r-- | plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c | 6 | ||||
-rw-r--r-- | plugins/Dbx_mdbx/src/libmdbx/src/osal.h | 12 |
4 files changed, 84 insertions, 6 deletions
diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h index 293de7f80c..6915202ae6 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/bits.h +++ b/plugins/Dbx_mdbx/src/libmdbx/src/bits.h @@ -742,7 +742,7 @@ struct MDBX_env { } me_dbgeo; /* */ #if defined(_WIN32) || defined(_WIN64) - SRWLOCK me_remap_guard; + MDBX_shlock me_remap_guard; #else mdbx_fastmutex_t me_remap_guard; #endif diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c b/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c index c7ce8a17b3..0cd28d3bd4 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c +++ b/plugins/Dbx_mdbx/src/libmdbx/src/lck-windows.c @@ -152,7 +152,7 @@ void mdbx_txn_unlock(MDBX_env *env) { #define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN int mdbx_rdt_lock(MDBX_env *env) { - AcquireSRWLockShared(&env->me_remap_guard); + mdbx_shlock_acquireShared(&env->me_remap_guard); if (env->me_lfd == INVALID_HANDLE_VALUE) return MDBX_SUCCESS; /* readonly database in readonly filesystem */ @@ -168,7 +168,7 @@ void mdbx_rdt_unlock(MDBX_env *env) { if (!funlock(env->me_lfd, LCK_UPPER)) mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError()); } - ReleaseSRWLockShared(&env->me_remap_guard); + mdbx_shlock_releaseShared(&env->me_remap_guard); } static int suspend_and_append(mdbx_handle_array_t **array, @@ -564,3 +564,69 @@ int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) { return rc; } } + +/*----------------------------------------------------------------------------*/ +/* shared lock + Copyright (C) 1995-2002 Brad Wilson +*/ + +void mdbx_shlock_init(MDBX_shlock *lck) +{ + lck->readerCount = lck->writerCount = 0; +} + +void mdbx_shlock_acquireShared(MDBX_shlock *lck) +{ + while (1) { + // If there's a writer already, spin without unnecessarily + // interlocking the CPUs + + if (lck->writerCount != 0) { + YieldProcessor(); + continue; + } + + // Add to the readers list + + _InterlockedIncrement((long*)&lck->readerCount); + + // Check for writers again (we may have been pre-empted). If + // there are no writers writing or waiting, then we're done. + + if (lck->writerCount == 0) + break; + + // Remove from the readers list, spin, try again + + _InterlockedDecrement((long*)&lck->readerCount); + YieldProcessor(); + } +} + +void mdbx_shlock_releaseShared(MDBX_shlock *lck) +{ + _InterlockedDecrement((long*)&lck->readerCount); +} + +void mdbx_shlock_acquireExclusive(MDBX_shlock *lck) +{ + // See if we can become the writer (expensive, because it inter- + // locks the CPUs, so writing should be an infrequent process) + + while (_InterlockedExchange((long*)&lck->writerCount, 1) == 1) { + YieldProcessor(); + } + + // Now we're the writer, but there may be outstanding readers. + // Spin until there aren't any more; new readers will wait now + // that we're the writer. + + while (lck->readerCount != 0) { + YieldProcessor(); + } +} + +void mdbx_shlock_releaseExclusive(MDBX_shlock *lck) +{ + lck->writerCount = 0; +} diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c index 4cb1645ba9..2eafad6155 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c +++ b/plugins/Dbx_mdbx/src/libmdbx/src/mdbx.c @@ -1637,7 +1637,7 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno, /* Acquire guard in exclusive mode for: * - to avoid collision between read and write txns around env->me_dbgeo; * - to avoid attachment of new reading threads (see mdbx_rdt_lock); */ - AcquireSRWLockExclusive(&env->me_remap_guard); + mdbx_shlock_acquireExclusive(&env->me_remap_guard); mdbx_handle_array_t *suspended = NULL; mdbx_handle_array_t array_onstack; int rc = MDBX_SUCCESS; @@ -1712,7 +1712,7 @@ bailout: #if defined(_WIN32) || defined(_WIN64) int err = MDBX_SUCCESS; - ReleaseSRWLockExclusive(&env->me_remap_guard); + mdbx_shlock_releaseExclusive(&env->me_remap_guard); if (suspended) { err = mdbx_resume_threads_after_remap(suspended); if (suspended != &array_onstack) @@ -4436,7 +4436,7 @@ int __cold mdbx_env_create(MDBX_env **penv) { goto bailout; #if defined(_WIN32) || defined(_WIN64) - InitializeSRWLock(&env->me_remap_guard); + mdbx_shlock_init(&env->me_remap_guard); #else rc = mdbx_fastmutex_init(&env->me_remap_guard); if (unlikely(rc != MDBX_SUCCESS)) { diff --git a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h index e84d18cad2..eb6cd5ee10 100644 --- a/plugins/Dbx_mdbx/src/libmdbx/src/osal.h +++ b/plugins/Dbx_mdbx/src/libmdbx/src/osal.h @@ -522,6 +522,18 @@ void mdbx_txn_unlock(MDBX_env *env); int mdbx_rpid_set(MDBX_env *env); int mdbx_rpid_clear(MDBX_env *env); +typedef struct MDBX_shlock +{ + __declspec(align(64)) long volatile readerCount; + __declspec(align(64)) long volatile writerCount; +} MDBX_shlock; + +void mdbx_shlock_init(MDBX_shlock *lck); +void mdbx_shlock_acquireShared(MDBX_shlock *lck); +void mdbx_shlock_releaseShared(MDBX_shlock *lck); +void mdbx_shlock_acquireExclusive(MDBX_shlock *lck); +void mdbx_shlock_releaseExclusive(MDBX_shlock *lck); + /* Checks reader by pid. * * Returns: |