Author: davidxu
Date: Fri Mar 16 04:35:52 2012
New Revision: 233022
URL: http://svn.freebsd.org/changeset/base/233022

Log:
  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.

Modified:
  head/lib/libthr/thread/thr_barrier.c
  head/lib/libthr/thread/thr_private.h

Modified: head/lib/libthr/thread/thr_barrier.c
==============================================================================
--- head/lib/libthr/thread/thr_barrier.c        Fri Mar 16 03:22:37 2012        
(r233021)
+++ head/lib/libthr/thread/thr_barrier.c        Fri Mar 16 04:35:52 2012        
(r233022)
@@ -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 
        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 
                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;
        }

Modified: head/lib/libthr/thread/thr_private.h
==============================================================================
--- head/lib/libthr/thread/thr_private.h        Fri Mar 16 03:22:37 2012        
(r233021)
+++ head/lib/libthr/thread/thr_private.h        Fri Mar 16 04:35:52 2012        
(r233022)
@@ -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 {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to