Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Mar 2012 04:35:52 +0000 (UTC)
From:      David Xu <davidxu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233022 - head/lib/libthr/thread
Message-ID:  <201203160435.q2G4ZqhX099496@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203160435.q2G4ZqhX099496>