The first implementation seemed to allow for the possibility that a thread

could block at the barrier, wake and exit the barrier, re-acquire the barrier
lock and increase `nentered` before the other blocked threads woke and checked
`nentered % count == 0`.  Then the other blocked threads would check `nentered
% count == 0` and, finding it false, go back to sleep in the barrier.  This new
implementation waits for a looser condition to obtain so that threads don't go
back to sleep in the barrier.
This commit is contained in:
David Young 2020-02-27 11:27:45 -06:00
parent 11d22f3ea5
commit 4be589813a

View File

@ -143,6 +143,7 @@ int
pthread_barrier_wait(pthread_barrier_t *barrier)
{
int rc;
uint64_t threshold;
if (barrier == NULL)
return EINVAL;
@ -152,8 +153,14 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
rc = EINVAL;
goto out;
}
/* Compute the release `threshold`. All threads entering with count = 5
* and `nentered` in [0, 4] should be released once `nentered` reaches 5:
* call 5 the release `threshold`. All threads entering with count = 5
* and `nentered` in [5, 9] should be released once `nentered` reaches 10.
*/
threshold = (barrier->nentered / barrier->count + 1) * barrier->count;
barrier->nentered++;
while (barrier->nentered % barrier->count != 0) {
while (barrier->nentered < threshold) {
if ((rc = pthread_cond_wait(&barrier->cv, &barrier->mtx)) != 0)
goto out;
}