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
This commit is contained in:
Ryan Leavengood 2007-09-23 02:48:30 +00:00
parent cb8be29457
commit 10508d2e99
2 changed files with 13 additions and 1 deletions

View File

@ -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);
}

View File

@ -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;