Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 May 2003 14:21:15 -0700 (PDT)
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 31939 for review
Message-ID:  <200305272121.h4RLLFHI050982@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=31939

Change 31939 by peter@peter_daintree on 2003/05/27 14:20:15

	IFC @31936

Affected files ...

.. //depot/projects/hammer/lib/libthr/arch/i386/i386/_setcurthread.c#6 integrate
.. //depot/projects/hammer/lib/libthr/arch/ia64/ia64/_curthread.c#3 integrate
.. //depot/projects/hammer/lib/libthr/arch/sparc64/sparc64/_setcurthread.c#2 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_cancel.c#4 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_create.c#5 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_exit.c#4 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_find_thread.c#2 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_gc.c#3 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_info.c#2 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_init.c#4 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_join.c#3 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_kern.c#5 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_private.h#5 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_spinlock.c#3 integrate
.. //depot/projects/hammer/lib/libthr/thread/thr_stack.c#2 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/early-adopter/article.sgml#4 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/errata/article.sgml#4 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/alpha/proc-alpha.sgml#5 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/common/dev.sgml#7 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/common/intro.sgml#3 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/i386/proc-i386.sgml#4 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/ia64/article.sgml#4 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/ia64/proc-ia64.sgml#3 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/hardware/sparc64/proc-sparc64.sgml#4 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/installation/common/install.sgml#6 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/installation/common/trouble.sgml#5 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/installation/common/upgrade.sgml#4 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/readme/article.sgml#5 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/relnotes/common/new.sgml#8 integrate
.. //depot/projects/hammer/release/doc/de_DE.ISO8859-1/share/sgml/release.dsl#5 integrate
.. //depot/projects/hammer/release/doc/en_US.ISO8859-1/relnotes/common/new.sgml#28 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/early-adopter/article.sgml#3 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/hardware/common/dev.sgml#5 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/hardware/common/intro.sgml#3 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/hardware/i386/proc-i386.sgml#4 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/hardware/ia64/article.sgml#3 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/hardware/ia64/proc-ia64.sgml#3 integrate
.. //depot/projects/hammer/release/doc/ja_JP.eucJP/share/sgml/release.dsl#5 integrate
.. //depot/projects/hammer/sys/alpha/alpha/busdma_machdep.c#7 integrate
.. //depot/projects/hammer/sys/alpha/include/bus.h#7 integrate
.. //depot/projects/hammer/sys/amd64/amd64/busdma_machdep.c#5 integrate
.. //depot/projects/hammer/sys/amd64/include/bus_dma.h#6 integrate
.. //depot/projects/hammer/sys/contrib/dev/acpica/dsmethod.c#5 integrate
.. //depot/projects/hammer/sys/contrib/dev/acpica/nsalloc.c#4 integrate
.. //depot/projects/hammer/sys/dev/advansys/advansys.c#5 integrate
.. //depot/projects/hammer/sys/dev/advansys/adwcam.c#5 integrate
.. //depot/projects/hammer/sys/dev/aha/aha.c#6 integrate
.. //depot/projects/hammer/sys/dev/ahb/ahb.c#5 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx.c#7 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx.h#6 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx.reg#7 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx.seq#6 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx_inline.h#6 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx_osm.c#6 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx_osm.h#4 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic79xx_pci.c#6 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx.c#7 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx.h#5 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx.reg#5 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx.seq#4 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx_inline.h#5 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx_osm.c#9 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx_osm.h#6 integrate
.. //depot/projects/hammer/sys/dev/aic7xxx/aic7xxx_pci.c#5 integrate
.. //depot/projects/hammer/sys/dev/amd/amd.c#3 integrate
.. //depot/projects/hammer/sys/dev/buslogic/bt.c#6 integrate
.. //depot/projects/hammer/sys/dev/dpt/dpt_scsi.c#6 integrate
.. //depot/projects/hammer/sys/dev/firewire/fwdma.h#2 integrate
.. //depot/projects/hammer/sys/dev/ida/ida.c#6 integrate
.. //depot/projects/hammer/sys/dev/mpt/mpt_freebsd.c#6 integrate
.. //depot/projects/hammer/sys/dev/trm/trm.c#5 integrate
.. //depot/projects/hammer/sys/geom/geom_disk.c#13 integrate
.. //depot/projects/hammer/sys/i386/i386/busdma_machdep.c#8 integrate
.. //depot/projects/hammer/sys/i386/include/bus_dma.h#5 integrate
.. //depot/projects/hammer/sys/ia64/ia64/busdma_machdep.c#7 integrate
.. //depot/projects/hammer/sys/ia64/ia64/exception.s#12 integrate
.. //depot/projects/hammer/sys/ia64/ia64/machdep.c#15 integrate
.. //depot/projects/hammer/sys/ia64/ia64/pmap.c#13 integrate
.. //depot/projects/hammer/sys/ia64/ia64/support.s#4 integrate
.. //depot/projects/hammer/sys/ia64/ia64/unwind.c#4 integrate
.. //depot/projects/hammer/sys/ia64/include/bus.h#6 integrate
.. //depot/projects/hammer/sys/kern/kern_alq.c#5 integrate
.. //depot/projects/hammer/sys/kern/kern_umtx.c#2 integrate
.. //depot/projects/hammer/sys/kern/subr_sbuf.c#6 integrate
.. //depot/projects/hammer/sys/pci/agp_intel.c#6 integrate
.. //depot/projects/hammer/sys/pci/agpreg.h#4 integrate
.. //depot/projects/hammer/sys/powerpc/include/bus.h#5 integrate
.. //depot/projects/hammer/sys/powerpc/powerpc/busdma_machdep.c#6 integrate
.. //depot/projects/hammer/sys/sparc64/include/bus.h#8 integrate
.. //depot/projects/hammer/sys/sparc64/include/iommuvar.h#5 integrate
.. //depot/projects/hammer/sys/sparc64/pci/psycho.c#10 integrate
.. //depot/projects/hammer/sys/sparc64/sbus/sbus.c#5 integrate
.. //depot/projects/hammer/sys/sparc64/sparc64/bus_machdep.c#8 integrate
.. //depot/projects/hammer/sys/sparc64/sparc64/iommu.c#7 integrate
.. //depot/projects/hammer/tools/tools/tinderbox/tbmaster.pl#8 integrate
.. //depot/projects/hammer/usr.bin/usbhidctl/usbhid.c#3 integrate
.. //depot/projects/hammer/usr.sbin/pkg_install/info/show.c#6 integrate
.. //depot/projects/hammer/usr.sbin/pkg_install/lib/lib.h#5 integrate
.. //depot/projects/hammer/usr.sbin/pkg_install/lib/str.c#2 integrate

