mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-21 21:48:21 +08:00
mdbx-posix: refine locking build-options.
Change-Id: I09c0dd453dd39e0105176ad8d9e414e2582849fb
This commit is contained in:
parent
e2ae62bdb2
commit
2f45c37320
@ -4611,15 +4611,15 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
|||||||
#endif /* MDBX_TXN_CHECKPID */
|
#endif /* MDBX_TXN_CHECKPID */
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(MDBX_reader) == 32);
|
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(
|
STATIC_ASSERT(
|
||||||
offsetof(MDBX_lockinfo, mti_oldest_reader) % MDBX_CACHELINE_SIZE == 0);
|
offsetof(MDBX_lockinfo, mti_oldest_reader) % MDBX_CACHELINE_SIZE == 0);
|
||||||
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE ==
|
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_numreaders) % MDBX_CACHELINE_SIZE ==
|
||||||
0);
|
0);
|
||||||
#else
|
#endif /* MDBX_LOCKING */
|
||||||
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_wlock) % MDBX_CACHELINE_SIZE == 0);
|
|
||||||
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_rlock) % MDBX_CACHELINE_SIZE == 0);
|
|
||||||
#endif
|
|
||||||
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE ==
|
STATIC_ASSERT(offsetof(MDBX_lockinfo, mti_readers) % MDBX_CACHELINE_SIZE ==
|
||||||
0);
|
0);
|
||||||
|
|
||||||
@ -7494,11 +7494,9 @@ int __cold mdbx_env_create(MDBX_env **penv) {
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MDBX_USE_MUTEXES == 0
|
#if MDBX_LOCKING > 0
|
||||||
rc = sem_init(&env->me_lckless_stub.wlock, false, 1) ? errno : MDBX_SUCCESS;
|
rc = mdbx_ipclock_stub(&env->me_lckless_stub.wlock);
|
||||||
#elif MDBX_USE_MUTEXES > 0
|
#endif /* MDBX_LOCKING */
|
||||||
rc = pthread_mutex_init(&env->me_lckless_stub.wlock, nullptr);
|
|
||||||
#endif
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
mdbx_fastmutex_destroy(&env->me_remap_guard);
|
mdbx_fastmutex_destroy(&env->me_remap_guard);
|
||||||
mdbx_fastmutex_destroy(&env->me_dbi_lock);
|
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_discarded_tail = &env->me_lckless_stub.discarded_tail;
|
||||||
env->me_meta_sync_txnid = &env->me_lckless_stub.meta_sync_txnid;
|
env->me_meta_sync_txnid = &env->me_lckless_stub.meta_sync_txnid;
|
||||||
env->me_maxreaders = UINT_MAX;
|
env->me_maxreaders = UINT_MAX;
|
||||||
#if MDBX_USE_MUTEXES >= 0
|
#if MDBX_LOCKING > 0
|
||||||
env->me_wlock = &env->me_lckless_stub.wlock;
|
env->me_wlock = &env->me_lckless_stub.wlock;
|
||||||
#endif
|
#endif /* MDBX_LOCKING */
|
||||||
mdbx_debug("lck-setup:%s%s%s", " lck-less",
|
mdbx_debug("lck-setup:%s%s%s", " lck-less",
|
||||||
(env->me_flags & MDBX_RDONLY) ? " readonly" : "",
|
(env->me_flags & MDBX_RDONLY) ? " readonly" : "",
|
||||||
(rc == MDBX_RESULT_TRUE) ? " exclusive" : " cooperative");
|
(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_autosync_threshold = &lck->mti_autosync_threshold;
|
||||||
env->me_discarded_tail = &lck->mti_discarded_tail;
|
env->me_discarded_tail = &lck->mti_discarded_tail;
|
||||||
env->me_meta_sync_txnid = &lck->mti_meta_sync_txnid;
|
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;
|
env->me_wlock = &lck->mti_wlock;
|
||||||
#endif
|
#endif /* MDBX_LOCKING */
|
||||||
return lck_seize_rc;
|
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);
|
mdbx_fastmutex_destroy(&env->me_remap_guard) == MDBX_SUCCESS);
|
||||||
#endif /* Windows */
|
#endif /* Windows */
|
||||||
|
|
||||||
#if MDBX_USE_MUTEXES == 0
|
#if MDBX_LOCKING > 0
|
||||||
mdbx_ensure(env, sem_destroy(&env->me_lckless_stub.wlock) == 0);
|
mdbx_ensure(env, mdbx_ipclock_destroy(&env->me_lckless_stub.wlock) == 0);
|
||||||
#elif MDBX_USE_MUTEXES > 0
|
#endif /* MDBX_LOCKING */
|
||||||
mdbx_ensure(env, pthread_mutex_destroy(&env->me_lckless_stub.wlock) == 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mdbx_ensure(env, env->me_lcklist_next == nullptr);
|
mdbx_ensure(env, env->me_lcklist_next == nullptr);
|
||||||
env->me_pid = 0;
|
env->me_pid = 0;
|
||||||
@ -15043,7 +15039,7 @@ int __cold mdbx_reader_check0(MDBX_env *env, int rdt_locked, int *dead) {
|
|||||||
|
|
||||||
rdt_locked = -1;
|
rdt_locked = -1;
|
||||||
if (err == MDBX_RESULT_TRUE) {
|
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;
|
rc = MDBX_RESULT_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -16677,7 +16673,7 @@ __dll_export
|
|||||||
" MDBX_BUILD_SHARED_LIBRARY=" STRINGIFY(MDBX_BUILD_SHARED_LIBRARY)
|
" MDBX_BUILD_SHARED_LIBRARY=" STRINGIFY(MDBX_BUILD_SHARED_LIBRARY)
|
||||||
" WINVER=" STRINGIFY(WINVER)
|
" WINVER=" STRINGIFY(WINVER)
|
||||||
#else /* Windows */
|
#else /* Windows */
|
||||||
" MDBX_USE_MUTEXES=" MDBX_USE_MUTEXES_CONFIG
|
" MDBX_LOCKING=" MDBX_LOCKING_CONFIG
|
||||||
" MDBX_USE_OFDLOCKS=" MDBX_USE_OFDLOCKS_CONFIG
|
" MDBX_USE_OFDLOCKS=" MDBX_USE_OFDLOCKS_CONFIG
|
||||||
#endif /* !Windows */
|
#endif /* !Windows */
|
||||||
" MDBX_CACHELINE_SIZE=" STRINGIFY(MDBX_CACHELINE_SIZE)
|
" MDBX_CACHELINE_SIZE=" STRINGIFY(MDBX_CACHELINE_SIZE)
|
||||||
|
@ -203,32 +203,37 @@
|
|||||||
#define MDBX_64BIT_CAS_CONFIG STRINGIFY(MDBX_64BIT_CAS)
|
#define MDBX_64BIT_CAS_CONFIG STRINGIFY(MDBX_64BIT_CAS)
|
||||||
#endif /* 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)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
#define MDBX_USE_MUTEXES -1 /* Windows don't support POSIX */
|
#define MDBX_LOCKING MDBX_LOCKING_WIN32FILES
|
||||||
#else
|
#else
|
||||||
#ifndef MDBX_USE_MUTEXES
|
#ifndef MDBX_LOCKING
|
||||||
#if defined(_POSIX_THREAD_PROCESS_SHARED) && \
|
#if defined(_POSIX_THREAD_PROCESS_SHARED) && \
|
||||||
_POSIX_THREAD_PROCESS_SHARED >= 200112L && !defined(__FreeBSD__)
|
_POSIX_THREAD_PROCESS_SHARED >= 200112L && !defined(__FreeBSD__)
|
||||||
|
|
||||||
/* Some platforms define the EOWNERDEAD error code even though they
|
/* 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 && \
|
#if defined(EOWNERDEAD) && _POSIX_THREAD_PROCESS_SHARED >= 200809L && \
|
||||||
(defined(_POSIX_THREAD_ROBUST_PRIO_INHERIT) || \
|
(defined(_POSIX_THREAD_ROBUST_PRIO_INHERIT) || \
|
||||||
defined(_POSIX_THREAD_ROBUST_PRIO_PROTECT) || \
|
defined(_POSIX_THREAD_ROBUST_PRIO_PROTECT) || \
|
||||||
defined(PTHREAD_MUTEX_ROBUST) || defined(PTHREAD_MUTEX_ROBUST_NP)) && \
|
defined(PTHREAD_MUTEX_ROBUST) || defined(PTHREAD_MUTEX_ROBUST_NP)) && \
|
||||||
(!defined(__GLIBC__) || \
|
(!defined(__GLIBC__) || \
|
||||||
__GLIBC_PREREQ(2, 10) /* troubles with Robust mutexes before 2.10 */)
|
__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
|
#else
|
||||||
#define MDBX_USE_MUTEXES 1 /* use shared pthread mutexes */
|
#define MDBX_LOCKING MDBX_LOCKING_POSIX2001
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define MDBX_USE_MUTEXES 0 /* use unnamed shared semaphores */
|
#define MDBX_LOCKING MDBX_LOCKING_POSIX1988
|
||||||
#endif
|
#endif
|
||||||
#define MDBX_USE_MUTEXES_CONFIG "AUTO=" STRINGIFY(MDBX_USE_MUTEXES)
|
#define MDBX_LOCKING_CONFIG "AUTO=" STRINGIFY(MDBX_LOCKING)
|
||||||
#else
|
#else
|
||||||
#define MDBX_USE_MUTEXES_CONFIG STRINGIFY(MDBX_USE_MUTEXES)
|
#define MDBX_LOCKING_CONFIG STRINGIFY(MDBX_LOCKING)
|
||||||
#endif /* MDBX_USE_MUTEXES */
|
#endif /* MDBX_LOCKING */
|
||||||
#endif /* !Windows */
|
#endif /* !Windows */
|
||||||
|
|
||||||
#ifndef MDBX_USE_OFDLOCKS
|
#ifndef MDBX_USE_OFDLOCKS
|
||||||
@ -502,6 +507,25 @@ typedef struct MDBX_page {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#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
|
/* Reader Lock Table
|
||||||
*
|
*
|
||||||
* Readers don't acquire any locks for their data access. Instead, they
|
* 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;
|
volatile bin128_t mti_bootid;
|
||||||
|
|
||||||
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
||||||
|
|
||||||
/* Write transation lok. */
|
/* Write transation lok. */
|
||||||
#if MDBX_USE_MUTEXES > 0
|
#if MDBX_LOCKING > 0
|
||||||
pthread_mutex_t mti_wlock;
|
mdbx_ipclock_t mti_wlock;
|
||||||
#define MDBX_OSAL_LOCK_SIGN UINT32_C(0x8017)
|
#endif /* MDBX_LOCKING */
|
||||||
#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 */
|
|
||||||
|
|
||||||
volatile txnid_t mti_oldest_reader;
|
volatile txnid_t mti_oldest_reader;
|
||||||
|
|
||||||
@ -647,11 +666,9 @@ typedef struct MDBX_lockinfo {
|
|||||||
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
alignas(MDBX_CACHELINE_SIZE) /* cacheline ---------------------------------*/
|
||||||
|
|
||||||
/* Readeaders registration lock. */
|
/* Readeaders registration lock. */
|
||||||
#if MDBX_USE_MUTEXES > 0
|
#if MDBX_LOCKING > 0
|
||||||
pthread_mutex_t mti_rlock;
|
mdbx_ipclock_t mti_rlock;
|
||||||
#elif MDBX_USE_MUTEXES == 0
|
#endif /* MDBX_LOCKING */
|
||||||
sem_t mti_rlock;
|
|
||||||
#endif /* MDBX_USE_MUTEXES */
|
|
||||||
|
|
||||||
/* The number of slots that have been used in the reader table.
|
/* The number of slots that have been used in the reader table.
|
||||||
* This always records the maximum count, it is not decremented
|
* 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 */
|
/* Lockfile format signature: version, features and field layout */
|
||||||
#define MDBX_LOCK_FORMAT \
|
#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_reader, mr_snapshot_pages_used) * 251 + \
|
||||||
(unsigned)offsetof(MDBX_lockinfo, mti_oldest_reader) * 83 + \
|
(unsigned)offsetof(MDBX_lockinfo, mti_oldest_reader) * 83 + \
|
||||||
(unsigned)offsetof(MDBX_lockinfo, mti_numreaders) * 37 + \
|
(unsigned)offsetof(MDBX_lockinfo, mti_numreaders) * 37 + \
|
||||||
@ -1003,11 +1020,9 @@ struct MDBX_env {
|
|||||||
MDBX_txn *me_txn0; /* prealloc'd write transaction */
|
MDBX_txn *me_txn0; /* prealloc'd write transaction */
|
||||||
|
|
||||||
/* write-txn lock */
|
/* write-txn lock */
|
||||||
#if MDBX_USE_MUTEXES > 0
|
#if MDBX_LOCKING > 0
|
||||||
pthread_mutex_t *me_wlock;
|
mdbx_ipclock_t *me_wlock;
|
||||||
#elif MDBX_USE_MUTEXES == 0
|
#endif /* MDBX_LOCKING */
|
||||||
sem_t *me_wlock;
|
|
||||||
#endif /* MDBX_USE_MUTEXES */
|
|
||||||
|
|
||||||
MDBX_dbx *me_dbxs; /* array of static DB info */
|
MDBX_dbx *me_dbxs; /* array of static DB info */
|
||||||
uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */
|
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;
|
volatile uint32_t *me_meta_sync_txnid;
|
||||||
MDBX_oom_func *me_oom_func; /* Callback for kicking laggard readers */
|
MDBX_oom_func *me_oom_func; /* Callback for kicking laggard readers */
|
||||||
struct {
|
struct {
|
||||||
#if MDBX_USE_MUTEXES > 0
|
#if MDBX_LOCKING > 0
|
||||||
pthread_mutex_t wlock;
|
mdbx_ipclock_t wlock;
|
||||||
#elif MDBX_USE_MUTEXES == 0
|
#endif /* MDBX_LOCKING */
|
||||||
sem_t wlock;
|
|
||||||
#endif /* MDBX_USE_MUTEXES */
|
|
||||||
txnid_t oldest;
|
txnid_t oldest;
|
||||||
uint64_t sync_timestamp;
|
uint64_t sync_timestamp;
|
||||||
uint64_t autosync_period;
|
uint64_t autosync_period;
|
||||||
|
@ -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) {
|
MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) {
|
||||||
assert(env->me_fd != INVALID_HANDLE_VALUE);
|
assert(env->me_fd != INVALID_HANDLE_VALUE);
|
||||||
if (unlikely(mdbx_getpid() != env->me_pid))
|
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,
|
lck_op(env->me_fd, op_setlk,
|
||||||
(env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0,
|
(env->me_flags & MDBX_RDONLY) ? F_RDLCK : F_WRLCK, 0,
|
||||||
OFF_T_MAX) == 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) {
|
if (rc == 0) {
|
||||||
mdbx_munmap(&env->me_lck_mmap);
|
mdbx_munmap(&env->me_lck_mmap);
|
||||||
rc = ftruncate(env->me_lfd, 0) ? errno : 0;
|
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 LCK already opened/used inside current process */
|
||||||
;
|
;
|
||||||
|
|
||||||
#if MDBX_USE_MUTEXES == 0
|
#if MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
||||||
|
|
||||||
/* don't initialize semaphores twice */
|
/* don't initialize semaphores twice */
|
||||||
if (global_uniqueness_flag == MDBX_RESULT_TRUE) {
|
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;
|
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
|
/* FIXME: Unfortunately, there is no other reliable way but to long testing
|
||||||
* on each platform. On the other hand, behavior like FreeBSD is incorrect
|
* 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)
|
if (rc)
|
||||||
goto bailout;
|
goto bailout;
|
||||||
|
|
||||||
#if MDBX_USE_MUTEXES > 1
|
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
||||||
#if defined(PTHREAD_MUTEX_ROBUST)
|
#if defined(PTHREAD_MUTEX_ROBUST) || defined(pthread_mutexattr_setrobust)
|
||||||
rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
|
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);
|
rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP);
|
||||||
#elif /* defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \
|
#elif _POSIX_THREAD_PROCESS_SHARED < 200809L
|
||||||
!defined(pthread_mutex_consistent) && */ \
|
|
||||||
_POSIX_C_SOURCE < 200809L
|
|
||||||
rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP);
|
rc = pthread_mutexattr_setrobust_np(&ma, PTHREAD_MUTEX_ROBUST_NP);
|
||||||
#else
|
#else
|
||||||
rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
|
rc = pthread_mutexattr_setrobust(&ma, PTHREAD_MUTEX_ROBUST);
|
||||||
#endif
|
#endif
|
||||||
if (rc)
|
if (rc)
|
||||||
goto bailout;
|
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)
|
!defined(MDBX_SAFE4QEMU)
|
||||||
rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT);
|
rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT);
|
||||||
if (rc == ENOTSUP)
|
if (rc == ENOTSUP)
|
||||||
rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_NONE);
|
rc = pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_NONE);
|
||||||
if (rc)
|
if (rc && rc != ENOTSUP)
|
||||||
goto bailout;
|
goto bailout;
|
||||||
#endif /* PTHREAD_PRIO_INHERIT */
|
#endif /* PTHREAD_PRIO_INHERIT */
|
||||||
|
|
||||||
rc = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
|
rc = pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_ERRORCHECK);
|
||||||
if (rc)
|
if (rc && rc != ENOTSUP)
|
||||||
goto bailout;
|
goto bailout;
|
||||||
|
|
||||||
rc = pthread_mutex_init(&env->me_lck->mti_rlock, &ma);
|
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:
|
bailout:
|
||||||
pthread_mutexattr_destroy(&ma);
|
pthread_mutexattr_destroy(&ma);
|
||||||
return rc;
|
return rc;
|
||||||
#endif /* MDBX_USE_MUTEXES */
|
#else
|
||||||
|
#error "FIXME"
|
||||||
|
#endif /* MDBX_LOCKING > 0 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MDBX_USE_MUTEXES > 0
|
static int __cold mdbx_ipclock_failed(MDBX_env *env, mdbx_ipclock_t *ipc,
|
||||||
static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex,
|
|
||||||
const int err) {
|
const int err) {
|
||||||
int rc = err;
|
int rc = err;
|
||||||
#if MDBX_USE_MUTEXES > 1
|
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
||||||
if (err == EOWNERDEAD) {
|
if (err == EOWNERDEAD) {
|
||||||
/* We own the mutex. Clean up after dead previous owner. */
|
/* 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;
|
rc = MDBX_SUCCESS;
|
||||||
if (!rlocked) {
|
if (!rlocked) {
|
||||||
if (unlikely(env->me_txn)) {
|
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);
|
int check_rc = mdbx_reader_check0(env, rlocked, NULL);
|
||||||
check_rc = (check_rc == MDBX_SUCCESS) ? MDBX_RESULT_TRUE : check_rc;
|
check_rc = (check_rc == MDBX_SUCCESS) ? MDBX_RESULT_TRUE : check_rc;
|
||||||
|
|
||||||
#if defined(__GLIBC__) && !__GLIBC_PREREQ(2, 12) && \
|
#if defined(PTHREAD_MUTEX_ROBUST) || defined(pthread_mutex_consistent)
|
||||||
!defined(pthread_mutex_consistent) && _POSIX_C_SOURCE < 200809L
|
int mreco_rc = pthread_mutex_consistent(ipc);
|
||||||
int mreco_rc = pthread_mutex_consistent_np(mutex);
|
#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
|
#else
|
||||||
int mreco_rc = pthread_mutex_consistent(mutex);
|
int mreco_rc = pthread_mutex_consistent(ipc);
|
||||||
#endif
|
#endif
|
||||||
check_rc = (mreco_rc == 0) ? check_rc : mreco_rc;
|
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;
|
rc = (rc == MDBX_SUCCESS) ? check_rc : rc;
|
||||||
if (MDBX_IS_ERROR(rc))
|
if (MDBX_IS_ERROR(rc))
|
||||||
pthread_mutex_unlock(mutex);
|
pthread_mutex_unlock(ipc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001
|
||||||
|
(void)ipc;
|
||||||
|
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
||||||
|
(void)ipc;
|
||||||
#else
|
#else
|
||||||
(void)mutex;
|
#error "FIXME"
|
||||||
#endif /* MDBX_USE_MUTEXES > 1 (USE_ROBUST) */
|
#endif /* MDBX_LOCKING */
|
||||||
|
|
||||||
mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err));
|
mdbx_error("mutex (un)lock failed, %s", mdbx_strerror(err));
|
||||||
if (rc != EDEADLK)
|
if (rc != EDEADLK)
|
||||||
@ -543,85 +572,73 @@ static int __cold mdbx_mutex_failed(MDBX_env *env, pthread_mutex_t *mutex,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mdbx_robust_lock(MDBX_env *env, pthread_mutex_t *mutex) {
|
static int mdbx_ipclock_lock(MDBX_env *env, mdbx_ipclock_t *ipc,
|
||||||
int rc = pthread_mutex_lock(mutex);
|
const bool dont_wait) {
|
||||||
if (unlikely(rc != 0))
|
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
|
||||||
rc = mdbx_mutex_failed(env, mutex, rc);
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mdbx_robust_trylock(MDBX_env *env, pthread_mutex_t *mutex) {
|
static int mdbx_ipclock_unlock(mdbx_ipclock_t *ipc) {
|
||||||
int rc = pthread_mutex_trylock(mutex);
|
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
|
||||||
if (unlikely(rc != 0 && rc != EBUSY))
|
MDBX_LOCKING == MDBX_LOCKING_POSIX2008
|
||||||
rc = mdbx_mutex_failed(env, mutex, rc);
|
int rc = pthread_mutex_unlock(ipc);
|
||||||
return (rc != EBUSY) ? rc : MDBX_BUSY;
|
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
|
||||||
}
|
int rc = sem_post(ipc) ? errno : MDBX_SUCCESS;
|
||||||
|
#else
|
||||||
static int mdbx_robust_unlock(MDBX_env *env, pthread_mutex_t *mutex) {
|
#error "FIXME"
|
||||||
int rc = pthread_mutex_unlock(mutex);
|
#endif /* MDBX_LOCKING */
|
||||||
if (unlikely(rc != 0))
|
|
||||||
env->me_flags |= MDBX_FATAL_ERROR;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif /* MDBX_USE_MUTEXES */
|
|
||||||
|
|
||||||
MDBX_INTERNAL_FUNC int mdbx_rdt_lock(MDBX_env *env) {
|
MDBX_INTERNAL_FUNC int mdbx_rdt_lock(MDBX_env *env) {
|
||||||
mdbx_trace("%s", ">>");
|
mdbx_trace("%s", ">>");
|
||||||
mdbx_jitter4testing(true);
|
mdbx_jitter4testing(true);
|
||||||
#if MDBX_USE_MUTEXES > 0
|
int rc = mdbx_ipclock_lock(env, &env->me_lck->mti_rlock, false);
|
||||||
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 */
|
|
||||||
mdbx_trace("<< rc %d", rc);
|
mdbx_trace("<< rc %d", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) {
|
MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) {
|
||||||
mdbx_trace("%s", ">>");
|
mdbx_trace("%s", ">>");
|
||||||
#if MDBX_USE_MUTEXES > 0
|
int rc = mdbx_ipclock_unlock(&env->me_lck->mti_rlock);
|
||||||
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 */
|
|
||||||
mdbx_trace("<< rc %d", rc);
|
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);
|
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) {
|
int mdbx_txn_lock(MDBX_env *env, bool dont_wait) {
|
||||||
mdbx_trace("%s", ">>");
|
mdbx_trace("%swait %s", dont_wait ? "dont-" : "", ">>");
|
||||||
mdbx_jitter4testing(true);
|
mdbx_jitter4testing(true);
|
||||||
#if MDBX_USE_MUTEXES > 0
|
int rc = mdbx_ipclock_lock(env, env->me_wlock, dont_wait);
|
||||||
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 */
|
|
||||||
mdbx_trace("<< rc %d", rc);
|
mdbx_trace("<< rc %d", rc);
|
||||||
return MDBX_IS_ERROR(rc) ? rc : MDBX_SUCCESS;
|
return MDBX_IS_ERROR(rc) ? rc : MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mdbx_txn_unlock(MDBX_env *env) {
|
void mdbx_txn_unlock(MDBX_env *env) {
|
||||||
mdbx_trace("%s", ">>");
|
mdbx_trace("%s", ">>");
|
||||||
#if MDBX_USE_MUTEXES > 0
|
int rc = mdbx_ipclock_unlock(env->me_wlock);
|
||||||
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 */
|
|
||||||
mdbx_trace("<< rc %d", rc);
|
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);
|
mdbx_panic("%s() failed: errcode %d\n", __func__, rc);
|
||||||
else
|
|
||||||
mdbx_jitter4testing(true);
|
mdbx_jitter4testing(true);
|
||||||
}
|
}
|
||||||
|
@ -774,7 +774,7 @@ MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env);
|
|||||||
/// Reading transactions will not be blocked.
|
/// Reading transactions will not be blocked.
|
||||||
/// Declared as LIBMDBX_API because it is used in mdbx_chk.
|
/// Declared as LIBMDBX_API because it is used in mdbx_chk.
|
||||||
/// \return Error code or zero on success
|
/// \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
|
/// \brief Releases lock once DB changes is made (after writing transaction
|
||||||
/// has finished).
|
/// has finished).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user