When destroying a barrier, waiting all threads exit the barrier,

this makes it possible a thread received PTHREAD_BARRIER_SERIAL_THREAD
immediately free memory area of the barrier.
This commit is contained in:
davidxu 2012-03-16 04:35:52 +00:00
parent dd9eff8d39
commit 02e067d118
2 changed files with 31 additions and 4 deletions

View File

@ -42,13 +42,34 @@ int
_pthread_barrier_destroy(pthread_barrier_t *barrier)
{
pthread_barrier_t bar;
struct pthread *curthread;
if (barrier == NULL || *barrier == NULL)
return (EINVAL);
curthread = _get_curthread();
bar = *barrier;
if (bar->b_waiters > 0)
THR_UMUTEX_LOCK(curthread, &bar->b_lock);
if (bar->b_destroying) {
THR_UMUTEX_UNLOCK(curthread, &bar->b_lock);
return (EBUSY);
}
bar->b_destroying = 1;
do {
if (bar->b_waiters > 0) {
bar->b_destroying = 0;
THR_UMUTEX_UNLOCK(curthread, &bar->b_lock);
return (EBUSY);
}
if (bar->b_refcount != 0) {
_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0);
THR_UMUTEX_LOCK(curthread, &bar->b_lock);
} else
break;
} while (1);
bar->b_destroying = 0;
THR_UMUTEX_UNLOCK(curthread, &bar->b_lock);
*barrier = NULL;
free(bar);
return (0);
@ -74,6 +95,7 @@ _pthread_barrier_init(pthread_barrier_t *barrier,
bar->b_cycle = 0;
bar->b_waiters = 0;
bar->b_count = count;
bar->b_refcount = 0;
*barrier = bar;
return (0);
@ -101,11 +123,14 @@ _pthread_barrier_wait(pthread_barrier_t *barrier)
ret = PTHREAD_BARRIER_SERIAL_THREAD;
} else {
cycle = bar->b_cycle;
bar->b_refcount++;
do {
_thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0);
THR_UMUTEX_LOCK(curthread, &bar->b_lock);
/* test cycle to avoid bogus wakeup */
} while (cycle == bar->b_cycle);
if (--bar->b_refcount == 0 && bar->b_destroying)
_thr_ucond_broadcast(&bar->b_cv);
THR_UMUTEX_UNLOCK(curthread, &bar->b_lock);
ret = 0;
}

View File

@ -182,9 +182,11 @@ struct pthread_cond_attr {
struct pthread_barrier {
struct umutex b_lock;
struct ucond b_cv;
volatile int64_t b_cycle;
volatile int b_count;
volatile int b_waiters;
int64_t b_cycle;
int b_count;
int b_waiters;
int b_refcount;
int b_destroying;
};
struct pthread_barrierattr {