Differences ...

==== //depot/projects/hammer/lib/libthr/arch/i386/i386/_setcurthread.c#6 (text+ko) ====

@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/arch/i386/i386/_setcurthread.c,v 1.7 2003/05/23 23:39:31 mtm Exp $
+ * $FreeBSD: src/lib/libthr/arch/i386/i386/_setcurthread.c,v 1.8 2003/05/25 22:40:57 mtm Exp $
  */
 
 #include <sys/types.h>
@@ -87,13 +87,15 @@
 }
 
 void *
-_set_curthread(ucontext_t *uc, struct pthread *thr)
+_set_curthread(ucontext_t *uc, struct pthread *thr, int *err)
 {
 	union descriptor desc;
 	void **ldt_entry;
 	int ldt_index;
 	int error;
 
+	*err = 0;
+
 	/*
 	 * If we are setting up the initial thread, the gs register
 	 * won't be setup for the current thread. In any case, we
@@ -106,8 +108,11 @@
 	if (ldt_inited == NULL)
 		ldt_init();
 
-	if (ldt_free == NULL)
-		abort();
+	if (ldt_free == NULL) {
+		/* Concurrent thread limit reached */
+		*err = curthread->error = EAGAIN;
+		return (NULL);
+	}
 
 	/*
 	 * Pull one off of the free list and update the free list pointer.

==== //depot/projects/hammer/lib/libthr/arch/ia64/ia64/_curthread.c#3 (text+ko) ====

@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libthr/arch/ia64/ia64/_curthread.c,v 1.2 2003/05/25 06:49:19 marcel Exp $");
+__FBSDID("$FreeBSD: src/lib/libthr/arch/ia64/ia64/_curthread.c,v 1.3 2003/05/25 22:40:57 mtm Exp $");
 
 #include <sys/types.h>
 #include <sys/ucontext.h>
@@ -48,9 +48,9 @@
 }
 
 void *
-_set_curthread(ucontext_t *uc, struct pthread *thread)
+_set_curthread(ucontext_t *uc, struct pthread *thread, int *err)
 {
-
+	*err = 0;
 	if (uc != NULL)
 		uc->uc_mcontext.mc_special.tp = (uint64_t)thread;
 	else

==== //depot/projects/hammer/lib/libthr/arch/sparc64/sparc64/_setcurthread.c#2 (text+ko) ====

@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libthr/arch/sparc64/sparc64/_setcurthread.c,v 1.2 2003/04/03 03:34:50 jake Exp $");
+__FBSDID("$FreeBSD: src/lib/libthr/arch/sparc64/sparc64/_setcurthread.c,v 1.3 2003/05/25 22:40:57 mtm Exp $");
 
 #include <sys/types.h>
 #include <sys/ucontext.h>
@@ -48,9 +48,9 @@
 }
 
 void *
-_set_curthread(ucontext_t *uc, struct pthread *thread)
+_set_curthread(ucontext_t *uc, struct pthread *thread, int *err)
 {
-
+	*err = 0;
 	if (uc != NULL)
 		uc->uc_mcontext.mc_global[6] = (uint64_t)thread;
 	else

==== //depot/projects/hammer/lib/libthr/thread/thr_cancel.c#4 (text+ko) ====

@@ -1,6 +1,6 @@
 /*
  * David Leonard <d@openbsd.org>, 1999. Public domain.
- * $FreeBSD: src/lib/libthr/thread/thr_cancel.c,v 1.4 2003/05/23 09:48:20 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_cancel.c,v 1.5 2003/05/25 08:48:11 mtm Exp $
  */
 #include <sys/errno.h>
 #include <pthread.h>
