Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions libraries/liblmdb/mdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ static NtCloseFunc *NtClose;
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdatomic.h>

#ifdef _MSC_VER
#include <io.h>
Expand Down Expand Up @@ -1304,7 +1303,9 @@ struct MDB_txn {
/** Nested txn under this txn, set together with flag #MDB_TXN_HAS_CHILD */
MDB_txn *mt_child;
/** The count of nested RDONLY txns under this txn also named child txns */
atomic_uint mt_rdonly_child_count;
unsigned int mt_rdonly_child_count;
/** Mutex protecting mt_rdonly_child_count */
pthread_mutex_t mt_child_mutex;
pgno_t mt_next_pgno; /**< next unallocated page */
#ifdef MDB_VL32
pgno_t mt_last_pgno; /**< last written page */
Expand Down Expand Up @@ -3148,6 +3149,11 @@ mdb_txn_renew0(MDB_txn *txn)
#endif
txn->mt_child = NULL;
txn->mt_rdonly_child_count = 0;
#ifdef _WIN32
txn->mt_child_mutex = CreateMutex(NULL, FALSE, NULL);
#else
pthread_mutex_init(&txn->mt_child_mutex, NULL);
#endif
txn->mt_loose_pgs = NULL;
txn->mt_loose_count = 0;
txn->mt_dirty_room = MDB_IDL_UM_MAX;
Expand Down Expand Up @@ -3290,9 +3296,13 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
parent->mt_flags |= MDB_TXN_HAS_CHILD;
parent->mt_child = txn;
if (F_ISSET(flags, MDB_RDONLY)) {
atomic_fetch_add(&parent->mt_rdonly_child_count, 1);
pthread_mutex_lock(&parent->mt_child_mutex);
parent->mt_rdonly_child_count++;
pthread_mutex_unlock(&parent->mt_child_mutex);
} else {
pthread_mutex_lock(&parent->mt_child_mutex);
parent->mt_rdonly_child_count = 0;
pthread_mutex_unlock(&parent->mt_child_mutex);
}
txn->mt_parent = parent;
txn->mt_numdbs = parent->mt_numdbs;
Expand Down Expand Up @@ -3448,7 +3458,14 @@ mdb_txn_end(MDB_txn *txn, unsigned mode)
UNLOCK_MUTEX(env->me_wmutex);
} else {
/* mark parent txn has no longer having children if this is the last nested txn */
if (!F_ISSET(flags, MDB_RDONLY) || atomic_fetch_sub(&txn->mt_parent->mt_rdonly_child_count, 1) == 1) {
int last_child = 0;
if (F_ISSET(flags, MDB_RDONLY)) {
pthread_mutex_lock(&txn->mt_parent->mt_child_mutex);
txn->mt_parent->mt_rdonly_child_count--;
last_child = (txn->mt_parent->mt_rdonly_child_count == 0);
pthread_mutex_unlock(&txn->mt_parent->mt_child_mutex);
}
if (!F_ISSET(flags, MDB_RDONLY) || last_child) {
txn->mt_parent->mt_child = NULL;
txn->mt_parent->mt_flags &= ~MDB_TXN_HAS_CHILD;
env->me_pgstate = ((MDB_ntxn *)txn)->mnt_pgstate;
Expand Down Expand Up @@ -3487,8 +3504,14 @@ mdb_txn_end(MDB_txn *txn, unsigned mode)
free(tl);
}
#endif
if (mode & MDB_END_FREE)
if (mode & MDB_END_FREE) {
#ifdef _WIN32
CloseHandle(txn->mt_child_mutex);
#else
pthread_mutex_destroy(&txn->mt_child_mutex);
#endif
free(txn);
}
}

void
Expand All @@ -3512,7 +3535,10 @@ _mdb_txn_abort(MDB_txn *txn)

if (txn->mt_parent && txn->mt_flags & MDB_RDONLY) {
// You must first abort the child before the parent
mdb_tassert(txn, txn->mt_parent && atomic_load(&txn->mt_rdonly_child_count) == 0);
pthread_mutex_lock(&txn->mt_child_mutex);
int count = txn->mt_rdonly_child_count;
pthread_mutex_unlock(&txn->mt_child_mutex);
mdb_tassert(txn, txn->mt_parent && count == 0);
}

if (txn->mt_child)
Expand Down