From 10508d2e992274b5a4e9aad8444b35e3efeb7d8d Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 23 Sep 2007 02:48:30 +0000 Subject: [PATCH] Implemented Ingo's suggestions to avoid the situation that condition variables don't block when they should because the semaphore sometimes gets released too much. One day I'll try to add some tests, though this seems like something you can't exactly unit test. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22279 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/libroot/posix/pthread/pthread_cond.c | 13 ++++++++++++- src/system/libroot/posix/pthread/pthread_private.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/system/libroot/posix/pthread/pthread_cond.c b/src/system/libroot/posix/pthread/pthread_cond.c index a632174a77..e684650eae 100644 --- a/src/system/libroot/posix/pthread/pthread_cond.c +++ b/src/system/libroot/posix/pthread/pthread_cond.c @@ -56,6 +56,7 @@ pthread_cond_init(pthread_cond_t *_cond, const pthread_condattr_t *_attr) cond->mutex = NULL; cond->waiter_count = 0; + cond->event_counter = 0; memcpy(&cond->attr, attr, sizeof(pthread_condattr)); *_cond = cond; @@ -99,9 +100,18 @@ cond_wait(pthread_cond *cond, pthread_mutex_t *_mutex, bigtime_t timeout) cond->mutex = _mutex; cond->waiter_count++; + + int32 event = atomic_get(&cond->event_counter); + pthread_mutex_unlock(_mutex); - status = acquire_sem_etc(cond->sem, 1, timeout == B_INFINITE_TIMEOUT ? 0 : B_ABSOLUTE_TIMEOUT, timeout); + + do { + status = acquire_sem_etc(cond->sem, 1, + timeout == B_INFINITE_TIMEOUT ? 0 : B_ABSOLUTE_TIMEOUT, timeout); + } while (status == B_OK && atomic_get(&cond->event_counter) == event); + pthread_mutex_lock(_mutex); + cond->waiter_count--; // If there are no more waiters, we can change mutexes if (cond->waiter_count == 0) @@ -116,6 +126,7 @@ cond_signal(pthread_cond *cond, bool broadcast) if (cond == NULL) return B_BAD_VALUE; + atomic_add(&cond->event_counter, 1); return release_sem_etc(cond->sem, broadcast ? cond->waiter_count : 1, 0); } diff --git a/src/system/libroot/posix/pthread/pthread_private.h b/src/system/libroot/posix/pthread/pthread_private.h index 30bf0da949..311bdadc4e 100644 --- a/src/system/libroot/posix/pthread/pthread_private.h +++ b/src/system/libroot/posix/pthread/pthread_private.h @@ -21,6 +21,7 @@ typedef struct _pthread_cond { sem_id sem; pthread_mutex_t *mutex; int32 waiter_count; + int32 event_counter; pthread_condattr attr; } pthread_cond;