@@ -21,7 +21,16 @@
 _pthread_cancel(pthread_t pthread)
 {
 	int ret;
+	pthread_t joined;
 
+	/*
+	 * When canceling a thread that has joined another thread, this
+	 * routine breaks the normal lock order of locking first the
+	 * joined and then the joiner. Therefore, it is necessary that
+	 * if it can't obtain the second lock, that it release the first
+	 * one and restart from the top.
+	 */
+retry:
 	if ((ret = _find_thread(pthread)) != 0)
 		/* The thread is not on the list of active threads */
 		goto out;
@@ -70,10 +79,14 @@
 			/*
 			 * Disconnect the thread from the joinee:
 			 */
-			if (pthread->join_status.thread != NULL) {
-				pthread->join_status.thread->joiner
-				    = NULL;
-				pthread->join_status.thread = NULL;
+			if ((joined = pthread->join_status.thread) != NULL) {
+				if (_spintrylock(&joined->lock) == EBUSY) {
+					_thread_critical_exit(pthread);
+					goto retry;
+				}
+				pthread->join_status.thread->joiner = NULL;
+				_spinunlock(&joined->lock);
+				joined = pthread->join_status.thread = NULL;
 			}
 			pthread->cancelflags |= PTHREAD_CANCELLING;
 			PTHREAD_NEW_STATE(pthread, PS_RUNNING);

==== //depot/projects/hammer/lib/libthr/thread/thr_create.c#5 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_create.c,v 1.6 2003/05/23 09:48:20 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_create.c,v 1.9 2003/05/26 00:37:07 mtm Exp $
  */
 #include <errno.h>
 #include <stdlib.h>
@@ -116,7 +116,17 @@
 	new_thread->ctx.uc_stack.ss_sp = new_thread->stack;
 	new_thread->ctx.uc_stack.ss_size = pattr->stacksize_attr;
 	makecontext(&new_thread->ctx, _thread_start, 0);
-	new_thread->arch_id = _set_curthread(&new_thread->ctx, new_thread);
+	new_thread->arch_id = _set_curthread(&new_thread->ctx, new_thread, &ret);
+	if (ret != 0) {
+		if (pattr->stackaddr_attr == NULL) {
+			STACK_LOCK;
+			_thread_stack_free(new_thread->stack,
+			    pattr->stacksize_attr, pattr->guardsize_attr);
+			STACK_UNLOCK;
+		}
+		free(new_thread);
+		return (ret);
+	}
 
 	/* Copy the thread attributes: */
 	memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
@@ -155,16 +165,14 @@
 	new_thread->flags = 0;
 
 	/*
-	 * Protect the scheduling queues.
-	 */
-	GIANT_LOCK(curthread);
-
-	/*
 	 * Initialise the unique id which GDB uses to
 	 * track threads.
 	 */
 	new_thread->uniqueid = next_uniqueid++;
 
+	THREAD_LIST_LOCK;
+	_thread_critical_enter(new_thread);
+
 	/*
 	 * Check if the garbage collector thread
 	 * needs to be started.
@@ -174,6 +182,8 @@
 	/* Add the thread to the linked list of all threads: */
 	TAILQ_INSERT_HEAD(&_thread_list, new_thread, tle);
 
+	THREAD_LIST_UNLOCK;
+
 	/*
 	 * Create the thread.
 	 *
@@ -190,11 +200,11 @@
 		PANIC("thr_create");
 	}
 
-	GIANT_UNLOCK(curthread);
-
 	/* Return a pointer to the thread structure: */
 	(*thread) = new_thread;
 
+	_thread_critical_exit(new_thread);
+
 	/*
 	 * Start a garbage collector thread
 	 * if necessary.

==== //depot/projects/hammer/lib/libthr/thread/thr_exit.c#4 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_exit.c,v 1.5 2003/05/23 09:48:20 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_exit.c,v 1.6 2003/05/25 08:31:33 mtm Exp $
  */
 #include <errno.h>
 #include <unistd.h>
@@ -95,6 +95,7 @@
 _pthread_exit(void *status)
 {
 	pthread_t pthread;
+	int exitNow = 0;
 
 	/* Check if this thread is already in the process of exiting: */
 	if ((curthread->flags & PTHREAD_EXITING) != 0) {
@@ -121,37 +122,14 @@
 		_thread_cleanupspecific();
 	}
 
-	/*
-	 * Lock the garbage collector mutex to ensure that the garbage
-	 * collector is not using the dead thread list.
-	 */
-	if (pthread_mutex_lock(&_gc_mutex) != 0)
-		PANIC("Cannot lock gc mutex");
-
-	/* Add this thread to the list of dead threads. */
-	TAILQ_INSERT_HEAD(&_dead_list, curthread, dle);
-
-	/*
-	 * Signal the garbage collector thread that there is something
-	 * to clean up.
-	 */
-	if (pthread_cond_signal(&_gc_cond) != 0)
-		PANIC("Cannot signal gc cond");
-
-	/*
-	 * Avoid a race condition where a scheduling signal can occur
-	 * causing the garbage collector thread to run.  If this happens,
-	 * the current thread can be cleaned out from under us.
-	 */
-	GIANT_LOCK(curthread);
+	/* Lock the dead list first to maintain correct lock order */
+	DEAD_LIST_LOCK;
+	_thread_critical_enter(curthread);
 
-	/* Unlock the garbage collector mutex. */
-	if (pthread_mutex_unlock(&_gc_mutex) != 0)
-		PANIC("Cannot unlock gc mutex");
-
 	/* Check if there is a thread joining this one: */
 	if (curthread->joiner != NULL) {
 		pthread = curthread->joiner;
+		_SPINLOCK(&pthread->lock);
 		curthread->joiner = NULL;
 
 		/* Make the joining thread runnable: */
@@ -161,6 +139,7 @@
 		pthread->join_status.ret = curthread->ret;
 		pthread->join_status.error = 0;
 		pthread->join_status.thread = NULL;
+		_SPINUNLOCK(&pthread->lock);
 
 		/* Make this thread collectable by the garbage collector. */
 		PTHREAD_ASSERT(((curthread->attr.flags & PTHREAD_DETACHED) ==
@@ -168,14 +147,31 @@
 		curthread->attr.flags |= PTHREAD_DETACHED;
 	}
 
-	/* Remove this thread from the thread list: */
+	/*
+	 * Add this thread to the list of dead threads, and
+	 * also remove it from the active threads list.
+	 */
+	THREAD_LIST_LOCK;
+	TAILQ_INSERT_HEAD(&_dead_list, curthread, dle);
 	TAILQ_REMOVE(&_thread_list, curthread, tle);
-
 	PTHREAD_SET_STATE(curthread, PS_DEAD);
-	GIANT_UNLOCK(curthread);
+	_thread_critical_exit(curthread);
+	
+	/*
+	 * Signal the garbage collector thread that there is something
+	 * to clean up.
+	 */
+	if (pthread_cond_signal(&_gc_cond) != 0)
+		PANIC("Cannot signal gc cond");
 
 	/* If we're the last thread, call it quits */
 	if (TAILQ_EMPTY(&_thread_list))
+		exitNow = 1;
+
+	THREAD_LIST_UNLOCK;
+	DEAD_LIST_UNLOCK;
+
+	if (exitNow)
 		exit(0);
 
 	/*

==== //depot/projects/hammer/lib/libthr/thread/thr_find_thread.c#2 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_find_thread.c,v 1.2 2003/04/02 03:05:39 jeff Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_find_thread.c,v 1.3 2003/05/25 08:35:37 mtm Exp $
  */
 #include <errno.h>
 #include <pthread.h>
@@ -44,7 +44,7 @@
 	if (pthread == NULL || pthread->magic != PTHREAD_MAGIC)
 		return(EINVAL);
 
-	GIANT_LOCK(curthread);
+	THREAD_LIST_LOCK;
 
 	/* Search for the specified thread: */
 	TAILQ_FOREACH(pthread1, &_thread_list, tle) {
@@ -52,7 +52,7 @@
 			break;
 	}
 
-	GIANT_UNLOCK(curthread);
+	THREAD_LIST_UNLOCK;
 
 	/* Return zero if the thread exists: */
 	return ((pthread1 != NULL) ? 0:ESRCH);

==== //depot/projects/hammer/lib/libthr/thread/thr_gc.c#3 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_gc.c,v 1.3 2003/04/20 02:56:12 marcel Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_gc.c,v 1.5 2003/05/26 00:37:07 mtm Exp $
  *
  * Garbage collector thread. Frees memory allocated for dead threads.
  *
@@ -75,19 +75,17 @@
 			_thread_dump_info();
 
 		/*
-		 * Lock the garbage collector mutex which ensures that
+		 * Lock the list of dead threads which ensures that
 		 * this thread sees another thread exit:
 		 */
-		if (pthread_mutex_lock(&_gc_mutex) != 0)
-			PANIC("Cannot lock gc mutex");
+		DEAD_LIST_LOCK;
 
 		/* No stack or thread structure to free yet. */
 		p_stack = NULL;
 		pthread_cln = NULL;
 
-		GIANT_LOCK(curthread);
-
 		/* Check if this is the last running thread. */
+		THREAD_LIST_LOCK;
 		if (TAILQ_FIRST(&_thread_list) == curthread &&
 		    TAILQ_NEXT(curthread, tle) == NULL)
 			/*
@@ -95,6 +93,7 @@
 			 * now.
 			 */
 			f_done = 1;
+		THREAD_LIST_UNLOCK;
 
 		/*
 		 * Enter a loop to search for the first dead thread that
@@ -106,57 +105,45 @@
 			/* Don't destroy the initial thread. */
 			if (pthread == _thread_initial) 
 				continue;
+
+			_SPINLOCK(&pthread->lock);
+
 			/*
-			 * Check if this thread has detached:
+			 * Check if the stack was not specified by
+			 * the caller to pthread_create() and has not
+			 * been destroyed yet: 
 			 */
-			if ((pthread->attr.flags &
-			    PTHREAD_DETACHED) != 0) {
-				/* Remove this thread from the dead list: */
-				TAILQ_REMOVE(&_dead_list, pthread, dle);
+			STACK_LOCK;
+			if (pthread->attr.stackaddr_attr == NULL &&
+			    pthread->stack != NULL) {
+				_thread_stack_free(pthread->stack,
+				    pthread->attr.stacksize_attr,
+				    pthread->attr.guardsize_attr);
+				pthread->stack = NULL;
+			}
+			STACK_UNLOCK;
 
-				/*
-				 * Check if the stack was not specified by
-				 * the caller to pthread_create() and has not
-				 * been destroyed yet: 
-				 */
-				if (pthread->attr.stackaddr_attr == NULL &&
-				    pthread->stack != NULL) {
-					_thread_stack_free(pthread->stack,
-					    pthread->attr.stacksize_attr,
-					    pthread->attr.guardsize_attr);
-				}
+			/*
+			 * If the thread has not been detached, leave
+			 * it on the dead thread list.
+			 */
+			if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
+				_SPINUNLOCK(&pthread->lock);
+				continue;
+			}
 
-				/*
-				 * Point to the thread structure that must
-				 * be freed outside the locks:
-				 */
-				pthread_cln = pthread;
+			/* Remove this thread from the dead list: */
+			TAILQ_REMOVE(&_dead_list, pthread, dle);
 
-			} else {
-				/*
-				 * This thread has not detached, so do
-				 * not destroy it.
-				 *
-				 * Check if the stack was not specified by
-				 * the caller to pthread_create() and has not
-				 * been destroyed yet: 
-				 */
-				if (pthread->attr.stackaddr_attr == NULL &&
-				    pthread->stack != NULL) {
-					_thread_stack_free(pthread->stack,
-					    pthread->attr.stacksize_attr,
-					    pthread->attr.guardsize_attr);
+			/*
+			 * Point to the thread structure that must
+			 * be freed outside the locks:
+			 */
+			pthread_cln = pthread;
 
-					/*
-					 * NULL the stack pointer now that the
-					 * memory has been freed:
-					 */
-					pthread->stack = NULL;
-				}
-			}
+			_SPINUNLOCK(&pthread->lock);
 		}
 
-		GIANT_UNLOCK(curthread);
 		/*
 		 * Check if this is not the last thread and there is no
 		 * memory to free this time around.
@@ -177,15 +164,14 @@
 			 * timeout (for a backup poll).
 			 */
 			if ((ret = pthread_cond_timedwait(&_gc_cond,
-			    &_gc_mutex, &abstime)) != 0 && ret != ETIMEDOUT) {
+			    &dead_list_lock, &abstime)) != 0 && ret != ETIMEDOUT) {
 				_thread_printf(STDERR_FILENO, "ret = %d", ret);
 				PANIC("gc cannot wait for a signal");
 			}
 		}
 
 		/* Unlock the garbage collector mutex: */
