From 2f45c37320761fd7c5d2aa3dbcabce2fd1749fb4 Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Sun, 10 Nov 2019 23:20:23 +0300 Subject: [PATCH] mdbx-posix: refine locking build-options. Change-Id: I09c0dd453dd39e0105176ad8d9e414e2582849fb --- src/elements/core.c | 38 ++++---- src/elements/internals.h | 81 +++++++++------- src/elements/lck-posix.c | 195 +++++++++++++++++++++------------------ src/elements/osal.h | 2 +- 4 files changed, 171 insertions(+), 145 deletions(-) diff --git a/src/elements/core.c b/src/elements/core.c index 54534bf5..c880c1f7 100644 --- a/src/elements/core.c +++ b/src/elements/core.c @@ -4611,15 +4611,15 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) { #endif /* MDBX_TXN_CHECKPID */ STATIC_ASSERT(sizeof(MDBX_reader) == 32); -#if MDBX_USE_MUTEXES < 0 +#if MDBX_LOCKING > 0 + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_wlock) % MDBX_CACHELINE_SIZE == 0); + STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_rlock) % MDBX_CACHELINE_SIZE == 0); +#else STATIC_ASSERT( offsetof(MDBX_lockinfo, mti_oldest_reader) % MDBX_CACHELINE_SIZE == 0); STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE == 0); -#else - STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_wlock) % MDBX_CACHELINE_SIZE == 0); - STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_rlock) % MDBX_CACHELINE_SIZE == 0); -#endif +#endif /* MDBX_LOCKING */ STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE == 0); @@ -7494,11 +7494,9 @@ int __cold mdbx_env_create(MDBX_env **penv) { goto bailout; } -#if MDBX_USE_MUTEXES == 0 - rc = sem_init(&env->me_lckless_stub.wlock, false, 1) ? errno : MDBX_SUCCESS; -#elif MDBX_USE_MUTEXES > 0 - rc = pthread_mutex_init(&env->me_lckless_stub.wlock, nullptr); -#endif +#if MDBX_LOCKING > 0 + rc = mdbx_ipclock_stub(&env->me_lckless_stub.wlock); +#endif /* MDBX_LOCKING */ if (unlikely(rc != MDBX_SUCCESS)) { mdbx_fastmutex_destroy(&env->me_remap_guard); mdbx_fastmutex_destroy(&env->me_dbi_lock); @@ -8338,9 +8336,9 @@ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname, env->me_discarded_tail = &env->me_lckless_stub.discarded_tail; env->me_meta_sync_txnid = &env->me_lckless_stub.meta_sync_txnid; env->me_maxreaders = UINT_MAX; -#if MDBX_USE_MUTEXES >= 0 +#if MDBX_LOCKING > 0 env->me_wlock = &env->me_lckless_stub.wlock; -#endif +#endif /* MDBX_LOCKING */ mdbx_debug("lck-setup:%s%s%s", " lck-less", (env->me_flags & MDBX_RDONLY) ? " readonly" : "", (rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative"); @@ -8472,9 +8470,9 @@ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname, env->me_autosync_threshold = &lck->mti_autosync_threshold; env->me_discarded_tail = &lck->mti_discarded_tail; env->me_meta_sync_txnid = &lck->mti_meta_sync_txnid; -#if MDBX_USE_MUTEXES >= 0 +#if MDBX_LOCKING > 0 env->me_wlock = &lck->mti_wlock; -#endif +#endif /* MDBX_LOCKING */ return lck_seize_rc; } @@ -8932,11 +8930,9 @@ int __cold mdbx_env_close_ex(MDBX_env *env, int dont_sync) { mdbx_fastmutex_destroy(&env->me_remap_guard) == MDBX_SUCCESS); #endif /* Windows */ -#if MDBX_USE_MUTEXES == 0 - mdbx_ensure(env, sem_destroy(&env->me_lckless_stub.wlock) == 0); -#elif MDBX_USE_MUTEXES > 0 - mdbx_ensure(env, pthread_mutex_destroy(&env->me_lckless_stub.wlock) == 0); -#endif +#if MDBX_LOCKING > 0 + mdbx_ensure(env, mdbx_ipclock_destroy(&env->me_lckless_stub.wlock) == 0); +#endif /* MDBX_LOCKING */ mdbx_ensure(env, env->me_lcklist_next == nullptr); env->me_pid = 0; @@ -15043,7 +15039,7 @@ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) { rdt_locked = -1; if (err == MDBX_RESULT_TRUE) { - /* mutex recovered, the mdbx_mutex_failed() checked all readers */ + /* mutex recovered, the mdbx_ipclock_failed() checked all readers */ rc = MDBX_RESULT_TRUE; break; } @@ -16677,7 +16673,7 @@ __dll_export " MDBX_BUILD_SHARED_LIBRARY=" STRINGIFY(MDBX_BUILD_SHARED_LIBRARY) " WINVER=" STRINGIFY(WINVER) #else /* Windows */ - " MDBX_USE_MUTEXES=" MDBX_USE_MUTEXES_CONFIG + " MDBX_LOCKING=" MDBX_LOCKING_CONFIG " MDBX_USE_OFDLOCKS=" MDBX_USE_OFDLOCKS_CONFIG #endif /* !Windows */ " MDBX_CACHELINE_SIZE=" STRINGIFY(MDBX_CACHELINE_SIZE) diff --git a/src/elements/internals.h b/src/elements/internals.h index 1a2b8be2..f68bdb46 100644 --- a/src/elements/internals.h +++ b/src/elements/internals.h @@ -203,32 +203,37 @@ #define MDBX_64BIT_CAS_CONFIG STRINGIFY(MDBX_64BIT_CAS) #endif /* MDBX_64BIT_CAS */ +#define MDBX_LOCKING_WIN32FILES -1 +#define MDBX_LOCKING_POSIX1988 1988 /* POSIX-1 Shared anonymous semaphores */ +#define MDBX_LOCKING_POSIX2001 2001 /* POSIX-2001 Shared Mutexes */ +#define MDBX_LOCKING_POSIX2008 2008 /* POSIX-2008 Robust Mutexes */ + #if defined(_WIN32) || defined(_WIN64) -#define MDBX_USE_MUTEXES -1 /* Windows don't support POSIX */ +#define MDBX_LOCKING MDBX_LOCKING_WIN32FILES #else -#ifndef MDBX_USE_MUTEXES +#ifndef MDBX_LOCKING #if defined(_POSIX_THREAD_PROCESS_SHARED) && \ _POSIX_THREAD_PROCESS_SHARED >= 200112L && !defined(__FreeBSD__) /* Some platforms define the EOWNERDEAD error code even though they - * don't support Robust Mutexes. If doubt compile with -MDBX_USE_MUTEXES=1. */ + * don't support Robust Mutexes. If doubt compile with -MDBX_LOCKING=2001. */ #if defined(EOWNERDEAD) && _POSIX_THREAD_PROCESS_SHARED >= 200809L && \ (defined(_POSIX_THREAD_ROBUST_PRIO_INHERIT) || \ defined(_POSIX_THREAD_ROBUST_PRIO_PROTECT) || \ defined(PTHREAD_MUTEX_ROBUST) || defined(PTHREAD_MUTEX_ROBUST_NP)) && \ (!defined(__GLIBC__) || \ __GLIBC_PREREQ(2, 10) /* troubles with Robust mutexes before 2.10 */) -#define MDBX_USE_MUTEXES 2 /* use robust shared pthread mutexes */ +#define MDBX_LOCKING MDBX_LOCKING_POSIX2008 #else -#define MDBX_USE_MUTEXES 1 /* use shared pthread mutexes */ +#define MDBX_LOCKING MDBX_LOCKING_POSIX2001 #endif #else -#define MDBX_USE_MUTEXES 0 /* use unnamed shared semaphores */ +#define MDBX_LOCKING MDBX_LOCKING_POSIX1988 #endif -#define MDBX_USE_MUTEXES_CONFIG "AUTO=" STRINGIFY(MDBX_USE_MUTEXES) +#define MDBX_LOCKING_CONFIG "AUTO=" STRINGIFY(MDBX_LOCKING) #else -#define MDBX_USE_MUTEXES_CONFIG STRINGIFY(MDBX_USE_MUTEXES) -#endif /* MDBX_USE_MUTEXES */ +#define MDBX_LOCKING_CONFIG STRINGIFY(MDBX_LOCKING) +#endif /* MDBX_LOCKING */ #endif /* !Windows */ #ifndef MDBX_USE_OFDLOCKS @@ -502,6 +507,25 @@ typedef struct MDBX_page { #pragma pack(pop) +#if MDBX_LOCKING > 0 +#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ + MDBX_LOCKING == MDBX_LOCKING_POSIX2008 +#define MDBX_CLOCK_SIGN UINT32_C(0x8017) +typedef pthread_mutex_t mdbx_ipclock_t; +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988 +#define MDBX_CLOCK_SIGN UINT32_C(0xFC29) +typedef sem_t mdbx_ipclock_t; +#else +#error "FIXME" +#endif + +MDBX_INTERNAL_FUNC int mdbx_ipclock_stub(mdbx_ipclock_t *ipc); +MDBX_INTERNAL_FUNC int mdbx_ipclock_destroy(mdbx_ipclock_t *ipc); + +#else +#define MDBX_CLOCK_SIGN UINT32_C(0xF10C) +#endif /* MDBX_LOCKING */ + /* Reader Lock Table * * Readers don't acquire any locks for their data access. Instead, they @@ -617,16 +641,11 @@ typedef struct MDBX_lockinfo { volatile bin128_t mti_bootid; alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ + /* Write transation lok. */ -#if MDBX_USE_MUTEXES > 0 - pthread_mutex_t mti_wlock; -#define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017) -#elif MDBX_USE_MUTEXES == 0 - sem_t mti_wlock; -#define MDBX_OSAL_LOCK_SIGN UINT32_C(0xFC29) -#else -#define MDBX_OSAL_LOCK_SIGN UINT32_C(0xF10C) -#endif /* MDBX_USE_MUTEXES */ +#if MDBX_LOCKING > 0 + mdbx_ipclock_t mti_wlock; +#endif /* MDBX_LOCKING */ volatile txnid_t mti_oldest_reader; @@ -647,11 +666,9 @@ typedef struct MDBX_lockinfo { alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/ /* Readeaders registration lock. */ -#if MDBX_USE_MUTEXES > 0 - pthread_mutex_t mti_rlock; -#elif MDBX_USE_MUTEXES == 0 - sem_t mti_rlock; -#endif /* MDBX_USE_MUTEXES */ +#if MDBX_LOCKING > 0 + mdbx_ipclock_t mti_rlock; +#endif /* MDBX_LOCKING */ /* The number of slots that have been used in the reader table. * This always records the maximum count, it is not decremented @@ -665,7 +682,7 @@ typedef struct MDBX_lockinfo { /* Lockfile format signature: version, features and field layout */ #define MDBX_LOCK_FORMAT \ - (MDBX_OSAL_LOCK_SIGN * 27733 + (unsigned)sizeof(MDBX_reader) * 13 + \ + (MDBX_CLOCK_SIGN * 27733 + (unsigned)sizeof(MDBX_reader) * 13 + \ (unsigned)offsetof(MDBX_reader, mr_snapshot_pages_used) * 251 + \ (unsigned)offsetof(MDBX_lockinfo, mti_oldest_reader) * 83 + \ (unsigned)offsetof(MDBX_lockinfo, mti_numreaders) * 37 + \ @@ -1003,11 +1020,9 @@ struct MDBX_env { MDBX_txn *me_txn0; /* prealloc'd write transaction */ /* write-txn lock */ -#if MDBX_USE_MUTEXES > 0 - pthread_mutex_t *me_wlock; -#elif MDBX_USE_MUTEXES == 0 - sem_t *me_wlock; -#endif /* MDBX_USE_MUTEXES */ +#if MDBX_LOCKING > 0 + mdbx_ipclock_t *me_wlock; +#endif /* MDBX_LOCKING */ MDBX_dbx *me_dbxs; /* array of static DB info */ uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */ @@ -1033,11 +1048,9 @@ struct MDBX_env { volatile uint32_t *me_meta_sync_txnid; MDBX_oom_func *me_oom_func; /* Callback for kicking laggard readers */ struct { -#if MDBX_USE_MUTEXES > 0 - pthread_mutex_t wlock; -#elif MDBX_USE_MUTEXES == 0 - sem_t wlock; -#endif /* MDBX_USE_MUTEXES */ +#if MDBX_LOCKING > 0 + mdbx_ipclock_t wlock; +#endif /* MDBX_LOCKING */ txnid_t oldest; uint64_t sync_timestamp; uint64_t autosync_period; diff --git a/src/elements/lck-posix.c b/src/elements/lck-posix.c index 68f58c5e..47356ddf 100644 --- a/src/elements/lck-posix.c +++ b/src/elements/lck-posix.c @@ -195,6 +195,30 @@ MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid) { /*---------------------------------------------------------------------------*/ +#if MDBX_LOCKING > 0 +MDBX_INTERNAL_FUNC int mdbx_ipclock_stub(mdbx_ipclock_t *ipc) { +#if MDBX_LOCKING == MDBX_LOCKING_POSIX1988 + return sem_init(ipc, false, 1) ? errno : 0; +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ + MDBX_LOCKING == MDBX_LOCKING_POSIX2008 + return pthread_mutex_init(ipc, nullptr); +#else +#error "FIXME" +#endif +} + +MDBX_INTERNAL_FUNC int mdbx_ipclock_destroy(mdbx_ipclock_t *ipc) { +#if MDBX_LOCKING == MDBX_LOCKING_POSIX1988 + return sem_destroy(ipc) ? errno : 0; +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ + MDBX_LOCKING == MDBX_LOCKING_POSIX2008 + return pthread_mutex_destroy(ipc); +#else +#error "FIXME" +#endif +} +#endif /* MDBX_LOCKING */ + MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) { assert(env->me_fd != INVALID_HANDLE_VALUE); if (unlikely(mdbx_getpid() != env->me_pid)) @@ -339,18 +363,15 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env, lck_op(env->me_fd, op_setlk, (env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0, OFF_T_MAX) == 0) { - mdbx_verbose("%s: got exclusive, drown mutexes", __func__); -#if MDBX_USE_MUTEXES > 0 - rc = pthread_mutex_destroy(&env->me_lck->mti_rlock); - if (rc == 0) - rc = pthread_mutex_destroy(&env->me_lck->mti_wlock); -#else - rc = sem_destroy(&env->me_lck->mti_rlock) ? errno : 0; - if (rc == 0) - rc = sem_destroy(&env->me_lck->mti_wlock) ? errno : 0; -#endif /* MDBX_USE_MUTEXES */ - mdbx_assert(env, rc == 0); + mdbx_verbose("%s: got exclusive, drown locks", __func__); +#if MDBX_LOCKING > 0 + rc = mdbx_ipclock_destroy(&env->me_lck->mti_rlock); + if (rc == 0) + rc = mdbx_ipclock_destroy(&env->me_lck->mti_wlock); +#endif /* MDBX_LOCKING */ + + mdbx_assert(env, rc == 0); if (rc == 0) { mdbx_munmap(&env->me_lck_mmap); rc = ftruncate(env->me_lfd, 0) ? errno : 0; @@ -411,7 +432,7 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env, if LCK already opened/used inside current process */ ; -#if MDBX_USE_MUTEXES == 0 +#if MDBX_LOCKING == MDBX_LOCKING_POSIX1988 /* don't initialize semaphores twice */ if (global_uniqueness_flag == MDBX_RESULT_TRUE) { @@ -422,7 +443,8 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env, } return MDBX_SUCCESS; -#else +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ + MDBX_LOCKING == MDBX_LOCKING_POSIX2008 /* FIXME: Unfortunately, there is no other reliable way but to long testing * on each platform. On the other hand, behavior like FreeBSD is incorrect @@ -453,33 +475,32 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env, if (rc) goto bailout; -#if MDBX_USE_MUTEXES > 1 -#if defined(PTHREAD_MUTEX_ROBUST) +#if MDBX_LOCKING == MDBX_LOCKING_POSIX2008 +#if defined(PTHREAD_MUTEX_ROBUST) || defined(pthread_mutexattr_setrobust) rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); -#elif defined(PTHREAD_MUTEX_ROBUST_NP) +#elif defined(PTHREAD_MUTEX_ROBUST_NP) || \ + defined(pthread_mutexattr_setrobust_np) rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP); -#elif /* defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \ - !defined(pthread_mutex_consistent) && */ \ - _POSIX_C_SOURCE < 200809L +#elif _POSIX_THREAD_PROCESS_SHARED < 200809L rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP); #else rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST); #endif if (rc) goto bailout; -#endif /* MDBX_USE_MUTEXES > 1 (USE_ROBUST) */ +#endif /* MDBX_LOCKING == MDBX_LOCKING_POSIX2008 */ -#if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT > 0 && \ +#if defined(_POSIX_THREAD_PRIO_INHERIT) && _POSIX_THREAD_PRIO_INHERIT >= 0 && \ !defined(MDBX_SAFE4QEMU) rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT); if (rc == ENOTSUP) rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_NONE); - if (rc) + if (rc && rc != ENOTSUP) goto bailout; #endif /* PTHREAD_PRIO_INHERIT */ rc = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK); - if (rc) + if (rc && rc != ENOTSUP) goto bailout; rc = pthread_mutex_init(&env->me_lck->mti_rlock, &ma); @@ -490,18 +511,19 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env, bailout: pthread_mutexattr_destroy(&ma); return rc; -#endif /* MDBX_USE_MUTEXES */ +#else +#error "FIXME" +#endif /* MDBX_LOCKING > 0 */ } -#if MDBX_USE_MUTEXES > 0 -static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, - const int err) { +static int __cold mdbx_ipclock_failed(MDBX_env *env, mdbx_ipclock_t *ipc, + const int err) { int rc = err; -#if MDBX_USE_MUTEXES > 1 +#if MDBX_LOCKING == MDBX_LOCKING_POSIX2008 if (err == EOWNERDEAD) { /* We own the mutex. Clean up after dead previous owner. */ - int rlocked = (env->me_lck && mutex == &env->me_lck->mti_rlock); + const bool rlocked = (env->me_lck && ipc == &env->me_lck->mti_rlock); rc = MDBX_SUCCESS; if (!rlocked) { if (unlikely(env->me_txn)) { @@ -517,11 +539,14 @@ static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, int check_rc = mdbx_reader_check0(env, rlocked, NULL); check_rc = (check_rc == MDBX_SUCCESS) ? MDBX_RESULT_TRUE : check_rc; -#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \ - !defined(pthread_mutex_consistent) && _POSIX_C_SOURCE < 200809L - int mreco_rc = pthread_mutex_consistent_np(mutex); +#if defined(PTHREAD_MUTEX_ROBUST) || defined(pthread_mutex_consistent) + int mreco_rc = pthread_mutex_consistent(ipc); +#elif defined(PTHREAD_MUTEX_ROBUST_NP) || defined(pthread_mutex_consistent_np) + int mreco_rc = pthread_mutex_consistent_np(ipc); +#elif _POSIX_THREAD_PROCESS_SHARED < 200809L + int mreco_rc = pthread_mutex_consistent_np(ipc); #else - int mreco_rc = pthread_mutex_consistent(mutex); + int mreco_rc = pthread_mutex_consistent(ipc); #endif check_rc = (mreco_rc == 0) ? check_rc : mreco_rc; @@ -530,12 +555,16 @@ static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, rc = (rc == MDBX_SUCCESS) ? check_rc : rc; if (MDBX_IS_ERROR(rc)) - pthread_mutex_unlock(mutex); + pthread_mutex_unlock(ipc); return rc; } +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 + (void)ipc; +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988 + (void)ipc; #else - (void)mutex; -#endif /* MDBX_USE_MUTEXES > 1 (USE_ROBUST) */ +#error "FIXME" +#endif /* MDBX_LOCKING */ mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err)); if (rc != EDEADLK) @@ -543,85 +572,73 @@ static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex, return rc; } -static int mdbx_robust_lock(MDBX_env *env, pthread_mutex_t *mutex) { - int rc = pthread_mutex_lock(mutex); - if (unlikely(rc != 0)) - rc = mdbx_mutex_failed(env, mutex, rc); +static int mdbx_ipclock_lock(MDBX_env *env, mdbx_ipclock_t *ipc, + const bool dont_wait) { +#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ + MDBX_LOCKING == MDBX_LOCKING_POSIX2008 + int rc = dont_wait ? pthread_mutex_trylock(ipc) : pthread_mutex_lock(ipc); + rc = (rc == EBUSY && dont_wait) ? MDBX_BUSY : rc; +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988 + int rc = MDBX_SUCCESS; + if (dont_wait) { + if (sem_trywait(ipc)) { + rc = errno; + if (rc == EAGAIN) + rc = MDBX_BUSY; + } + } else if (sem_wait(ipc)) + rc = errno; +#else +#error "FIXME" +#endif /* MDBX_LOCKING */ + + if (unlikely(rc != MDBX_SUCCESS && rc != MDBX_BUSY)) + rc = mdbx_ipclock_failed(env, ipc, rc); return rc; } -static int mdbx_robust_trylock(MDBX_env *env, pthread_mutex_t *mutex) { - int rc = pthread_mutex_trylock(mutex); - if (unlikely(rc != 0 && rc != EBUSY)) - rc = mdbx_mutex_failed(env, mutex, rc); - return (rc != EBUSY) ? rc : MDBX_BUSY; -} - -static int mdbx_robust_unlock(MDBX_env *env, pthread_mutex_t *mutex) { - int rc = pthread_mutex_unlock(mutex); - if (unlikely(rc != 0)) - env->me_flags |= MDBX_FATAL_ERROR; +static int mdbx_ipclock_unlock(mdbx_ipclock_t *ipc) { +#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \ + MDBX_LOCKING == MDBX_LOCKING_POSIX2008 + int rc = pthread_mutex_unlock(ipc); +#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988 + int rc = sem_post(ipc) ? errno : MDBX_SUCCESS; +#else +#error "FIXME" +#endif /* MDBX_LOCKING */ return rc; } -#endif /* MDBX_USE_MUTEXES */ MDBX_INTERNAL_FUNC int mdbx_rdt_lock(MDBX_env *env) { mdbx_trace("%s", ">>"); mdbx_jitter4testing(true); -#if MDBX_USE_MUTEXES > 0 - int rc = mdbx_robust_lock(env, &env->me_lck->mti_rlock); -#else - int rc = sem_wait(&env->me_lck->mti_rlock) ? errno : MDBX_SUCCESS; -#endif /* MDBX_USE_MUTEXES */ + int rc = mdbx_ipclock_lock(env, &env->me_lck->mti_rlock, false); mdbx_trace("<< rc %d", rc); return rc; } MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) { mdbx_trace("%s", ">>"); -#if MDBX_USE_MUTEXES > 0 - int rc = mdbx_robust_unlock(env, &env->me_lck->mti_rlock); -#else - int rc = sem_post(&env->me_lck->mti_rlock) ? errno : MDBX_SUCCESS; -#endif /* MDBX_USE_MUTEXES */ + int rc = mdbx_ipclock_unlock(&env->me_lck->mti_rlock); mdbx_trace("<< rc %d", rc); - if (unlikely(MDBX_IS_ERROR(rc))) + if (unlikely(rc != MDBX_SUCCESS)) mdbx_panic("%s() failed: errcode %d\n", __func__, rc); - else - mdbx_jitter4testing(true); + mdbx_jitter4testing(true); } -int mdbx_txn_lock(MDBX_env *env, bool dontwait) { - mdbx_trace("%s", ">>"); +int mdbx_txn_lock(MDBX_env *env, bool dont_wait) { + mdbx_trace("%swait %s", dont_wait ? "dont-" : "", ">>"); mdbx_jitter4testing(true); -#if MDBX_USE_MUTEXES > 0 - int rc = dontwait ? mdbx_robust_trylock(env, env->me_wlock) - : mdbx_robust_lock(env, env->me_wlock); -#else - int rc = MDBX_SUCCESS; - if (dontwait) { - if (sem_trywait(&env->me_lck->mti_wlock)) { - rc = errno; - if (rc == EAGAIN) - rc = MDBX_BUSY; - } - } else if (sem_wait(&env->me_lck->mti_wlock)) - rc = errno; -#endif /* MDBX_USE_MUTEXES */ + int rc = mdbx_ipclock_lock(env, env->me_wlock, dont_wait); mdbx_trace("<< rc %d", rc); return MDBX_IS_ERROR(rc) ? rc : MDBX_SUCCESS; } void mdbx_txn_unlock(MDBX_env *env) { mdbx_trace("%s", ">>"); -#if MDBX_USE_MUTEXES > 0 - int rc = mdbx_robust_unlock(env, env->me_wlock); -#else - int rc = sem_post(&env->me_lck->mti_wlock) ? errno : MDBX_SUCCESS; -#endif /* MDBX_USE_MUTEXES */ + int rc = mdbx_ipclock_unlock(env->me_wlock); mdbx_trace("<< rc %d", rc); - if (unlikely(MDBX_IS_ERROR(rc))) + if (unlikely(rc != MDBX_SUCCESS)) mdbx_panic("%s() failed: errcode %d\n", __func__, rc); - else - mdbx_jitter4testing(true); + mdbx_jitter4testing(true); } diff --git a/src/elements/osal.h b/src/elements/osal.h index d126b015..8ec1ccf1 100644 --- a/src/elements/osal.h +++ b/src/elements/osal.h @@ -774,7 +774,7 @@ MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env); /// Reading transactions will not be blocked. /// Declared as LIBMDBX_API because it is used in mdbx_chk. /// \return Error code or zero on success -LIBMDBX_API int mdbx_txn_lock(MDBX_env *env, bool dontwait); +LIBMDBX_API int mdbx_txn_lock(MDBX_env *env, bool dont_wait); /// \brief Releases lock once DB changes is made (after writing transaction /// has finished).