Fix mutex state tracking around pthread_cond_wait().

pthread_cond_wait drops and re-acquires the mutex internally, w/o
going through our wrapper.  Update the locked state explicitly.
This commit is contained in:
Qi Wang 2024-09-20 15:07:27 -07:00 committed by Qi Wang
parent 661fb1e672
commit 3eb7a4b53d
1 changed files with 22 additions and 2 deletions

View File

@ -153,6 +153,26 @@ set_current_thread_affinity(int cpu) {
/* Minimal sleep interval 100 ms. */
#define BACKGROUND_THREAD_MIN_INTERVAL_NS (BILLION / 10)
static int
background_thread_cond_wait(background_thread_info_t *info,
struct timespec *ts) {
int ret;
/*
* pthread_cond_wait drops and re-acquires the mutex internally, w/o
* going through our wrapper. Update the locked state explicitly.
*/
atomic_store_b(&info->mtx.locked, false, ATOMIC_RELAXED);
if (ts == NULL) {
ret = pthread_cond_wait(&info->cond, &info->mtx.lock);
} else {
ret = pthread_cond_timedwait(&info->cond, &info->mtx.lock, ts);
}
atomic_store_b(&info->mtx.locked, true, ATOMIC_RELAXED);
return ret;
}
static void
background_thread_sleep(tsdn_t *tsdn, background_thread_info_t *info,
uint64_t interval) {
@ -171,7 +191,7 @@ background_thread_sleep(tsdn_t *tsdn, background_thread_info_t *info,
if (interval == BACKGROUND_THREAD_INDEFINITE_SLEEP) {
background_thread_wakeup_time_set(tsdn, info,
BACKGROUND_THREAD_INDEFINITE_SLEEP);
ret = pthread_cond_wait(&info->cond, &info->mtx.lock);
ret = background_thread_cond_wait(info, NULL);
assert(ret == 0);
} else {
assert(interval >= BACKGROUND_THREAD_MIN_INTERVAL_NS &&
@ -193,7 +213,7 @@ background_thread_sleep(tsdn_t *tsdn, background_thread_info_t *info,
ts.tv_nsec = (size_t)nstime_nsec(&ts_wakeup);
assert(!background_thread_indefinite_sleep(info));
ret = pthread_cond_timedwait(&info->cond, &info->mtx.lock, &ts);
ret = background_thread_cond_wait(info, &ts);
assert(ret == ETIMEDOUT || ret == 0);
}
if (config_stats) {