-		if (pthread_mutex_unlock(&_gc_mutex) != 0)
-			PANIC("Cannot unlock gc mutex");
+		DEAD_LIST_UNLOCK;
 
 		/*
 		 * If there is memory to free, do it now. The call to

==== //depot/projects/hammer/lib/libthr/thread/thr_info.c#2 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_info.c,v 1.2 2003/04/02 03:05:39 jeff Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_info.c,v 1.3 2003/05/25 08:31:33 mtm Exp $
  */
 #include <stdio.h>
 #include <stdlib.h>
@@ -109,6 +109,7 @@
 		}
 
 		/* Check if there are no dead threads: */
+		DEAD_LIST_LOCK;
 		if (TAILQ_FIRST(&_dead_list) == NULL) {
 			/* Output a record: */
 			strcpy(s, "\n\nTHERE ARE NO DEAD THREADS\n");
@@ -126,6 +127,7 @@
 				dump_thread(fd, pthread, /*long_version*/ 0);
 			}
 		}
+		DEAD_LIST_UNLOCK;
 
 		/* Close the dump file: */
 		__sys_close(fd);

==== //depot/projects/hammer/lib/libthr/thread/thr_init.c#4 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_init.c,v 1.5 2003/05/23 09:48:20 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_init.c,v 1.7 2003/05/25 22:40:57 mtm Exp $
  */
 
 /* Allocate space for global thread variables here: */
