mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 00:54:14 +08:00
mdbx: use single pointer to lck-less stub.
Change-Id: I80542423386bd54cac574d1678af2620f147c769
This commit is contained in:
parent
7d249c97ad
commit
e57e42d0f8
402
src/core.c
402
src/core.c
File diff suppressed because it is too large
Load Diff
@ -1133,7 +1133,7 @@ struct MDBX_env {
|
||||
mdbx_filehandle_t me_dsync_fd;
|
||||
mdbx_mmap_t me_lck_mmap; /* The lock file */
|
||||
#define me_lfd me_lck_mmap.fd
|
||||
#define me_lck me_lck_mmap.lck
|
||||
struct MDBX_lockinfo *me_lck;
|
||||
|
||||
unsigned me_psize; /* DB page size, initialized from me_os_psize */
|
||||
unsigned me_leaf_nodemax; /* max size of a leaf-node */
|
||||
@ -1148,25 +1148,15 @@ struct MDBX_env {
|
||||
void *me_pbuf; /* scratch area for DUPSORT put() */
|
||||
MDBX_txn *me_txn0; /* prealloc'd write transaction */
|
||||
|
||||
MDBX_dbx *me_dbxs; /* array of static DB info */
|
||||
uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */
|
||||
unsigned *me_dbiseqs; /* array of dbi sequence numbers */
|
||||
atomic_txnid_t *me_oldest; /* ID of oldest reader last time we looked */
|
||||
/* Number of freelist items that can fit in a single overflow page */
|
||||
unsigned me_maxgc_ov1page;
|
||||
MDBX_dbx *me_dbxs; /* array of static DB info */
|
||||
uint16_t *me_dbflags; /* array of flags from MDBX_db.md_flags */
|
||||
unsigned *me_dbiseqs; /* array of dbi sequence numbers */
|
||||
unsigned
|
||||
me_maxgc_ov1page; /* Number of pgno_t fit in a single overflow page */
|
||||
uint32_t me_live_reader; /* have liveness lock in reader table */
|
||||
void *me_userctx; /* User-settable context */
|
||||
MDBX_atomic_uint64_t *me_sync_timestamp;
|
||||
MDBX_atomic_uint64_t *me_autosync_period;
|
||||
atomic_pgno_t *me_unsynced_pages;
|
||||
atomic_pgno_t *me_autosync_threshold;
|
||||
atomic_pgno_t *me_discarded_tail;
|
||||
pgno_t *me_readahead_anchor;
|
||||
MDBX_atomic_uint32_t *me_meta_sync_txnid;
|
||||
#if MDBX_ENABLE_PGOP_STAT
|
||||
MDBX_pgop_stat_t *me_pgop_stat;
|
||||
#endif /* MDBX_ENABLE_PGOP_STAT*/
|
||||
MDBX_hsr_func *me_hsr_callback; /* Callback for kicking laggard readers */
|
||||
|
||||
struct {
|
||||
unsigned dp_reserve_limit;
|
||||
unsigned rp_augment_limit;
|
||||
@ -1216,11 +1206,6 @@ struct MDBX_env {
|
||||
/* PNL of pages that became unused in a write txn */
|
||||
MDBX_PNL me_retired_pages;
|
||||
|
||||
/* write-txn lock */
|
||||
#if MDBX_LOCKING > 0
|
||||
mdbx_ipclock_t *me_wlock;
|
||||
#endif /* MDBX_LOCKING > 0 */
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
MDBX_srwlock me_remap_guard;
|
||||
/* Workaround for LockFileEx and WriteFile multithread bug */
|
||||
@ -1229,23 +1214,6 @@ struct MDBX_env {
|
||||
mdbx_fastmutex_t me_remap_guard;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
#if MDBX_LOCKING > 0
|
||||
mdbx_ipclock_t wlock;
|
||||
#endif /* MDBX_LOCKING > 0 */
|
||||
atomic_txnid_t oldest;
|
||||
MDBX_atomic_uint64_t sync_timestamp;
|
||||
MDBX_atomic_uint64_t autosync_period;
|
||||
atomic_pgno_t autosync_pending;
|
||||
atomic_pgno_t autosync_threshold;
|
||||
atomic_pgno_t discarded_tail;
|
||||
pgno_t readahead_anchor;
|
||||
MDBX_atomic_uint32_t meta_sync_txnid;
|
||||
#if MDBX_ENABLE_PGOP_STAT
|
||||
MDBX_pgop_stat_t pgop_stat;
|
||||
#endif /* MDBX_ENABLE_PGOP_STAT*/
|
||||
} me_lckless_stub;
|
||||
|
||||
/* -------------------------------------------------------------- debugging */
|
||||
|
||||
#if MDBX_DEBUG
|
||||
@ -1257,6 +1225,12 @@ struct MDBX_env {
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
pgno_t me_poison_edge;
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
|
||||
/* ------------------------------------------------- stub for lck-less mode */
|
||||
alignas(MDBX_CACHELINE_SIZE) uint64_t
|
||||
me_lckless_stub[((sizeof(MDBX_lockinfo) + MDBX_CACHELINE_SIZE - 1) &
|
||||
~(MDBX_CACHELINE_SIZE - 1)) /
|
||||
8];
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
@ -474,8 +474,8 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env,
|
||||
|
||||
int rc = MDBX_SUCCESS;
|
||||
struct stat lck_info;
|
||||
if (env->me_lfd != INVALID_HANDLE_VALUE && !inprocess_neighbor &&
|
||||
env->me_lck &&
|
||||
MDBX_lockinfo *lck = env->me_lck_mmap.lck;
|
||||
if (env->me_lfd != INVALID_HANDLE_VALUE && !inprocess_neighbor && lck &&
|
||||
/* try get exclusive access */
|
||||
lck_op(env->me_lfd, op_setlk, F_WRLCK, 0, OFF_T_MAX) == 0 &&
|
||||
/* if LCK was not removed */
|
||||
@ -489,14 +489,14 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env,
|
||||
if (env->me_sysv_ipc.semid != -1)
|
||||
rc = semctl(env->me_sysv_ipc.semid, 2, IPC_RMID) ? errno : 0;
|
||||
#else
|
||||
rc = mdbx_ipclock_destroy(&env->me_lck->mti_rlock);
|
||||
rc = mdbx_ipclock_destroy(&lck->mti_rlock);
|
||||
if (rc == 0)
|
||||
rc = mdbx_ipclock_destroy(&env->me_lck->mti_wlock);
|
||||
rc = mdbx_ipclock_destroy(&lck->mti_wlock);
|
||||
#endif /* MDBX_LOCKING */
|
||||
|
||||
mdbx_assert(env, rc == 0);
|
||||
if (rc == 0) {
|
||||
const bool synced = env->me_lck_mmap.lck->mti_unsynced_pages.weak == 0;
|
||||
const bool synced = lck->mti_unsynced_pages.weak == 0;
|
||||
mdbx_munmap(&env->me_lck_mmap);
|
||||
if (synced)
|
||||
rc = ftruncate(env->me_lfd, 0) ? errno : 0;
|
||||
@ -617,9 +617,9 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env,
|
||||
/* don't initialize semaphores twice */
|
||||
(void)inprocess_neighbor;
|
||||
if (global_uniqueness_flag == MDBX_RESULT_TRUE) {
|
||||
if (sem_init(&env->me_lck->mti_rlock, true, 1))
|
||||
if (sem_init(&env->me_lck_mmap.lck->mti_rlock, true, 1))
|
||||
return errno;
|
||||
if (sem_init(&env->me_lck->mti_wlock, true, 1))
|
||||
if (sem_init(&env->me_lck_mmap.lck->mti_wlock, true, 1))
|
||||
return errno;
|
||||
}
|
||||
return MDBX_SUCCESS;
|
||||
@ -688,10 +688,10 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_init(MDBX_env *env,
|
||||
if (rc && rc != ENOTSUP)
|
||||
goto bailout;
|
||||
|
||||
rc = pthread_mutex_init(&env->me_lck->mti_rlock, &ma);
|
||||
rc = pthread_mutex_init(&env->me_lck_mmap.lck->mti_rlock, &ma);
|
||||
if (rc)
|
||||
goto bailout;
|
||||
rc = pthread_mutex_init(&env->me_lck->mti_wlock, &ma);
|
||||
rc = pthread_mutex_init(&env->me_lck_mmap.lck->mti_wlock, &ma);
|
||||
|
||||
bailout:
|
||||
pthread_mutexattr_destroy(&ma);
|
||||
@ -708,7 +708,7 @@ static int __cold mdbx_ipclock_failed(MDBX_env *env, mdbx_ipclock_t *ipc,
|
||||
if (err == EOWNERDEAD) {
|
||||
/* We own the mutex. Clean up after dead previous owner. */
|
||||
|
||||
const bool rlocked = (env->me_lck && ipc == &env->me_lck->mti_rlock);
|
||||
const bool rlocked = ipc == &env->me_lck->mti_rlock;
|
||||
rc = MDBX_SUCCESS;
|
||||
if (!rlocked) {
|
||||
if (unlikely(env->me_txn)) {
|
||||
@ -785,7 +785,7 @@ static int mdbx_ipclock_lock(MDBX_env *env, mdbx_ipclock_t *ipc,
|
||||
} else if (sem_wait(ipc))
|
||||
rc = errno;
|
||||
#elif MDBX_LOCKING == MDBX_LOCKING_SYSV
|
||||
struct sembuf op = {.sem_num = (ipc != env->me_wlock),
|
||||
struct sembuf op = {.sem_num = (ipc != &env->me_lck->mti_wlock),
|
||||
.sem_op = -1,
|
||||
.sem_flg = dont_wait ? IPC_NOWAIT | SEM_UNDO : SEM_UNDO};
|
||||
int rc;
|
||||
@ -818,8 +818,9 @@ static int mdbx_ipclock_unlock(MDBX_env *env, mdbx_ipclock_t *ipc) {
|
||||
if (unlikely(*ipc != (pid_t)env->me_pid))
|
||||
return EPERM;
|
||||
*ipc = 0;
|
||||
struct sembuf op = {
|
||||
.sem_num = (ipc != env->me_wlock), .sem_op = 1, .sem_flg = SEM_UNDO};
|
||||
struct sembuf op = {.sem_num = (ipc != &env->me_lck->mti_wlock),
|
||||
.sem_op = 1,
|
||||
.sem_flg = SEM_UNDO};
|
||||
int rc = semop(env->me_sysv_ipc.semid, &op, 1) ? errno : MDBX_SUCCESS;
|
||||
#else
|
||||
#error "FIXME"
|
||||
@ -847,14 +848,14 @@ MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) {
|
||||
int mdbx_txn_lock(MDBX_env *env, bool dont_wait) {
|
||||
mdbx_trace("%swait %s", dont_wait ? "dont-" : "", ">>");
|
||||
mdbx_jitter4testing(true);
|
||||
int rc = mdbx_ipclock_lock(env, env->me_wlock, dont_wait);
|
||||
int rc = mdbx_ipclock_lock(env, &env->me_lck->mti_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", ">>");
|
||||
int rc = mdbx_ipclock_unlock(env, env->me_wlock);
|
||||
int rc = mdbx_ipclock_unlock(env, &env->me_lck->mti_wlock);
|
||||
mdbx_trace("<< rc %d", rc);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
mdbx_panic("%s() failed: err %d\n", __func__, rc);
|
||||
|
@ -262,11 +262,12 @@ MDBX_INTERNAL_FUNC int
|
||||
mdbx_suspend_threads_before_remap(MDBX_env *env, mdbx_handle_array_t **array) {
|
||||
const uintptr_t CurrentTid = GetCurrentThreadId();
|
||||
int rc;
|
||||
if (env->me_lck) {
|
||||
if (env->me_lck_mmap.lck) {
|
||||
/* Scan LCK for threads of the current process */
|
||||
const MDBX_reader *const begin = env->me_lck->mti_readers;
|
||||
const MDBX_reader *const begin = env->me_lck_mmap.lck->mti_readers;
|
||||
const MDBX_reader *const end =
|
||||
begin + atomic_load32(&env->me_lck->mti_numreaders, mo_AcquireRelease);
|
||||
begin +
|
||||
atomic_load32(&env->me_lck_mmap.lck->mti_numreaders, mo_AcquireRelease);
|
||||
const uintptr_t WriteTxnOwner = env->me_txn0 ? env->me_txn0->mt_owner : 0;
|
||||
for (const MDBX_reader *reader = begin; reader < end; ++reader) {
|
||||
if (reader->mr_pid.weak != env->me_pid || !reader->mr_tid.weak) {
|
||||
@ -599,7 +600,7 @@ MDBX_INTERNAL_FUNC int mdbx_lck_destroy(MDBX_env *env,
|
||||
* STATUS_USER_MAPPED_FILE/ERROR_USER_MAPPED_FILE */
|
||||
if (env->me_map)
|
||||
mdbx_munmap(&env->me_dxb_mmap);
|
||||
if (env->me_lck) {
|
||||
if (env->me_lck_mmap.lck) {
|
||||
const bool synced = env->me_lck_mmap.lck->mti_unsynced_pages.weak == 0;
|
||||
mdbx_munmap(&env->me_lck_mmap);
|
||||
if (synced && !inprocess_neighbor && env->me_lfd != INVALID_HANDLE_VALUE &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user