mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-30 22:47:16 +08:00
mdbx: fix/rework rthc counting.
Change-Id: I97fd5bd6dc1a46658138d82db10e937c9595d81f
This commit is contained in:
parent
571b50622e
commit
864be54f01
55
src/mdbx.c
55
src/mdbx.c
@ -241,21 +241,26 @@ static void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value) {
|
|||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
mdbx_ensure(nullptr, TlsSetValue(key, (void *)value));
|
mdbx_ensure(nullptr, TlsSetValue(key, (void *)value));
|
||||||
#else
|
#else
|
||||||
static __thread bool thread_registered;
|
#define MDBX_THREAD_RTHC_ZERO 0
|
||||||
if (value && unlikely(!thread_registered)) {
|
#define MDBX_THREAD_RTHC_REGISTERD 1
|
||||||
thread_registered = true;
|
#define MDBX_THREAD_RTHC_COUNTED 2
|
||||||
|
static __thread uint32_t thread_registration_state;
|
||||||
|
if (value && unlikely(thread_registration_state == MDBX_THREAD_RTHC_ZERO)) {
|
||||||
|
thread_registration_state = MDBX_THREAD_RTHC_REGISTERD;
|
||||||
|
mdbx_trace("thread registered 0x%" PRIxPTR, (uintptr_t)mdbx_thread_self());
|
||||||
if (&__cxa_thread_atexit_impl == nullptr ||
|
if (&__cxa_thread_atexit_impl == nullptr ||
|
||||||
__cxa_thread_atexit_impl(mdbx_rthc_thread_dtor, &thread_registered,
|
__cxa_thread_atexit_impl(mdbx_rthc_thread_dtor,
|
||||||
|
&thread_registration_state,
|
||||||
(void *)&mdbx_version /* dso_anchor */)) {
|
(void *)&mdbx_version /* dso_anchor */)) {
|
||||||
mdbx_ensure(nullptr,
|
mdbx_ensure(nullptr, pthread_setspecific(
|
||||||
pthread_setspecific(mdbx_rthc_key, &thread_registered) == 0);
|
mdbx_rthc_key, &thread_registration_state) == 0);
|
||||||
|
thread_registration_state = MDBX_THREAD_RTHC_COUNTED;
|
||||||
const unsigned count_before = mdbx_atomic_add32(&mdbx_rthc_pending, 1);
|
const unsigned count_before = mdbx_atomic_add32(&mdbx_rthc_pending, 1);
|
||||||
mdbx_ensure(nullptr, count_before < INT_MAX);
|
mdbx_ensure(nullptr, count_before < INT_MAX);
|
||||||
mdbx_trace("fallback to pthreads' tsd, key 0x%x, count %u",
|
mdbx_trace("fallback to pthreads' tsd, key 0x%x, count %u",
|
||||||
(unsigned)mdbx_rthc_key, count_before);
|
(unsigned)mdbx_rthc_key, count_before);
|
||||||
(void)count_before;
|
(void)count_before;
|
||||||
}
|
}
|
||||||
mdbx_trace("thread registered 0x%" PRIxPTR, (uintptr_t)mdbx_thread_self());
|
|
||||||
}
|
}
|
||||||
mdbx_ensure(nullptr, pthread_setspecific(key, value) == 0);
|
mdbx_ensure(nullptr, pthread_setspecific(key, value) == 0);
|
||||||
#endif
|
#endif
|
||||||
@ -313,7 +318,14 @@ void mdbx_rthc_thread_dtor(void *ptr) {
|
|||||||
ptr);
|
ptr);
|
||||||
mdbx_rthc_unlock();
|
mdbx_rthc_unlock();
|
||||||
#else
|
#else
|
||||||
mdbx_ensure(nullptr, mdbx_atomic_sub32(&mdbx_rthc_pending, 1) > 0);
|
const char self_registration = *(char *)ptr;
|
||||||
|
*(char *)ptr = MDBX_THREAD_RTHC_ZERO;
|
||||||
|
mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, self-status %d",
|
||||||
|
(uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid(),
|
||||||
|
self_registration);
|
||||||
|
if (self_registration == MDBX_THREAD_RTHC_COUNTED)
|
||||||
|
mdbx_ensure(nullptr, mdbx_atomic_sub32(&mdbx_rthc_pending, 1) > 0);
|
||||||
|
|
||||||
if (mdbx_rthc_pending == 0) {
|
if (mdbx_rthc_pending == 0) {
|
||||||
mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, wake",
|
mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, wake",
|
||||||
(uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid());
|
(uintptr_t)mdbx_thread_self(), ptr, mdbx_getpid());
|
||||||
@ -337,13 +349,18 @@ __cold void mdbx_rthc_global_dtor(void) {
|
|||||||
mdbx_getpid(), &mdbx_rthc_global_dtor, &mdbx_rthc_thread_dtor,
|
mdbx_getpid(), &mdbx_rthc_global_dtor, &mdbx_rthc_thread_dtor,
|
||||||
&mdbx_rthc_remove);
|
&mdbx_rthc_remove);
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
|
||||||
mdbx_rthc_lock();
|
|
||||||
#else
|
|
||||||
if (pthread_getspecific(mdbx_rthc_key) != nullptr)
|
|
||||||
mdbx_ensure(nullptr, mdbx_atomic_sub32(&mdbx_rthc_pending, 1) > 0);
|
|
||||||
mdbx_thread_key_delete(mdbx_rthc_key);
|
|
||||||
mdbx_rthc_lock();
|
mdbx_rthc_lock();
|
||||||
|
#if !defined(_WIN32) && !defined(_WIN64)
|
||||||
|
char *rthc = (char *)pthread_getspecific(mdbx_rthc_key);
|
||||||
|
mdbx_trace("== thread 0x%" PRIxPTR ", rthc %p, pid %d, self-status %d",
|
||||||
|
(uintptr_t)mdbx_thread_self(), rthc, mdbx_getpid(),
|
||||||
|
rthc ? *rthc : -1);
|
||||||
|
if (rthc) {
|
||||||
|
const char self_registration = *(char *)rthc;
|
||||||
|
*rthc = MDBX_THREAD_RTHC_ZERO;
|
||||||
|
if (self_registration == MDBX_THREAD_RTHC_COUNTED)
|
||||||
|
mdbx_ensure(nullptr, mdbx_atomic_sub32(&mdbx_rthc_pending, 1) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
struct timespec abstime;
|
struct timespec abstime;
|
||||||
mdbx_ensure(nullptr, clock_gettime(CLOCK_REALTIME, &abstime) == 0);
|
mdbx_ensure(nullptr, clock_gettime(CLOCK_REALTIME, &abstime) == 0);
|
||||||
@ -352,18 +369,18 @@ __cold void mdbx_rthc_global_dtor(void) {
|
|||||||
abstime.tv_nsec -= 1000000000l;
|
abstime.tv_nsec -= 1000000000l;
|
||||||
abstime.tv_sec += 1;
|
abstime.tv_sec += 1;
|
||||||
}
|
}
|
||||||
|
#if MDBX_DEBUG > 0
|
||||||
|
abstime.tv_sec += 600;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (unsigned left; (left = mdbx_rthc_pending) > 0;) {
|
for (unsigned left; (left = mdbx_rthc_pending) > 0;) {
|
||||||
mdbx_trace("pid %d, pending %u, wait for...", mdbx_getpid(), left);
|
mdbx_trace("pid %d, pending %u, wait for...", mdbx_getpid(), left);
|
||||||
const int rc =
|
const int rc =
|
||||||
pthread_cond_timedwait(&mdbx_rthc_cond, &mdbx_rthc_mutex, &abstime);
|
pthread_cond_timedwait(&mdbx_rthc_cond, &mdbx_rthc_mutex, &abstime);
|
||||||
if (rc && rc != EINTR) {
|
if (rc && rc != EINTR)
|
||||||
/* LY: yielding a few timeslices to give a more chance
|
|
||||||
* to racing destructor(s) for completion. */
|
|
||||||
mdbx_workaround_glibc_bug21031();
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
mdbx_thread_key_delete(mdbx_rthc_key);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const mdbx_pid_t self_pid = mdbx_getpid();
|
const mdbx_pid_t self_pid = mdbx_getpid();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user