@@ -162,6 +162,7 @@
 	size_t		len;
 	int		mib[2];
 	sigset_t	set;
+	int		error;
 
 	struct clockinfo clockinfo;
 	struct sigaction act;
@@ -221,7 +222,7 @@
 	memset(pthread, 0, sizeof(struct pthread));
 
 	_thread_initial = pthread;
-	pthread->arch_id = _set_curthread(NULL, pthread);
+	pthread->arch_id = _set_curthread(NULL, pthread, &error);
 
 	/* Get our thread id. */
 	thr_self(&pthread->thr_id);
@@ -326,7 +327,7 @@
 		    clockinfo.tick : CLOCK_RES_USEC_MIN;
 
 	/* Initialise the garbage collector mutex and condition variable. */
-	if (_pthread_mutex_init(&_gc_mutex,NULL) != 0 ||
+	if (_pthread_mutex_init(&dead_list_lock,NULL) != 0 ||
 	    _pthread_cond_init(&_gc_cond,NULL) != 0)
 		PANIC("Failed to initialise garbage collector mutex or condvar");
 }

==== //depot/projects/hammer/lib/libthr/thread/thr_join.c#3 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_join.c,v 1.4 2003/05/20 18:48:41 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_join.c,v 1.6 2003/05/26 00:28:49 mtm Exp $
  */
 #include <errno.h>
 #include <pthread.h>
