mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-08 05:04:13 +08:00
mdbx: provide SRWL stub for Windows XP/2000.
Change-Id: I438373a4952298efc88ca4c1a92c88e173b82f98
This commit is contained in:
parent
685abc7bcb
commit
9f2bf6a377
@ -779,7 +779,7 @@ struct MDBX_env {
|
|||||||
} me_dbgeo; /* */
|
} me_dbgeo; /* */
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
SRWLOCK me_remap_guard;
|
MDBX_srwlock me_remap_guard;
|
||||||
/* Workaround for LockFileEx and WriteFile multithread bug */
|
/* Workaround for LockFileEx and WriteFile multithread bug */
|
||||||
CRITICAL_SECTION me_windowsbug_lock;
|
CRITICAL_SECTION me_windowsbug_lock;
|
||||||
#else
|
#else
|
||||||
|
@ -156,7 +156,7 @@ void mdbx_txn_unlock(MDBX_env *env) {
|
|||||||
#define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN
|
#define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN
|
||||||
|
|
||||||
int mdbx_rdt_lock(MDBX_env *env) {
|
int mdbx_rdt_lock(MDBX_env *env) {
|
||||||
AcquireSRWLockShared(&env->me_remap_guard);
|
mdbx_srwlock_AcquireShared(&env->me_remap_guard);
|
||||||
if (env->me_lfd == INVALID_HANDLE_VALUE)
|
if (env->me_lfd == INVALID_HANDLE_VALUE)
|
||||||
return MDBX_SUCCESS; /* readonly database in readonly filesystem */
|
return MDBX_SUCCESS; /* readonly database in readonly filesystem */
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ int mdbx_rdt_lock(MDBX_env *env) {
|
|||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
|
|
||||||
int rc = GetLastError();
|
int rc = GetLastError();
|
||||||
ReleaseSRWLockShared(&env->me_remap_guard);
|
mdbx_srwlock_ReleaseShared(&env->me_remap_guard);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ void mdbx_rdt_unlock(MDBX_env *env) {
|
|||||||
if (!funlock(env->me_lfd, LCK_UPPER))
|
if (!funlock(env->me_lfd, LCK_UPPER))
|
||||||
mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError());
|
mdbx_panic("%s failed: errcode %u", mdbx_func_, GetLastError());
|
||||||
}
|
}
|
||||||
ReleaseSRWLockShared(&env->me_remap_guard);
|
mdbx_srwlock_ReleaseShared(&env->me_remap_guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int suspend_and_append(mdbx_handle_array_t **array,
|
static int suspend_and_append(mdbx_handle_array_t **array,
|
||||||
@ -573,3 +573,103 @@ int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Stub for slim read-write lock
|
||||||
|
// Copyright (C) 1995-2002 Brad Wilson
|
||||||
|
|
||||||
|
static void WINAPI stub_srwlock_Init(MDBX_srwlock *srwl) {
|
||||||
|
srwl->readerCount = srwl->writerCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI stub_srwlock_AcquireShared(MDBX_srwlock *srwl) {
|
||||||
|
while (true) {
|
||||||
|
assert(srwl->writerCount >= 0 && srwl->readerCount >= 0);
|
||||||
|
|
||||||
|
// If there's a writer already, spin without unnecessarily
|
||||||
|
// interlocking the CPUs
|
||||||
|
if (srwl->writerCount != 0) {
|
||||||
|
YieldProcessor();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to the readers list
|
||||||
|
_InterlockedIncrement(&srwl->readerCount);
|
||||||
|
|
||||||
|
// Check for writers again (we may have been pre-empted). If
|
||||||
|
// there are no writers writing or waiting, then we're done.
|
||||||
|
if (srwl->writerCount == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Remove from the readers list, spin, try again
|
||||||
|
_InterlockedDecrement(&srwl->readerCount);
|
||||||
|
YieldProcessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI stub_srwlock_ReleaseShared(MDBX_srwlock *srwl) {
|
||||||
|
assert(srwl->readerCount > 0);
|
||||||
|
_InterlockedDecrement(&srwl->readerCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI stub_srwlock_AcquireExclusive(MDBX_srwlock *srwl) {
|
||||||
|
while (true) {
|
||||||
|
assert(srwl->writerCount >= 0 && srwl->readerCount >= 0);
|
||||||
|
|
||||||
|
// If there's a writer already, spin without unnecessarily
|
||||||
|
// interlocking the CPUs
|
||||||
|
if (srwl->writerCount != 0) {
|
||||||
|
YieldProcessor();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we can become the writer (expensive, because it inter-
|
||||||
|
// locks the CPUs, so writing should be an infrequent process)
|
||||||
|
if (_InterlockedExchange(&srwl->writerCount, 1) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (srwl->readerCount != 0) {
|
||||||
|
assert(srwl->writerCount >= 0 && srwl->readerCount >= 0);
|
||||||
|
YieldProcessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI stub_srwlock_ReleaseExclusive(MDBX_srwlock *srwl) {
|
||||||
|
assert(srwl->writerCount == 1 && srwl->readerCount >= 0);
|
||||||
|
srwl->writerCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WINAPI srwlock_thunk_init(MDBX_srwlock *srwl) {
|
||||||
|
HINSTANCE hInst = GetModuleHandleA("kernel32.dll");
|
||||||
|
MDBX_srwlock_function init =
|
||||||
|
(MDBX_srwlock_function)GetProcAddress(hInst, "InitializeSRWLock");
|
||||||
|
if (init != NULL) {
|
||||||
|
mdbx_srwlock_AcquireShared =
|
||||||
|
(MDBX_srwlock_function)GetProcAddress(hInst, "AcquireSRWLockShared");
|
||||||
|
mdbx_srwlock_ReleaseShared =
|
||||||
|
(MDBX_srwlock_function)GetProcAddress(hInst, "ReleaseSRWLockShared");
|
||||||
|
mdbx_srwlock_AcquireExclusive =
|
||||||
|
(MDBX_srwlock_function)GetProcAddress(hInst, "AcquireSRWLockExclusive");
|
||||||
|
mdbx_srwlock_ReleaseExclusive =
|
||||||
|
(MDBX_srwlock_function)GetProcAddress(hInst, "ReleaseSRWLockExclusive");
|
||||||
|
} else {
|
||||||
|
init = stub_srwlock_Init;
|
||||||
|
mdbx_srwlock_AcquireShared = stub_srwlock_AcquireShared;
|
||||||
|
mdbx_srwlock_ReleaseShared = stub_srwlock_ReleaseShared;
|
||||||
|
mdbx_srwlock_AcquireExclusive = stub_srwlock_AcquireExclusive;
|
||||||
|
mdbx_srwlock_ReleaseExclusive = stub_srwlock_ReleaseExclusive;
|
||||||
|
}
|
||||||
|
mdbx_compiler_barrier();
|
||||||
|
mdbx_srwlock_Init = init;
|
||||||
|
mdbx_srwlock_Init(srwl);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDBX_srwlock_function mdbx_srwlock_Init = srwlock_thunk_init;
|
||||||
|
MDBX_srwlock_function mdbx_srwlock_AcquireShared;
|
||||||
|
MDBX_srwlock_function mdbx_srwlock_ReleaseShared;
|
||||||
|
MDBX_srwlock_function mdbx_srwlock_AcquireExclusive;
|
||||||
|
MDBX_srwlock_function mdbx_srwlock_ReleaseExclusive;
|
||||||
|
@ -2003,7 +2003,7 @@ static int mdbx_mapresize(MDBX_env *env, const pgno_t size_pgno,
|
|||||||
/* Acquire guard in exclusive mode for:
|
/* Acquire guard in exclusive mode for:
|
||||||
* - to avoid collision between read and write txns around env->me_dbgeo;
|
* - to avoid collision between read and write txns around env->me_dbgeo;
|
||||||
* - to avoid attachment of new reading threads (see mdbx_rdt_lock); */
|
* - to avoid attachment of new reading threads (see mdbx_rdt_lock); */
|
||||||
AcquireSRWLockExclusive(&env->me_remap_guard);
|
mdbx_srwlock_AcquireExclusive(&env->me_remap_guard);
|
||||||
mdbx_handle_array_t *suspended = NULL;
|
mdbx_handle_array_t *suspended = NULL;
|
||||||
mdbx_handle_array_t array_onstack;
|
mdbx_handle_array_t array_onstack;
|
||||||
int rc = MDBX_SUCCESS;
|
int rc = MDBX_SUCCESS;
|
||||||
@ -2083,7 +2083,7 @@ bailout:
|
|||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
int err = MDBX_SUCCESS;
|
int err = MDBX_SUCCESS;
|
||||||
ReleaseSRWLockExclusive(&env->me_remap_guard);
|
mdbx_srwlock_ReleaseExclusive(&env->me_remap_guard);
|
||||||
if (suspended) {
|
if (suspended) {
|
||||||
err = mdbx_resume_threads_after_remap(suspended);
|
err = mdbx_resume_threads_after_remap(suspended);
|
||||||
if (suspended != &array_onstack)
|
if (suspended != &array_onstack)
|
||||||
@ -4912,7 +4912,7 @@ int __cold mdbx_env_create(MDBX_env **penv) {
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
InitializeSRWLock(&env->me_remap_guard);
|
mdbx_srwlock_Init(&env->me_remap_guard);
|
||||||
InitializeCriticalSection(&env->me_windowsbug_lock);
|
InitializeCriticalSection(&env->me_windowsbug_lock);
|
||||||
#else
|
#else
|
||||||
rc = mdbx_fastmutex_init(&env->me_remap_guard);
|
rc = mdbx_fastmutex_init(&env->me_remap_guard);
|
||||||
|
17
src/osal.h
17
src/osal.h
@ -560,6 +560,23 @@ LIBMDBX_API void mdbx_txn_unlock(MDBX_env *env);
|
|||||||
int mdbx_rpid_set(MDBX_env *env);
|
int mdbx_rpid_set(MDBX_env *env);
|
||||||
int mdbx_rpid_clear(MDBX_env *env);
|
int mdbx_rpid_clear(MDBX_env *env);
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
typedef struct MDBX_srwlock {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
long volatile readerCount;
|
||||||
|
long volatile writerCount;
|
||||||
|
};
|
||||||
|
RTL_SRWLOCK native;
|
||||||
|
};
|
||||||
|
} MDBX_srwlock;
|
||||||
|
|
||||||
|
typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *);
|
||||||
|
extern MDBX_srwlock_function mdbx_srwlock_Init, mdbx_srwlock_AcquireShared,
|
||||||
|
mdbx_srwlock_ReleaseShared, mdbx_srwlock_AcquireExclusive,
|
||||||
|
mdbx_srwlock_ReleaseExclusive;
|
||||||
|
#endif /* Windows */
|
||||||
|
|
||||||
/* Checks reader by pid.
|
/* Checks reader by pid.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user