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>