@@ -60,38 +60,36 @@
 	}
 
 	/*
-	 * Lock the garbage collector mutex to ensure that the garbage
-	 * collector is not using the dead thread list.
-	 */
-	if (pthread_mutex_lock(&_gc_mutex) != 0)
-		PANIC("Cannot lock gc mutex");
-
-	GIANT_LOCK(curthread);
-
-	/*
 	 * Search for the specified thread in the list of active threads.  This
 	 * is done manually here rather than calling _find_thread() because
 	 * the searches in _thread_list and _dead_list (as well as setting up
 	 * join/detach state) have to be done atomically.
 	 */
+	DEAD_LIST_LOCK;
+	THREAD_LIST_LOCK;
 	TAILQ_FOREACH(thread, &_thread_list, tle)
-		if (thread == pthread)
+		if (thread == pthread) {
+			_SPINLOCK(&pthread->lock);
 			break;
+		}
 
 	if (thread == NULL)
 		/*
 		 * Search for the specified thread in the list of dead threads:
 		 */
 		TAILQ_FOREACH(thread, &_dead_list, dle)
-			if (thread == pthread)
+			if (thread == pthread) {
+				_SPINLOCK(&pthread->lock);
 				break;
-
+			}
 
 	/* Check if the thread was not found or has been detached: */
 	if (thread == NULL ||
 	    ((pthread->attr.flags & PTHREAD_DETACHED) != 0)) {
-		if (pthread_mutex_unlock(&_gc_mutex) != 0)
-			PANIC("Cannot lock gc mutex");
+		if (thread != NULL)
+			_SPINUNLOCK(&pthread->lock);
+		THREAD_LIST_UNLOCK;
+		DEAD_LIST_UNLOCK;
 		ret = ESRCH;
 		goto out;
 
@@ -99,21 +97,17 @@
 	if (pthread->joiner != NULL) {
 		/* Multiple joiners are not supported. */
 		/* XXXTHR - support multiple joiners. */
-		if (pthread_mutex_unlock(&_gc_mutex) != 0)
-			PANIC("Cannot lock gc mutex");
+		_SPINUNLOCK(&pthread->lock);
+		THREAD_LIST_UNLOCK;
+		DEAD_LIST_UNLOCK;
 		ret = ENOTSUP;
 		goto out;
 
 	}
-	/*
-	 * Unlock the garbage collector mutex, now that the garbage collector
-	 * can't be run:
-	 */
-	if (pthread_mutex_unlock(&_gc_mutex) != 0)
-		PANIC("Cannot lock gc mutex");
 
 	/* Check if the thread is not dead: */
 	if (pthread->state != PS_DEAD) {
+		_thread_critical_enter(curthread);
 		/* Set the running thread to be the joiner: */
 		pthread->joiner = curthread;
 
@@ -123,9 +117,13 @@
 		while (curthread->join_status.thread == pthread) {
 			PTHREAD_SET_STATE(curthread, PS_JOIN);
 			/* Wait for our signal to wake up. */
-			GIANT_UNLOCK(curthread);
+			_thread_critical_exit(curthread);
+			_SPINUNLOCK(&pthread->lock);
+			THREAD_LIST_UNLOCK;
+			DEAD_LIST_UNLOCK;
 			_thread_suspend(curthread, NULL);
-			GIANT_LOCK(curthread);
+
+			_thread_critical_enter(curthread);
 		}
 
 		/*
@@ -135,6 +133,7 @@
 		ret = curthread->join_status.error;
 		if ((ret == 0) && (thread_return != NULL))
 			*thread_return = curthread->join_status.ret;
+		_thread_critical_exit(curthread);
 	} else {
 		/*
 		 * The thread exited (is dead) without being detached, and no
@@ -149,12 +148,14 @@
 
 		/* Make the thread collectable by the garbage collector. */
 		pthread->attr.flags |= PTHREAD_DETACHED;
-
+		_SPINUNLOCK(&pthread->lock);
+		if (pthread_cond_signal(&_gc_cond) != 0)
+			PANIC("Cannot signal gc cond");
+		THREAD_LIST_UNLOCK;
+		DEAD_LIST_UNLOCK;
 	}
 
 out:
-	GIANT_UNLOCK(curthread);
-
 	_thread_leave_cancellation_point();
 
 	/* Return the completion status: */

==== //depot/projects/hammer/lib/libthr/thread/thr_kern.c#5 (text+ko) ====

@@ -23,7 +23,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_kern.c,v 1.7 2003/05/23 10:28:13 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_kern.c,v 1.8 2003/05/25 07:58:22 mtm Exp $
  */
 
 #include <sys/cdefs.h>
@@ -68,6 +68,13 @@
 	 * acquired the giant lock.
 	 */
 	_SPINLOCK(&pthread->lock);
+
+	/* If we are already in a critical section, just up the refcount */
+	if (++curthread->crit_ref > 1)
+		return;
+	PTHREAD_ASSERT(curthread->crit_ref == 1,
+	    ("Critical section reference count must be 1!"));
+
 	if (__sys_sigprocmask(SIG_SETMASK, &set, &sav)) {
 		_thread_printf(STDERR_FILENO, "Critical Enter: sig err %d\n",
 		    errno);
@@ -81,6 +88,12 @@
 {
 	sigset_t set;
 
+	/* We might be in a nested critical section */
+	if (--curthread->crit_ref > 0)
+		return;
+	PTHREAD_ASSERT(curthread->crit_ref == 0,
+	    ("Non-Zero critical section reference count."));
+
 	/*
 	 * Restore signals.
 	 */

==== //depot/projects/hammer/lib/libthr/thread/thr_private.h#5 (text+ko) ====

@@ -31,7 +31,7 @@
  *
  * Private thread definitions for the uthread kernel.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_private.h,v 1.9 2003/05/23 23:39:31 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_private.h,v 1.14 2003/05/26 00:37:07 mtm Exp $
  */
 
 #ifndef _THR_PRIVATE_H
@@ -426,6 +426,7 @@
 	u_int64_t		uniqueid; /* for gdb */
 	thr_id_t		thr_id;
 	sigset_t		savedsig;
+	int			crit_ref; /* crit. section netsting level */
 
 	/*
 	 * Lock for accesses to this thread structure.
@@ -577,6 +578,14 @@
 ;
 #endif
 
+SCLASS spinlock_t stack_lock
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= _SPINLOCK_INITIALIZER
+#endif
+;
+#define STACK_LOCK	_SPINLOCK(&stack_lock);
+#define STACK_UNLOCK	_SPINUNLOCK(&stack_lock);
+
 /* List of all threads: */
 SCLASS TAILQ_HEAD(, pthread)	_thread_list
 #ifdef GLOBAL_PTHREAD_PRIVATE
@@ -593,6 +602,34 @@
 ;
 #endif
 
+/*
+ * These two locks protect the global active threads list and
+ * the global dead threads list, respectively. Combining these
+ * into one lock for both lists doesn't seem wise, since it
+ * would likely increase contention during busy thread creation
+ * and destruction for very little savings in space.
+ *
+ * The lock for the "dead threads list" must be a pthread mutex
+ * because it is used with condition variables to synchronize
+ * the gc thread with active threads in the process of exiting or
+ * dead threads who have just been joined.
+ */
+SCLASS spinlock_t thread_list_lock
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= _SPINLOCK_INITIALIZER
+#endif 
+;
+SCLASS pthread_mutex_t dead_list_lock
+#ifdef GLOBAL_PTHREAD_PRIVATE
+= NULL
+#endif
+;
+
+#define THREAD_LIST_LOCK	_SPINLOCK(&thread_list_lock)
+#define THREAD_LIST_UNLOCK	_SPINUNLOCK(&thread_list_lock)
+#define DEAD_LIST_LOCK		_pthread_mutex_lock(&dead_list_lock)
+#define DEAD_LIST_UNLOCK	_pthread_mutex_unlock(&dead_list_lock)
+
 /* Initial thread: */
 SCLASS struct pthread *_thread_initial
 #ifdef GLOBAL_PTHREAD_PRIVATE
@@ -643,12 +680,7 @@
 
 SCLASS int _giant_count;
 
-/* Garbage collector mutex and condition variable. */
-SCLASS	pthread_mutex_t _gc_mutex
-#ifdef GLOBAL_PTHREAD_PRIVATE
-= NULL
-#endif
-;
+/* Garbage collector condition variable. */
 SCLASS	pthread_cond_t  _gc_cond
 #ifdef GLOBAL_PTHREAD_PRIVATE
 = NULL
@@ -687,7 +719,7 @@
 void	_cond_wait_backout(pthread_t);
 int     _find_thread(pthread_t);
 pthread_t _get_curthread(void);
-void	*_set_curthread(ucontext_t *, struct pthread *);
+void	*_set_curthread(ucontext_t *, struct pthread *, int *);
 void	_retire_thread(void *arch_id);
 void	*_thread_stack_alloc(size_t, size_t);
 void	_thread_stack_free(void *, size_t, size_t);
@@ -713,6 +745,7 @@
 int	_pthread_once(pthread_once_t *, void (*) (void));
 pthread_t _pthread_self(void);
 int	_pthread_setspecific(pthread_key_t, const void *);
+int	_spintrylock(spinlock_t *);
 inline void _spinlock_pthread(pthread_t, spinlock_t *);
 inline void _spinunlock_pthread(pthread_t, spinlock_t *);
 void    _thread_exit(char *, int, char *);

==== //depot/projects/hammer/lib/libthr/thread/thr_spinlock.c#3 (text+ko) ====

@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_spinlock.c,v 1.3 2003/05/23 23:39:31 mtm Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_spinlock.c,v 1.4 2003/05/25 08:48:11 mtm Exp $
  *
  */
 
@@ -69,6 +69,16 @@
 	_spinlock_pthread(curthread, lck);
 }
 
+int
+_spintrylock(spinlock_t *lck)
+{
+	int error;
+	error = umtx_trylock((struct umtx *)lck, curthread->thr_id);
+	if (error != 0 && error != EBUSY)
+		abort();
+	return (error);
+}
+
 inline void
 _spinlock_pthread(pthread_t pthread, spinlock_t *lck)
 {

==== //depot/projects/hammer/lib/libthr/thread/thr_stack.c#2 (text+ko) ====

@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libthr/thread/thr_stack.c,v 1.1 2003/04/01 03:46:29 jeff Exp $
+ * $FreeBSD: src/lib/libthr/thread/thr_stack.c,v 1.3 2003/05/26 00:37:07 mtm Exp $
  */
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -144,8 +144,7 @@
 		 * Use the garbage collector mutex for synchronization of the
 		 * spare stack list.
 		 */
-		if (pthread_mutex_lock(&_gc_mutex) != 0)
-			PANIC("Cannot lock gc mutex");
+		STACK_LOCK;
 
 		if ((spare_stack = LIST_FIRST(&_dstackq)) != NULL) {
 				/* Use the spare stack. */
@@ -154,8 +153,7 @@
 		}
 
 		/* Unlock the garbage collector mutex. */
-		if (pthread_mutex_unlock(&_gc_mutex) != 0)
-			PANIC("Cannot unlock gc mutex");
+		STACK_UNLOCK;
 	}

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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