diff options
author | David Leonard <d@cvs.openbsd.org> | 1999-11-25 07:01:48 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 1999-11-25 07:01:48 +0000 |
commit | 0fe78c3128864d128b2b10153b8d533ff8c00375 (patch) | |
tree | 5229c3d97eed15f4d71927a5f454180aef2632f6 /lib | |
parent | ed00fa742a6455d22e3b56cf846dc5acd7a51fd7 (diff) |
sync with FreeBSD
Diffstat (limited to 'lib')
260 files changed, 5292 insertions, 4758 deletions
diff --git a/lib/libc_r/arch/alpha/uthread_machdep.h b/lib/libc_r/arch/alpha/uthread_machdep.h index 7ee0653367d..9a7c52da977 100644 --- a/lib/libc_r/arch/alpha/uthread_machdep.h +++ b/lib/libc_r/arch/alpha/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/alpha machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.4 1999/02/04 23:37:39 niklas Exp $ + * $OpenBSD: uthread_machdep.h,v 1.5 1999/11/25 07:01:27 d Exp $ */ /* save the floating point state of a thread */ @@ -50,11 +50,11 @@ do { \ { \ /* entry */ \ (thr)->saved_jmp_buf[2] = (long) entry; \ - (thr)->saved_jmp_buf[4+R_RA] = 0; \ - (thr)->saved_jmp_buf[4+R_T12] = (long) entry; \ + (thr)->saved_jmp_buf[4 + R_RA] = 0; \ + (thr)->saved_jmp_buf[4 + R_T12] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[4 + R_SP] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[4 + R_SP] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libc_r/arch/hppa/uthread_machdep.h b/lib/libc_r/arch/hppa/uthread_machdep.h index 773bd90e22f..0d80d718ded 100644 --- a/lib/libc_r/arch/hppa/uthread_machdep.h +++ b/lib/libc_r/arch/hppa/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/hppa machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.2 1999/01/17 23:49:48 d Exp $$ + * $OpenBSD: uthread_machdep.h,v 1.3 1999/11/25 07:01:27 d Exp $$ */ /* save the floating point state of a thread */ @@ -23,8 +23,8 @@ /* entry */ \ (thr)->saved_jmp_buf[5] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[2] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[2] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libc_r/arch/i386/uthread_machdep.h b/lib/libc_r/arch/i386/uthread_machdep.h index cac445509ca..dab5c413932 100644 --- a/lib/libc_r/arch/i386/uthread_machdep.h +++ b/lib/libc_r/arch/i386/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/i386 machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.5 1999/03/10 09:50:33 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.6 1999/11/25 07:01:28 d Exp $ */ #include <machine/reg.h> @@ -59,9 +59,10 @@ struct _machdep_struct { /* entry */ \ (thr)->saved_jmp_buf.mjb_eip = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf.mjb_esp = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ - - sizeof(double); \ + (thr)->saved_jmp_buf.mjb_esp = \ + (long) (thr)->stack->base + \ + (thr)->stack->size \ + - sizeof(double); \ } static __inline int diff --git a/lib/libc_r/arch/m68k/uthread_machdep.h b/lib/libc_r/arch/m68k/uthread_machdep.h index 4ed702981b5..8bda374924d 100644 --- a/lib/libc_r/arch/m68k/uthread_machdep.h +++ b/lib/libc_r/arch/m68k/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/m68k machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.2 1999/01/17 23:49:49 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.3 1999/11/25 07:01:28 d Exp $ */ /* save the floating point state of a thread */ @@ -23,8 +23,8 @@ /* entry */ \ (thr)->saved_jmp_buf[5] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[2] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[2] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libc_r/arch/m88k/uthread_machdep.h b/lib/libc_r/arch/m88k/uthread_machdep.h index dcad59d851d..0fcad5cf0ae 100644 --- a/lib/libc_r/arch/m88k/uthread_machdep.h +++ b/lib/libc_r/arch/m88k/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/m88k machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.1 1999/03/03 06:00:10 smurph Exp $ + * $OpenBSD: uthread_machdep.h,v 1.2 1999/11/25 07:01:28 d Exp $ */ /* save the floating point state of a thread */ @@ -23,8 +23,8 @@ /* entry */ \ (thr)->saved_jmp_buf[5] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[2] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[2] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libc_r/arch/mips/uthread_machdep.h b/lib/libc_r/arch/mips/uthread_machdep.h index 6052b2003da..89fb399d629 100644 --- a/lib/libc_r/arch/mips/uthread_machdep.h +++ b/lib/libc_r/arch/mips/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/mips machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.3 1999/01/17 23:49:49 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.4 1999/11/25 07:01:28 d Exp $ */ #include <machine/regnum.h> @@ -23,8 +23,8 @@ j->sc_regs[RA] = j->sc_pc; /* for gdb */ \ j->sc_pc = (int)entry; \ /* stack */ \ - j->sc_regs[SP] = (int) (thr)->stack \ - + (pattr)->stacksize_attr \ + j->sc_regs[SP] = (int) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libc_r/arch/powerpc/uthread_machdep.h b/lib/libc_r/arch/powerpc/uthread_machdep.h index bd713b5ff0e..6041279d95e 100644 --- a/lib/libc_r/arch/powerpc/uthread_machdep.h +++ b/lib/libc_r/arch/powerpc/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/powerpc machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.3 1999/04/21 03:45:21 rahnds Exp $ + * $OpenBSD: uthread_machdep.h,v 1.4 1999/11/25 07:01:29 d Exp $ */ /* save the floating point state of a thread */ @@ -24,8 +24,8 @@ (thr)->saved_jmp_buf[JMP_lr] = \ (unsigned int) entry; \ (thr)->saved_jmp_buf[JMP_r1] = \ - ((unsigned int) (thr)->stack \ - + (pattr)->stacksize_attr \ + ((unsigned int) (thr)->stack->base \ + + (thr)->stack->size \ - 0x4) & ~0xf; \ { \ unsigned int *pbacklink = \ diff --git a/lib/libc_r/arch/sparc/uthread_machdep.h b/lib/libc_r/arch/sparc/uthread_machdep.h index c922b49fd0c..46ffd6dc92c 100644 --- a/lib/libc_r/arch/sparc/uthread_machdep.h +++ b/lib/libc_r/arch/sparc/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/sparc machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.2 1999/01/17 23:49:49 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.3 1999/11/25 07:01:29 d Exp $ */ #include <sys/signal.h> @@ -9,13 +9,13 @@ /* save the floating point state of a thread */ #define _thread_machdep_save_float_state(thr) \ { \ - /* XXX tdb */ \ + /* XXX tdb */ \ } /* restore the floating point state of a thread */ #define _thread_machdep_restore_float_state(thr) \ { \ - /* XXX tdb */ \ + /* XXX tdb */ \ } /* initialise the jmpbuf stack frame so it continues from entry */ @@ -25,19 +25,13 @@ /* entry */ \ (thr)->saved_jmp_buf[1] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[0] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[0] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } -/* - * XXX high chance of longjmp botch (see libc/arch/sparc/gen/_setjmp.S) - * because it uses the frame pointer to pop off frames.. we don't want - * that.. what to do? fudge %fp? do our own setjmp? - */ -#define _thread_machdep_longjmp(a,v) _longjmp(a,v) -#define _thread_machdep_setjmp(a) _setjmp(a) - +#define _thread_machdep_longjmp(a,v) _longjmp(a,v) +#define _thread_machdep_setjmp(a) _setjmp(a) typedef jmp_buf _machdep_jmp_buf; struct _machdep_struct { diff --git a/lib/libc_r/include/pthread.h b/lib/libc_r/include/pthread.h index 108f4d2de41..d94bbe8173f 100644 --- a/lib/libc_r/include/pthread.h +++ b/lib/libc_r/include/pthread.h @@ -30,13 +30,19 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: pthread.h,v 1.8 1999/06/15 00:10:37 d Exp $ + * $OpenBSD: pthread.h,v 1.9 1999/11/25 07:01:29 d Exp $ * + * $FreeBSD: pthread.h,v 1.13 1999/07/31 08:36:07 rse Exp $ */ #ifndef _PTHREAD_H_ #define _PTHREAD_H_ #ifdef _POSIX_THREADS +#ifdef notyet +#warning -pthread option no longer needed - upgrade gcc +#endif +#undef _POSIX_THREADS +#endif /* * Header files. @@ -62,7 +68,7 @@ * Note that those commented out are not currently supported by the * implementation. */ - +#define _POSIX_THREADS #define _POSIX_THREAD_ATTR_STACKADDR #define _POSIX_THREAD_ATTR_STACKSIZE #define _POSIX_THREAD_PRIORITY_SCHEDULING @@ -113,7 +119,6 @@ struct pthread_mutex_attr; struct pthread_once; struct pthread_rwlock; struct pthread_rwlockattr; -struct sched_param; /* * Primitive system data type definitions required by P1003.1c. @@ -209,7 +214,6 @@ int pthread_attr_init __P((pthread_attr_t *)); int pthread_attr_setstacksize __P((pthread_attr_t *, size_t)); int pthread_attr_setstackaddr __P((pthread_attr_t *, void *)); int pthread_attr_setdetachstate __P((pthread_attr_t *, int)); -int pthread_cancel __P((pthread_t)); void pthread_cleanup_pop __P((int execute)); void pthread_cleanup_push __P((void (*routine) (void *), void *routine_arg)); @@ -252,7 +256,7 @@ int pthread_mutex_lock __P((pthread_mutex_t *)); int pthread_mutex_trylock __P((pthread_mutex_t *)); int pthread_mutex_unlock __P((pthread_mutex_t *)); int pthread_once __P((pthread_once_t *, - void (*init_routine) (void))); + void (*) (void))); int pthread_rwlock_destroy __P((pthread_rwlock_t *)); int pthread_rwlock_init __P((pthread_rwlock_t *, const pthread_rwlockattr_t *)); @@ -268,12 +272,13 @@ int pthread_rwlockattr_setpshared __P((pthread_rwlockattr_t *, int *)); int pthread_rwlockattr_destroy __P((pthread_rwlockattr_t *)); pthread_t pthread_self __P((void)); -int pthread_setcancelstate __P((int, int *)); -int pthread_setcanceltype __P((int, int *)); int pthread_setspecific __P((pthread_key_t, const void *)); int pthread_sigmask __P((int, const sigset_t *, sigset_t *)); -void pthread_testcancel __P((void)); +int pthread_cancel __P((pthread_t)); +int pthread_setcancelstate __P((int, int *)); +int pthread_setcanceltype __P((int, int *)); +void pthread_testcancel __P((void)); int pthread_getprio __P((pthread_t)); int pthread_setprio __P((pthread_t, int)); @@ -326,15 +331,13 @@ int pthread_attr_setcleanup __P((pthread_attr_t *, void (*routine) (void *), void *)); -#if 0 +#ifdef notyet /* - * Single Unix Specification v2 (UNIX98) also wants these: + * Single Unix Specification v2 (UNIX98) defines these: */ - #define PTHREAD_PRIO_INHERIT #define PTHREAD_PRIO_NONE #define PTHREAD_PRIO_PROTECT - int pthread_attr_getguardsize __P((const pthread_attr_t *, size_t *)); int pthread_attr_setguardsize __P((const pthread_attr_t *, @@ -343,12 +346,8 @@ int pthread_getconcurrency __P((void)); int pthread_mutexattr_gettype __P((const pthread_mutexattr_t *, int *)); int pthread_setconcurrency __P((int)); - #endif /* susv2 */ __END_DECLS -#else /* ! _POSIX_THREADS */ -#warning "included <pthread.h> without -pthread compiler option" -#endif /* ! _POSIX_THREADS */ #endif /* _PTHREAD_H_ */ diff --git a/lib/libc_r/include/pthread_np.h b/lib/libc_r/include/pthread_np.h index 6f8b7b7ef44..a6071d9e4d0 100644 --- a/lib/libc_r/include/pthread_np.h +++ b/lib/libc_r/include/pthread_np.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pthread_np.h,v 1.2 1999/05/26 00:17:41 d Exp $ */ +/* $OpenBSD: pthread_np.h,v 1.3 1999/11/25 07:01:29 d Exp $ */ /* * Copyright (c) 1996-98 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -48,11 +48,11 @@ int pthread_multi_np __P((void)); int pthread_resume_np __P((pthread_t)); int pthread_single_np __P((void)); int pthread_suspend_np __P((pthread_t)); -int pthread_mutexattr_getkind_np __P((pthread_mutexattr_t attr)); -int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *attr, int kind)); +int pthread_mutexattr_getkind_np __P((pthread_mutexattr_t)); +int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *, int)); void pthread_set_name_np __P((pthread_t, char *)); -int pthread_switch_add_np (pthread_switch_routine_t routine); -int pthread_switch_delete_np (pthread_switch_routine_t routine); +int pthread_switch_add_np __P((pthread_switch_routine_t)); +int pthread_switch_delete_np __P((pthread_switch_routine_t)); __END_DECLS #endif diff --git a/lib/libc_r/include/sched.h b/lib/libc_r/include/sched.h index 292edf7b2e3..46f8e9703d8 100644 --- a/lib/libc_r/include/sched.h +++ b/lib/libc_r/include/sched.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sched.h,v 1.2 1999/03/10 10:03:52 d Exp $ */ +/* $OpenBSD: sched.h,v 1.3 1999/11/25 07:01:29 d Exp $ */ #ifndef _SCHED_H_ #define _SCHED_H_ @@ -40,6 +40,10 @@ #include <sys/types.h> /* For pid_t */ +#ifndef KERNEL +#include <time.h> /* Per P1003.4 */ +#endif + /* Scheduling policies */ #define SCHED_FIFO 1 @@ -53,8 +57,6 @@ struct sched_param #ifndef KERNEL #include <sys/cdefs.h> -#include <time.h> /* Per P1003.4 */ -#include <sys/time.h> __BEGIN_DECLS int sched_setparam __P((pid_t, const struct sched_param *)); diff --git a/lib/libc_r/include/spinlock.h b/lib/libc_r/include/spinlock.h index 4da4a9ec500..772331be377 100644 --- a/lib/libc_r/include/spinlock.h +++ b/lib/libc_r/include/spinlock.h @@ -29,8 +29,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: spinlock.h,v 1.3 1999/01/18 00:03:34 d Exp $ - * $OpenBSD: spinlock.h,v 1.3 1999/01/18 00:03:34 d Exp $ + * $Id: spinlock.h,v 1.4 1999/11/25 07:01:29 d Exp $ + * $OpenBSD: spinlock.h,v 1.4 1999/11/25 07:01:29 d Exp $ * * Lock definitions used in both libc and libpthread. * @@ -61,6 +61,8 @@ typedef struct { #define _SPINLOCK(_lck) _spinlock(_lck) #endif +#define _SPINLOCK_INIT(_lck) _SPINUNLOCK(_lck) + /* * Thread function prototype definitions: */ diff --git a/lib/libc_r/sys/Makefile.inc b/lib/libc_r/sys/Makefile.inc index 2c4ee0df2fd..79b6afe2a4d 100644 --- a/lib/libc_r/sys/Makefile.inc +++ b/lib/libc_r/sys/Makefile.inc @@ -1,17 +1,23 @@ -# $Id: Makefile.inc,v 1.3 1999/01/06 05:36:18 d Exp $ -# $OpenBSD: Makefile.inc,v 1.3 1999/01/06 05:36:18 d Exp $ +# $Id: Makefile.inc,v 1.4 1999/11/25 07:01:29 d Exp $ +# $OpenBSD: Makefile.inc,v 1.4 1999/11/25 07:01:29 d Exp $ .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} -SRCS+= uthread_error.c _atomic_lock.c slow_atomic_lock.c +SRCS+= uthread_error.c _atomic_lock.c slow_atomic_lock.c SRCS+= _sys_aliases.c CLEANFILES += _sys_aliases.c _sys_aliases.c: ${.CURDIR}/Makefile ${LIBCSRCDIR}/sys/Makefile.inc - (echo '#include <sys/cdefs.h>'; \ - for fn in ${ASM:R} ${PSEUDO:R} ""; do \ + echo '#include <sys/cdefs.h>' > ${.TARGET} +.if ${MACHINE} == "alpha" + # This kludge will disappear when we shift to -lpthread + echo '#define __indr_reference(old,new)' \ + '__asm__(".globl "#new";"#new": jmp $$31,"#old)' > ${.TARGET} + +.endif + for fn in ${ASM:R} ${PSEUDO:R} ""; do \ case $$fn in ${HIDDEN_SYSCALLS:.o=|}"") : stays hidden ;; \ *) echo "__indr_reference(_thread_sys_$$fn,$$fn);";; \ esac; \ - done ) > ${.TARGET} + done >> ${.TARGET} diff --git a/lib/libc_r/sys/uthread_error.c b/lib/libc_r/sys/uthread_error.c index 545dfb06652..08740ed92ff 100644 --- a/lib/libc_r/sys/uthread_error.c +++ b/lib/libc_r/sys/uthread_error.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_error.c,v 1.2 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu @@ -31,6 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_error.c,v 1.2 1999/08/05 12:14:13 deischen Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index 56a6b0046ba..00022b16eb6 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -1,5 +1,5 @@ -# $Id: Makefile.inc,v 1.8 1999/06/15 00:07:39 d Exp $ -# $OpenBSD: Makefile.inc,v 1.8 1999/06/15 00:07:39 d Exp $ +# $OpenBSD: Makefile.inc,v 1.9 1999/11/25 07:01:30 d Exp $ +# $FreeBSD: Makefile.inc,v 1.19 1999/08/28 00:03:19 peter Exp $ # uthread sources .PATH: ${.CURDIR}/uthread @@ -15,7 +15,6 @@ SRCS+= \ uthread_attr_getschedparam.c \ uthread_attr_getschedpolicy.c \ uthread_attr_getscope.c \ - uthread_attr_setstackaddr.c \ uthread_attr_getstackaddr.c \ uthread_attr_getstacksize.c \ uthread_attr_setcreatesuspend_np.c \ @@ -28,7 +27,6 @@ SRCS+= \ uthread_attr_setstacksize.c \ uthread_autoinit.c \ uthread_bind.c \ - uthread_fchflags.c \ uthread_cancel.c \ uthread_clean.c \ uthread_close.c \ @@ -63,7 +61,7 @@ SRCS+= \ uthread_getschedparam.c \ uthread_getsockname.c \ uthread_getsockopt.c \ - uthread_info.c \ + uthread_info_openbsd.c \ uthread_init.c \ uthread_ioctl.c \ uthread_join.c \ @@ -82,9 +80,8 @@ SRCS+= \ uthread_once.c \ uthread_open.c \ uthread_pipe.c \ - uthread_priority_queue.c \ uthread_poll.c \ - uthread_queue.c \ + uthread_priority_queue.c \ uthread_read.c \ uthread_readv.c \ uthread_recvfrom.c \ @@ -116,6 +113,7 @@ SRCS+= \ uthread_socketpair.c \ uthread_spec.c \ uthread_spinlock.c \ + uthread_stack.c \ uthread_suspend_np.c \ uthread_switch_np.c \ uthread_vfork.c \ diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index 69a36e13477..f49d0eb257e 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -1,3 +1,4 @@ +/* $OpenBSD: pthread_private.h,v 1.18 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -31,15 +32,12 @@ * * Private thread definitions for the uthread kernel. * - * $OpenBSD: pthread_private.h,v 1.17 1999/09/08 08:21:47 espie Exp $ - * + * $FreeBSD: pthread_private.h,v 1.27 1999/09/29 15:18:38 marcel Exp $ */ #ifndef _PTHREAD_PRIVATE_H #define _PTHREAD_PRIVATE_H -#include <paths.h> - /* * Include files. */ @@ -51,9 +49,7 @@ #include <sched.h> #include <spinlock.h> #include <pthread_np.h> -#ifndef _NO_UTHREAD_MACHDEP #include "uthread_machdep.h" -#endif /* * Kernel fatal error handler macro. @@ -66,33 +62,88 @@ /* - * Priority queue manipulation macros: + * Priority queue manipulation macros (using pqe link): */ #define PTHREAD_PRIOQ_INSERT_HEAD(thrd) _pq_insert_head(&_readyq,thrd) #define PTHREAD_PRIOQ_INSERT_TAIL(thrd) _pq_insert_tail(&_readyq,thrd) #define PTHREAD_PRIOQ_REMOVE(thrd) _pq_remove(&_readyq,thrd) -#define PTHREAD_PRIOQ_FIRST _pq_first(&_readyq) +#define PTHREAD_PRIOQ_FIRST() _pq_first(&_readyq) /* - * Waiting queue manipulation macros: + * Waiting queue manipulation macros (using pqe link): */ -#define PTHREAD_WAITQ_INSERT(thrd) TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe) +#if defined(_PTHREADS_INVARIANTS) +#define PTHREAD_WAITQ_REMOVE(thrd) _waitq_remove(thrd) +#define PTHREAD_WAITQ_INSERT(thrd) _waitq_insert(thrd) +#define PTHREAD_WAITQ_CLEARACTIVE() _waitq_clearactive() +#define PTHREAD_WAITQ_SETACTIVE() _waitq_setactive() +#else #define PTHREAD_WAITQ_REMOVE(thrd) TAILQ_REMOVE(&_waitingq,thrd,pqe) +#define PTHREAD_WAITQ_INSERT(thrd) do { \ + if ((thrd)->wakeup_time.tv_sec == -1) \ + TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe); \ + else { \ + pthread_t tid = TAILQ_FIRST(&_waitingq); \ + while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) && \ + ((tid->wakeup_time.tv_sec < (thrd)->wakeup_time.tv_sec) || \ + ((tid->wakeup_time.tv_sec == (thrd)->wakeup_time.tv_sec) && \ + (tid->wakeup_time.tv_nsec <= (thrd)->wakeup_time.tv_nsec)))) \ + tid = TAILQ_NEXT(tid, pqe); \ + if (tid == NULL) \ + TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe); \ + else \ + TAILQ_INSERT_BEFORE(tid,thrd,pqe); \ + } \ +} while (0) +#define PTHREAD_WAITQ_CLEARACTIVE() +#define PTHREAD_WAITQ_SETACTIVE() +#endif + +/* + * Work queue manipulation macros (using qe link): + */ +#define PTHREAD_WORKQ_INSERT(thrd) do { \ + TAILQ_INSERT_TAIL(&_workq,thrd,qe); \ + (thrd)->flags |= PTHREAD_FLAGS_IN_WORKQ; \ +} while (0) +#define PTHREAD_WORKQ_REMOVE(thrd) do { \ + TAILQ_REMOVE(&_workq,thrd,qe); \ + (thrd)->flags &= ~PTHREAD_FLAGS_IN_WORKQ; \ +} while (0) + /* * State change macro without scheduling queue change: */ -#define PTHREAD_SET_STATE(thrd, newstate) { \ +#define PTHREAD_SET_STATE(thrd, newstate) do { \ (thrd)->state = newstate; \ (thrd)->fname = __FILE__; \ (thrd)->lineno = __LINE__; \ -} +} while (0) /* * State change macro with scheduling queue change - This must be * called with preemption deferred (see thread_kern_sched_[un]defer). */ -#define PTHREAD_NEW_STATE(thrd, newstate) { \ +#if defined(_PTHREADS_INVARIANTS) +#define PTHREAD_NEW_STATE(thrd, newstate) do { \ + if (_thread_kern_new_state != 0) \ + PANIC("Recursive PTHREAD_NEW_STATE"); \ + _thread_kern_new_state = 1; \ + if ((thrd)->state != newstate) { \ + if ((thrd)->state == PS_RUNNING) { \ + PTHREAD_PRIOQ_REMOVE(thrd); \ + PTHREAD_WAITQ_INSERT(thrd); \ + } else if (newstate == PS_RUNNING) { \ + PTHREAD_WAITQ_REMOVE(thrd); \ + PTHREAD_PRIOQ_INSERT_TAIL(thrd); \ + } \ + } \ + _thread_kern_new_state = 0; \ + PTHREAD_SET_STATE(thrd, newstate); \ +} while (0) +#else +#define PTHREAD_NEW_STATE(thrd, newstate) do { \ if ((thrd)->state != newstate) { \ if ((thrd)->state == PS_RUNNING) { \ PTHREAD_PRIOQ_REMOVE(thrd); \ @@ -103,7 +154,8 @@ } \ } \ PTHREAD_SET_STATE(thrd, newstate); \ -} +} while (0) +#endif /* * Define the signals to be used for scheduling. @@ -117,15 +169,6 @@ #endif /* - * Queue definitions. - */ -struct pthread_queue { - struct pthread *q_next; - struct pthread *q_last; - void *q_data; -}; - -/* * Priority queues. * * XXX It'd be nice if these were contained in uthread_priority_queue.[ch]. @@ -145,14 +188,9 @@ typedef struct pq_queue { /* - * Static queue initialization values. - */ -#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL } - -/* * TailQ initialization values. */ -#define TAILQ_INITIALIZER { NULL, NULL } +#define TAILQ_INITIALIZER { NULL, NULL } /* * Mutex definitions. @@ -223,7 +261,7 @@ struct pthread_mutex_attr { */ enum pthread_cond_type { COND_TYPE_FAST, - COND_TYPE_MAX +#define COND_TYPE_MAX ((int)COND_TYPE_FAST + 1) }; struct pthread_cond { @@ -255,8 +293,8 @@ struct pthread_cond_attr { * Static cond initialization values. */ #define PTHREAD_COND_STATIC_INITIALIZER \ - { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, NULL, \ - 0, _SPINLOCK_INITIALIZER } + { COND_TYPE_FAST, TAILQ_INITIALIZER, NULL, NULL, \ + 0, _SPINLOCK_INITIALIZER } /* * Cleanup definitions. @@ -290,6 +328,13 @@ struct pthread_attr { * Miscellaneous definitions. */ #define PTHREAD_STACK_DEFAULT 65536 +/* + * Maximum size of initial thread's stack. This perhaps deserves to be larger + * than the stacks of other threads, since many applications are likely to run + * almost entirely on this stack. + */ +#define PTHREAD_STACK_INITIAL 0x100000 +/* Address immediately beyond the beginning of the initial thread stack. */ #define PTHREAD_DEFAULT_PRIORITY 64 #define PTHREAD_MAX_PRIORITY 126 #define PTHREAD_MIN_PRIORITY 0 @@ -301,12 +346,6 @@ struct pthread_attr { #define CLOCK_RES_NSEC 10000000 /* - * Number of microseconds between incremental priority updates for - * threads that are ready to run, but denied being run. - */ -#define INC_PRIO_USEC 500000 - -/* * Time slice period in microseconds. */ #define TIMESLICE_USEC 100000 @@ -343,6 +382,7 @@ enum pthread_state { PS_FDR_WAIT, PS_FDW_WAIT, PS_FILE_WAIT, + PS_POLL_WAIT, PS_SELECT_WAIT, PS_SLEEP_WAIT, PS_WAIT_WAIT, @@ -352,8 +392,8 @@ enum pthread_state { PS_JOIN, PS_SUSPENDED, PS_DEAD, - PS_DEADLOCK, - PS_STATE_MAX + PS_DEADLOCK +#define PS_STATE_MAX ((int)PS_DEADLOCK + 1) }; @@ -375,8 +415,8 @@ struct fd_table_entry { * state of the lock on the file descriptor. */ spinlock_t lock; - struct pthread_queue r_queue; /* Read queue. */ - struct pthread_queue w_queue; /* Write queue. */ + TAILQ_HEAD(, pthread) r_queue; /* Read queue. */ + TAILQ_HEAD(, pthread) w_queue; /* Write queue. */ struct pthread *r_owner; /* Ptr to thread owning read lock. */ struct pthread *w_owner; /* Ptr to thread owning write lock. */ const char *r_fname; /* Ptr to read lock source file name */ @@ -388,11 +428,9 @@ struct fd_table_entry { int flags; /* Flags used in open. */ }; -struct pthread_select_data { +struct pthread_poll_data { int nfds; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; + struct pollfd *fds; }; union pthread_wait_data { @@ -404,10 +442,21 @@ union pthread_wait_data { short branch; /* Line number, for debugging. */ const char *fname; /* Source file name for debugging.*/ } fd; - struct pthread_select_data * select_data; + struct pthread_poll_data * poll_data; spinlock_t *spinlock; }; +/* Spare thread stack. */ +struct stack { + SLIST_ENTRY(stack) qe; /* Queue entry for this stack. */ + void *base; /* Bottom of useful stack */ + size_t size; /* Size of useful stack */ + void *redzone; /* Red zone location */ + void *storage; /* allocated storage */ +}; + +typedef TAILQ_ENTRY(pthread) pthread_entry_t; + /* * Thread structure. */ @@ -425,15 +474,11 @@ struct pthread { */ spinlock_t lock; - /* - * Pointer to the next thread in the thread linked list. - */ - struct pthread *nxt; + /* Queue entry for list of all threads: */ + pthread_entry_t tle; - /* - * Pointer to the next thread in the dead thread linked list. - */ - struct pthread *nxt_dead; + /* Queue entry for list of dead threads: */ + pthread_entry_t dle; /* * Thread start routine, argument, stack pointer and thread @@ -441,7 +486,7 @@ struct pthread { */ void *(*start_routine)(void *); void *arg; - void *stack; + struct stack *stack; struct pthread_attr attr; /* @@ -450,6 +495,17 @@ struct pthread { */ struct sigcontext saved_sigcontext; + /* + * Saved jump buffer used in call to longjmp by _thread_kern_sched + * if sig_saved is FALSE. + */ + _machdep_jmp_buf saved_jmp_buf; + + /* + * Further machine-dependent context, valid if sig_saved is FALSE. + */ + struct _machdep_struct _machdep; + /* * TRUE if the last state saved was a signal context. FALSE if the * last state saved was a jump buffer. @@ -484,12 +540,6 @@ struct pthread { long slice_usec; /* - * Cumulative times spent in thread - */ - struct timeval ru_utime; - struct timeval ru_stime; - - /* * Incremental priority accumulated by thread while it is ready to * run but is denied being run. */ @@ -510,36 +560,41 @@ struct pthread { */ int error; - /* Join queue for waiting threads: */ - struct pthread_queue join_queue; + /* Join queue head and link for waiting threads: */ + TAILQ_HEAD(join_head, pthread) join_queue; /* - * The current thread can belong to only one scheduling queue - * at a time (ready or waiting queue). It can also belong to - * a queue of threads waiting on mutexes or condition variables. - * Use pqe for the scheduling queue link (both ready and waiting), - * and qe for other links (mutexes and condition variables). + * The current thread can belong to only one scheduling queue at + * a time (ready or waiting queue). It can also belong to (only) + * one of: * - * Pointer to queue (if any) on which the current thread is waiting. + * o A queue of threads waiting for a mutex + * o A queue of threads waiting for a condition variable + * o A queue of threads waiting for another thread to terminate + * (the join queue above) + * o A queue of threads waiting for a file descriptor lock + * o A queue of threads needing work done by the kernel thread + * (waiting for a spinlock or file I/O) * - * XXX The queuing should be changed to use the TAILQ entry below. - * XXX For the time being, it's hybrid. + * Use pqe for the scheduling queue link (both ready and waiting), + * and qe for other links. */ - struct pthread_queue *queue; - - /* Pointer to next element in queue. */ - struct pthread *qnxt; /* Priority queue entry for this thread: */ - TAILQ_ENTRY(pthread) pqe; + pthread_entry_t pqe; /* Queue entry for this thread: */ - TAILQ_ENTRY(pthread) qe; + pthread_entry_t qe; /* Wait data. */ union pthread_wait_data data; /* + * Allocated for converting select into poll. + */ + struct pthread_poll_data poll_data; + + /* * Set to TRUE if a blocking operation was * interrupted by a signal: */ @@ -549,25 +604,28 @@ struct pthread { int signo; /* - * Set to non-zero when this thread has deferred thread - * scheduling. We allow for recursive deferral. + * Set to non-zero when this thread has deferred signals. + * We allow for recursive deferral. */ - int sched_defer_count; + int sig_defer_count; /* * Set to TRUE if this thread should yield after undeferring - * thread scheduling. + * signals. */ - int yield_on_sched_undefer; + int yield_on_sig_undefer; /* Miscellaneous data. */ int flags; #define PTHREAD_FLAGS_PRIVATE 0x0001 #define PTHREAD_EXITING 0x0002 -#define PTHREAD_FLAGS_QUEUED 0x0004 /* in queue (qe is used) */ -#define PTHREAD_FLAGS_TRACE 0x0008 -#define PTHREAD_CANCELLING 0x0010 /* thread has been cancelled */ -#define PTHREAD_AT_CANCEL_POINT 0x0020 /* thread at cancel point */ +#define PTHREAD_FLAGS_IN_CONDQ 0x0004 /* in condition queue using qe link*/ +#define PTHREAD_FLAGS_IN_WORKQ 0x0008 /* in work queue using qe link */ +#define PTHREAD_FLAGS_IN_WAITQ 0x0010 /* in waiting queue using pqe link*/ +#define PTHREAD_FLAGS_IN_PRIOQ 0x0020 /* in priority queue using pqe link*/ +#define PTHREAD_FLAGS_TRACE 0x0040 /* for debugging purposes */ +#define PTHREAD_FLAGS_CANCELED 0x1000 /* thread has been cancelled */ +#define PTHREAD_FLAGS_CANCELPT 0x2000 /* thread at cancel point */ /* * Base priority is the user setable and retrievable priority @@ -590,7 +648,7 @@ struct pthread { /* * Active priority is always the maximum of the threads base * priority and inherited priority. When there is a change - * in either the real or inherited priority, the active + * in either the base or inherited priority, the active * priority must be recalculated. */ char active_priority; @@ -611,17 +669,6 @@ struct pthread { struct pthread_cleanup *cleanup; const char *fname; /* Ptr to source file name */ int lineno; /* Source line number. */ - - /* - * Saved jump buffer used in call to longjmp by _thread_kern_sched - * if sig_saved is FALSE. - */ - _machdep_jmp_buf saved_jmp_buf; - -#ifndef _UTHREAD_MACHDEP - /* Machine dependent information */ - struct _machdep_struct _machdep; -#endif }; /* @@ -629,14 +676,13 @@ struct pthread { */ /* Kernel thread structure used when there are no running threads: */ -extern struct pthread volatile _thread_kern_thread; -extern struct pthread * volatile _thread_kern_threadp; +extern struct pthread _thread_kern_thread; /* Ptr to the thread structure for the running thread: */ extern struct pthread * volatile _thread_run; /* Ptr to the thread structure for the last user thread to run: */ -extern struct pthread * volatile _last_user_thread; +extern struct pthread * volatile _last_user_thread; /* * Ptr to the thread running in single-threaded mode or NULL if @@ -644,22 +690,23 @@ extern struct pthread * volatile _last_user_thread; */ extern struct pthread * volatile _thread_single; -/* Ptr to the first thread in the thread linked list: */ -extern struct pthread * volatile _thread_link_list; +/* List of all threads: */ +typedef TAILQ_HEAD(, pthread) _thread_list_t; +extern _thread_list_t _thread_list; /* * Array of kernel pipe file descriptors that are used to ensure that * no signals are missed in calls to _select. */ -extern int _thread_kern_pipe[2]; -extern int _thread_kern_in_select; +extern int _thread_kern_pipe[2]; +extern int volatile _queue_signals; extern int _thread_kern_in_sched; /* Last time that an incremental priority update was performed: */ extern struct timeval kern_inc_prio_time; /* Dead threads: */ -extern struct pthread * volatile _thread_dead; +extern _thread_list_t _dead_list; /* Initial thread: */ extern struct pthread *_thread_initial; @@ -682,12 +729,18 @@ extern int _pthread_stdio_flags[3]; /* File table information: */ extern struct fd_table_entry **_thread_fd_table; + +/* Table for polling file descriptors: */ +extern struct pollfd *_thread_pfd_table; + extern const int dtablecount; -extern int _thread_dtablesize; +extern int _thread_dtablesize; /* Descriptor table size. */ + +extern int _clock_res_nsec; /* Clock resolution in nsec. */ /* Garbage collector mutex and condition variable. */ -extern pthread_mutex_t _gc_mutex; -extern pthread_cond_t _gc_cond; +extern pthread_mutex_t _gc_mutex; +extern pthread_cond_t _gc_cond; /* * Array of signal actions for this process. @@ -698,19 +751,32 @@ extern struct sigaction _thread_sigact[NSIG]; * Scheduling queues: */ extern pq_queue_t _readyq; -typedef TAILQ_HEAD(, pthread) _waitingq_t; -extern _waitingq_t _waitingq; +extern _thread_list_t _waitingq; + +/* + * Work queue: + */ +extern _thread_list_t _workq; -/* Indicates that the waitingq now has threads ready to run. */ -extern volatile int _waitingq_check_reqd; +/* Tracks the number of threads blocked while waiting for a spinlock. */ +extern volatile int _spinblock_count; + +/* Indicates that the signal queue needs to be checked. */ +extern volatile int _sigq_check_reqd; /* Thread switch hook. */ extern pthread_switch_routine_t _sched_switch_hook; /* - * Where SIGINFO writes thread states when /dev/tty cannot be opened + * Spare stack queue. Stacks of default size are cached in order to reduce + * thread creation time. Spare stacks are used in LIFO order to increase cache + * locality. */ -#define INFO_DUMP_FILE "/tmp/uthread.dump" +typedef SLIST_HEAD(, stack) _stack_list_t; +extern _stack_list_t _stackq; + +/* Used for _PTHREADS_INVARIANTS checking. */ +extern int _thread_kern_new_state; #ifdef _LOCK_DEBUG #define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock_debug(_fd, _type, \ @@ -722,6 +788,8 @@ extern pthread_switch_routine_t _sched_switch_hook; #define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type) #endif +extern int __isthreaded; + /* * Function prototype definitions. */ @@ -733,49 +801,52 @@ int _thread_fd_lock(int, int, struct timespec *); int _thread_fd_lock_debug(int, int, struct timespec *,const char *fname,int lineno); void _dispatch_signals(void); void _thread_signal(pthread_t, int); -void _lock_thread(void); -void _lock_thread_list(void); -void _unlock_thread(void); -void _unlock_thread_list(void); int _mutex_cv_lock(pthread_mutex_t *); int _mutex_cv_unlock(pthread_mutex_t *); +int _mutex_reinit(pthread_mutex_t *); void _mutex_notify_priochange(struct pthread *); -int _pq_init(struct pq_queue *pq, int, int); +int _cond_reinit(pthread_cond_t *); +int _pq_alloc(struct pq_queue *, int, int); +int _pq_init(struct pq_queue *); void _pq_remove(struct pq_queue *pq, struct pthread *); void _pq_insert_head(struct pq_queue *pq, struct pthread *); void _pq_insert_tail(struct pq_queue *pq, struct pthread *); struct pthread *_pq_first(struct pq_queue *pq); -void _thread_exit(const char *, int, const char *) - __attribute__((noreturn)); +#if defined(_PTHREADS_INVARIANTS) +void _waitq_insert(pthread_t pthread); +void _waitq_remove(pthread_t pthread); +void _waitq_setactive(void); +void _waitq_clearactive(void); +#endif +__dead void _thread_exit(const char *, int, const char *) __attribute__((noreturn)); void _thread_fd_unlock(int, int); -void _thread_fd_unlock_debug(int, int, char *, int); +void _thread_fd_unlock_debug(int, int, const char *, int); void *_thread_cleanup(pthread_t); void _thread_cleanupspecific(void); void _thread_dump_info(void); void _thread_init(void); void _thread_kern_sched(struct sigcontext *); -void _thread_kern_sched_state(enum pthread_state, const char *, int); +void _thread_kern_sched_state(enum pthread_state,const char *fname,int lineno); void _thread_kern_sched_state_unlock(enum pthread_state state, spinlock_t *lock, char *fname, int lineno); void _thread_kern_set_timeout(struct timespec *); -void _thread_kern_sched_defer(void); -void _thread_kern_sched_undefer(void); +void _thread_kern_sig_defer(void); +void _thread_kern_sig_undefer(void); void _thread_sig_handler(int, int, struct sigcontext *); +void _thread_sig_handle(int, struct sigcontext *); +void _thread_sig_init(void); void _thread_start(void); void _thread_start_sig_handler(void); void _thread_seterrno(pthread_t,int); -void _thread_queue_init(struct pthread_queue *); -void _thread_queue_enq(struct pthread_queue *, struct pthread *); -int _thread_queue_remove(struct pthread_queue *, struct pthread *); int _thread_fd_table_init(int fd); -struct pthread *_thread_queue_get(struct pthread_queue *); -struct pthread *_thread_queue_deq(struct pthread_queue *); pthread_addr_t _thread_gc(pthread_addr_t); void _thread_enter_cancellation_point(void); void _thread_leave_cancellation_point(void); void _thread_cancellation_point(void); int _thread_slow_atomic_lock(volatile _spinlock_lock_t *); int _thread_slow_atomic_is_locked(volatile _spinlock_lock_t *); +struct stack * _thread_stack_alloc(void *, size_t); +void _thread_stack_free(struct stack *); /* #include <signal.h> */ #ifdef _USER_SIGNAL_H @@ -900,7 +971,7 @@ int _thread_sys_fchdir(int); int _thread_sys_fchown(int, uid_t, gid_t); int _thread_sys_fsync(int); int _thread_sys_ftruncate(int, off_t); -long _thread_sys_fpathconf(int, int); +long _thread_sys_fpathconf(int, int); int _thread_sys_pause(void); int _thread_sys_pipe(int *); int _thread_sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); @@ -909,8 +980,7 @@ pid_t _thread_sys_fork(void); pid_t _thread_sys_tcgetpgrp(int); ssize_t _thread_sys_read(int, void *, size_t); ssize_t _thread_sys_write(int, const void *, size_t); -void _thread_sys__exit(int) - __attribute__((noreturn)); +__dead void _thread_sys__exit(int) __attribute__((noreturn)); #endif /* #include <fcntl.h> */ @@ -948,16 +1018,16 @@ ssize_t _thread_sys_writev(int, const struct iovec *, int); #endif /* #include <sys/wait.h> */ -#ifdef _SYS_WAIT_H_ +#ifdef _SYS_WAIT_H_ pid_t _thread_sys_wait(int *); pid_t _thread_sys_waitpid(pid_t, int *, int); pid_t _thread_sys_wait3(int *, int, struct rusage *); pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *); #endif -/* #include <sys/poll.h> */ +/* #include <poll.h> */ #ifdef _SYS_POLL_H_ -int _thread_sys_poll(struct pollfd[], int, int); +int _thread_sys_poll(struct pollfd *, unsigned, int); #endif /* #include <sys/mman.h> */ diff --git a/lib/libc_r/uthread/uthread_accept.c b/lib/libc_r/uthread/uthread_accept.c index 95f8c10b56c..db8d078c444 100644 --- a/lib/libc_r/uthread/uthread_accept.c +++ b/lib/libc_r/uthread/uthread_accept.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_accept.c,v 1.4 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_accept.c,v 1.3 1999/02/16 16:39:59 deraadt Exp $ + * $FreeBSD: uthread_accept.c,v 1.9 1999/08/28 00:03:20 peter Exp $ */ #include <errno.h> #include <unistd.h> diff --git a/lib/libc_r/uthread/uthread_attr_destroy.c b/lib/libc_r/uthread/uthread_attr_destroy.c index 51848d5d438..feb0c8309f0 100644 --- a/lib/libc_r/uthread/uthread_attr_destroy.c +++ b/lib/libc_r/uthread/uthread_attr_destroy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_destroy.c,v 1.3 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_destroy.c,v 1.2 1999/01/10 23:05:18 d Exp $ + * $FreeBSD: uthread_attr_destroy.c,v 1.4 1999/08/28 00:03:20 peter Exp $ */ #include <stdlib.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_attr_getdetachstate.c b/lib/libc_r/uthread/uthread_attr_getdetachstate.c index 52ebdfb89c1..f0326139902 100644 --- a/lib/libc_r/uthread/uthread_attr_getdetachstate.c +++ b/lib/libc_r/uthread/uthread_attr_getdetachstate.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_getdetachstate.c,v 1.3 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_getdetachstate.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_getdetachstate.c,v 1.3 1999/08/28 00:03:20 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_getinheritsched.c b/lib/libc_r/uthread/uthread_attr_getinheritsched.c index 54294c2e74b..da160586615 100644 --- a/lib/libc_r/uthread/uthread_attr_getinheritsched.c +++ b/lib/libc_r/uthread/uthread_attr_getinheritsched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getinheritsched.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getinheritsched.c,v 1.2 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getinheritsched.c,v 1.3 1999/08/28 00:03:21 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_getschedparam.c b/lib/libc_r/uthread/uthread_attr_getschedparam.c index 1a51d23b069..321d2b646b1 100644 --- a/lib/libc_r/uthread/uthread_attr_getschedparam.c +++ b/lib/libc_r/uthread/uthread_attr_getschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getschedparam.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getschedparam.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getschedparam.c,v 1.3 1999/08/28 00:03:21 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_getschedpolicy.c b/lib/libc_r/uthread/uthread_attr_getschedpolicy.c index 54977df53a0..5be8dcba3bf 100644 --- a/lib/libc_r/uthread/uthread_attr_getschedpolicy.c +++ b/lib/libc_r/uthread/uthread_attr_getschedpolicy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getschedpolicy.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getschedpolicy.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getschedpolicy.c,v 1.3 1999/08/28 00:03:21 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_getscope.c b/lib/libc_r/uthread/uthread_attr_getscope.c index 5dd4772ae46..68bfb0d6654 100644 --- a/lib/libc_r/uthread/uthread_attr_getscope.c +++ b/lib/libc_r/uthread/uthread_attr_getscope.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getscope.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getscope.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getscope.c,v 1.3 1999/08/28 00:03:22 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_getstackaddr.c b/lib/libc_r/uthread/uthread_attr_getstackaddr.c index 0e0cb724b33..1a99e1db8a8 100644 --- a/lib/libc_r/uthread/uthread_attr_getstackaddr.c +++ b/lib/libc_r/uthread/uthread_attr_getstackaddr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_getstackaddr.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_getstackaddr.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_getstackaddr.c,v 1.3 1999/08/28 00:03:22 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_getstacksize.c b/lib/libc_r/uthread/uthread_attr_getstacksize.c index c62ca413e62..f8d2f0b054c 100644 --- a/lib/libc_r/uthread/uthread_attr_getstacksize.c +++ b/lib/libc_r/uthread/uthread_attr_getstacksize.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_getstacksize.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_getstacksize.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_getstacksize.c,v 1.3 1999/08/28 00:03:22 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_init.c b/lib/libc_r/uthread/uthread_attr_init.c index 04cca9e6cb8..2842ef38a6d 100644 --- a/lib/libc_r/uthread/uthread_attr_init.c +++ b/lib/libc_r/uthread/uthread_attr_init.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_init.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_init.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_init.c,v 1.4 1999/08/28 00:03:23 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c b/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c index 56c762c32f4..64c30da907e 100644 --- a/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c +++ b/lib/libc_r/uthread/uthread_attr_setcreatesuspend_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setcreatesuspend_np.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setcreatesuspend_np.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setcreatesuspend_np.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setdetachstate.c b/lib/libc_r/uthread/uthread_attr_setdetachstate.c index 5f86679e299..1c9e413d85a 100644 --- a/lib/libc_r/uthread/uthread_attr_setdetachstate.c +++ b/lib/libc_r/uthread/uthread_attr_setdetachstate.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setdetachstate.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setdetachstate.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setdetachstate.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setinheritsched.c b/lib/libc_r/uthread/uthread_attr_setinheritsched.c index 0e0e015558a..61e0f2f6144 100644 --- a/lib/libc_r/uthread/uthread_attr_setinheritsched.c +++ b/lib/libc_r/uthread/uthread_attr_setinheritsched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setinheritsched.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_setinheritsched.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setinheritsched.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setprio.c b/lib/libc_r/uthread/uthread_attr_setprio.c index 4a548b3a201..f36e07208c6 100644 --- a/lib/libc_r/uthread/uthread_attr_setprio.c +++ b/lib/libc_r/uthread/uthread_attr_setprio.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setprio.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setprio.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setprio.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setschedparam.c b/lib/libc_r/uthread/uthread_attr_setschedparam.c index 2ff67680fe8..216e1992c8b 100644 --- a/lib/libc_r/uthread/uthread_attr_setschedparam.c +++ b/lib/libc_r/uthread/uthread_attr_setschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setschedparam.c,v 1.1 1999/05/26 00:18:23 d Exp $ */ +/* $OpenBSD: uthread_attr_setschedparam.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setschedparam.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setschedpolicy.c b/lib/libc_r/uthread/uthread_attr_setschedpolicy.c index 2b47a9d9339..f5090d987a9 100644 --- a/lib/libc_r/uthread/uthread_attr_setschedpolicy.c +++ b/lib/libc_r/uthread/uthread_attr_setschedpolicy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setschedpolicy.c,v 1.1 1999/05/26 00:18:23 d Exp $ */ +/* $OpenBSD: uthread_attr_setschedpolicy.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setschedpolicy.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setscope.c b/lib/libc_r/uthread/uthread_attr_setscope.c index 26fdaf6f32c..e40b73afcb8 100644 --- a/lib/libc_r/uthread/uthread_attr_setscope.c +++ b/lib/libc_r/uthread/uthread_attr_setscope.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setscope.c,v 1.1 1999/05/26 00:18:23 d Exp $ */ +/* $OpenBSD: uthread_attr_setscope.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setscope.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setstackaddr.c b/lib/libc_r/uthread/uthread_attr_setstackaddr.c index ccef1189723..2dcdd79eee1 100644 --- a/lib/libc_r/uthread/uthread_attr_setstackaddr.c +++ b/lib/libc_r/uthread/uthread_attr_setstackaddr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setstackaddr.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setstackaddr.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setstackaddr.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_attr_setstacksize.c b/lib/libc_r/uthread/uthread_attr_setstacksize.c index ee73ae39a9a..6b1792d02dc 100644 --- a/lib/libc_r/uthread/uthread_attr_setstacksize.c +++ b/lib/libc_r/uthread/uthread_attr_setstacksize.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setstacksize.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setstacksize.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setstacksize.c,v 1.4 1999/08/28 00:03:26 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_autoinit.c b/lib/libc_r/uthread/uthread_autoinit.c index 85aae18b063..850aec29f09 100644 --- a/lib/libc_r/uthread/uthread_autoinit.c +++ b/lib/libc_r/uthread/uthread_autoinit.c @@ -1,7 +1,7 @@ /* * David Leonard, 1998. Public Domain. <david.leonard@csee.uq.edu.au> * - * $OpenBSD: uthread_autoinit.c,v 1.6 1999/03/10 10:05:39 d Exp $ + * $OpenBSD: uthread_autoinit.c,v 1.7 1999/11/25 07:01:32 d Exp $ */ #include <stdio.h> @@ -49,7 +49,7 @@ _thread_dot_init() * found in the .dynamic section into the _INIT field. This then gets * automatically run by GNU ELF's ld.so. */ -#ifdef pmax +#ifdef __mips__ extern int _init() __attribute__((constructor,section (".dynamic"))); int _init() @@ -58,7 +58,7 @@ _init() _thread_init(); return 0; } -#endif /* mips */ +#endif /* __mips__ */ /* * A GNU C installation may know how to automatically run @@ -68,7 +68,7 @@ _init() * the collect2 stage of linkage will inform __main (from libgcc.a) * to call it. */ -#ifdef __GNUC__ +#if defined(__GNUC__) /* && defined(notyet) /* internal compiler error??? */ void _thread_init_constructor __P((void)) __attribute__((constructor)); void _thread_init_constructor() @@ -80,6 +80,6 @@ _thread_init_constructor() /* * Dummy symbol referenced by uthread_init.o so this compilation unit - * is always loaded. + * is always loaded from archives. */ int _thread_autoinit_dummy_decl = 0; diff --git a/lib/libc_r/uthread/uthread_bind.c b/lib/libc_r/uthread/uthread_bind.c index 644b31a0197..fca26b55558 100644 --- a/lib/libc_r/uthread/uthread_bind.c +++ b/lib/libc_r/uthread/uthread_bind.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_bind.c,v 1.4 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_bind.c,v 1.3 1999/02/16 16:39:59 deraadt Exp $ + * $FreeBSD: uthread_bind.c,v 1.5 1999/08/28 00:03:26 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libc_r/uthread/uthread_cancel.c b/lib/libc_r/uthread/uthread_cancel.c index f3a205d1e9e..e43e03bf00b 100644 --- a/lib/libc_r/uthread/uthread_cancel.c +++ b/lib/libc_r/uthread/uthread_cancel.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_cancel.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * David Leonard <d@openbsd.org>, 1999. Public domain. */ @@ -12,35 +13,33 @@ pthread_cancel(pthread) int ret; if ((ret = _find_thread(pthread))) { - } else if (pthread->state == PS_DEAD) - ret = 0; - else { - /* Set the threads's I've-been-cancelled flag: */ - pthread->flags |= PTHREAD_CANCELLING; + } else if ((pthread->flags & PTHREAD_FLAGS_CANCELED) == 0) { + /* Set the thread's I've-been-cancelled flag: */ + pthread->flags |= PTHREAD_FLAGS_CANCELED; /* Check if we need to kick it back into the run queue: */ if ((pthread->cancelstate == PTHREAD_CANCEL_ENABLE) && ((pthread->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) || - (pthread->flags & PTHREAD_AT_CANCEL_POINT))) + (pthread->flags & PTHREAD_FLAGS_CANCELPT))) switch (pthread->state) { - case PS_RUNNING: - /* No need to resume: */ - break; case PS_WAIT_WAIT: case PS_FDR_WAIT: case PS_FDW_WAIT: case PS_SLEEP_WAIT: case PS_SELECT_WAIT: + case PS_POLL_WAIT: case PS_SIGSUSPEND: /* Interrupt and resume: */ pthread->interrupted = 1; + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); PTHREAD_NEW_STATE(pthread,PS_RUNNING); break; case PS_MUTEX_WAIT: case PS_COND_WAIT: + case PS_SIGWAIT: case PS_FDLR_WAIT: case PS_FDLW_WAIT: case PS_FILE_WAIT: - case PS_SIGWAIT: case PS_JOIN: case PS_SUSPENDED: case PS_SIGTHREAD: @@ -48,8 +47,10 @@ pthread_cancel(pthread) /* XXX may be incorrect */ PTHREAD_NEW_STATE(pthread,PS_RUNNING); break; + case PS_RUNNING: + case PS_DEADLOCK: + case PS_SPINBLOCK: case PS_DEAD: - case PS_STATE_MAX: /* Ignore */ break; } @@ -134,14 +135,14 @@ _thread_enter_cancellation_point() /* Look for a cancellation before we block: */ _thread_cancellation_point(); - _thread_run->flags |= PTHREAD_AT_CANCEL_POINT; + _thread_run->flags |= PTHREAD_FLAGS_CANCELPT; } void _thread_leave_cancellation_point() { - _thread_run->flags &=~ PTHREAD_AT_CANCEL_POINT; + _thread_run->flags &=~ PTHREAD_FLAGS_CANCELPT; /* Look for a cancellation after we unblock: */ _thread_cancellation_point(); } @@ -155,9 +156,9 @@ _thread_cancellation_point() { if ((_thread_run->cancelstate == PTHREAD_CANCEL_ENABLE) && - ((_thread_run->flags & (PTHREAD_CANCELLING|PTHREAD_EXITING)) == - PTHREAD_CANCELLING)) { - _thread_run->flags &=~ PTHREAD_CANCELLING; + ((_thread_run->flags & (PTHREAD_FLAGS_CANCELED|PTHREAD_EXITING)) == + PTHREAD_FLAGS_CANCELED)) { + _thread_run->flags &=~ PTHREAD_FLAGS_CANCELED; pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } diff --git a/lib/libc_r/uthread/uthread_clean.c b/lib/libc_r/uthread/uthread_clean.c index c13519b0def..0fc9a272f7f 100644 --- a/lib/libc_r/uthread/uthread_clean.c +++ b/lib/libc_r/uthread/uthread_clean.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_clean.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_clean.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_clean.c,v 1.4 1999/08/28 00:03:26 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_close.c b/lib/libc_r/uthread/uthread_close.c index 6cfde5ca48e..a3dff060aec 100644 --- a/lib/libc_r/uthread/uthread_close.c +++ b/lib/libc_r/uthread/uthread_close.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_close.c,v 1.6 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_close.c,v 1.5 1999/06/09 07:16:16 d Exp $ + * $FreeBSD: uthread_close.c,v 1.7 1999/08/28 00:03:26 peter Exp $ */ +#include <errno.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> @@ -44,16 +46,26 @@ close(int fd) { int flags; int ret; + int status; struct stat sb; + struct fd_table_entry *entry; /* This is a cancelation point: */ _thread_enter_cancellation_point(); - /* Lock the file descriptor while the file is closed: */ - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { - /* Get file descriptor status. */ - _thread_sys_fstat(fd, &sb); - + if ((fd == _thread_kern_pipe[0]) || (fd == _thread_kern_pipe[1])) { + /* + * Don't allow silly programs to close the kernel pipe. + */ + errno = EBADF; + ret = -1; + } + /* + * Lock the file descriptor while the file is closed and get + * the file descriptor status: + */ + else if (((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) && + ((ret = _thread_sys_fstat(fd, &sb)) == 0)) { /* * Check if the file should be left as blocking. * @@ -81,11 +93,14 @@ close(int fd) _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); } + /* XXX: Assumes well behaved threads. */ + /* XXX: Defer real close to avoid race condition */ + entry = _thread_fd_table[fd]; + _thread_fd_table[fd] = NULL; + free(entry); + /* Close the file descriptor: */ ret = _thread_sys_close(fd); - - free(_thread_fd_table[fd]); - _thread_fd_table[fd] = NULL; } /* No longer in a cancellation point: */ diff --git a/lib/libc_r/uthread/uthread_cond.c b/lib/libc_r/uthread/uthread_cond.c index aef5daac188..aed1adc7662 100644 --- a/lib/libc_r/uthread/uthread_cond.c +++ b/lib/libc_r/uthread/uthread_cond.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_cond.c,v 1.7 1999/06/09 07:06:54 d Exp $ */ +/* $OpenBSD: uthread_cond.c,v 1.8 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_cond.c,v 1.18 1999/08/30 00:02:07 deischen Exp $ */ #include <stdlib.h> #include <errno.h> @@ -45,6 +46,28 @@ static inline pthread_t cond_queue_deq(pthread_cond_t); static inline void cond_queue_remove(pthread_cond_t, pthread_t); static inline void cond_queue_enq(pthread_cond_t, pthread_t); +/* Reinitialize a condition variable to defaults. */ +int +_cond_reinit(pthread_cond_t * cond) +{ + int ret = 0; + + if (cond == NULL) + ret = EINVAL; + else if (*cond == NULL) + ret = pthread_cond_init(cond, NULL); + else { + /* + * Initialize the condition variable structure: + */ + TAILQ_INIT(&(*cond)->c_queue); + (*cond)->c_flags = COND_FLAGS_INITED; + (*cond)->c_type = COND_TYPE_FAST; + (*cond)->c_mutex = NULL; + memset(&(*cond)->lock, 0, sizeof((*cond)->lock)); + } + return (ret); +} int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr) @@ -96,7 +119,7 @@ pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr) pcond->c_flags |= COND_FLAGS_INITED; pcond->c_type = type; pcond->c_mutex = NULL; - _SPINUNLOCK(&pcond->lock); + _SPINLOCK_INIT(&pcond->lock); *cond = pcond; } } @@ -136,6 +159,7 @@ int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) { int rval = 0; + int status; /* This is a cancellation point: */ _thread_enter_cancellation_point(); @@ -149,6 +173,9 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) */ else if (*cond != NULL || (rval = pthread_cond_init(cond,NULL)) == 0) { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + /* * If the condvar was statically allocated, properly * initialize the tail queue. @@ -158,9 +185,6 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) (*cond)->c_flags |= COND_FLAGS_INITED; } - /* Lock the condition variable structure: */ - _SPINLOCK(&(*cond)->lock); - /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ @@ -242,11 +266,16 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec * abstime) { int rval = 0; + int status; /* This is a cancellation point: */ _thread_enter_cancellation_point(); - if (cond == NULL) + if (cond == NULL || abstime == NULL) + rval = EINVAL; + + else if (abstime->tv_sec < 0 || + abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) rval = EINVAL; /* @@ -255,6 +284,9 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, */ else if (*cond != NULL || (rval = pthread_cond_init(cond,NULL)) == 0) { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + /* * If the condvar was statically allocated, properly * initialize the tail queue. @@ -264,10 +296,6 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, (*cond)->c_flags |= COND_FLAGS_INITED; } - - /* Lock the condition variable structure: */ - _SPINLOCK(&(*cond)->lock); - /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ @@ -367,6 +395,7 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, rval = EINVAL; break; } + } /* No longer in a cancellation point: */ @@ -385,6 +414,12 @@ pthread_cond_signal(pthread_cond_t * cond) if (cond == NULL || *cond == NULL) rval = EINVAL; else { + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + /* Lock the condition variable structure: */ _SPINLOCK(&(*cond)->lock); @@ -419,6 +454,12 @@ pthread_cond_signal(pthread_cond_t * cond) /* Unlock the condition variable structure: */ _SPINUNLOCK(&(*cond)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -435,14 +476,10 @@ pthread_cond_broadcast(pthread_cond_t * cond) rval = EINVAL; else { /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. In addition, we must assure - * that all threads currently waiting on the condition - * variable are signaled and are not timedout by a - * scheduling signal that causes a preemption. + * Defer signals to protect the scheduling queues + * from access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Lock the condition variable structure: */ _SPINLOCK(&(*cond)->lock); @@ -478,9 +515,11 @@ pthread_cond_broadcast(pthread_cond_t * cond) /* Unlock the condition variable structure: */ _SPINUNLOCK(&(*cond)->lock); - /* Reenable preemption and yield if necessary. + /* + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -498,7 +537,7 @@ cond_queue_deq(pthread_cond_t cond) if ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { TAILQ_REMOVE(&cond->c_queue, pthread, qe); - pthread->flags &= ~PTHREAD_FLAGS_QUEUED; + pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; } return(pthread); @@ -517,9 +556,9 @@ cond_queue_remove(pthread_cond_t cond, pthread_t pthread) * guard against removing the thread from the queue if * it isn't in the queue. */ - if (pthread->flags & PTHREAD_FLAGS_QUEUED) { + if (pthread->flags & PTHREAD_FLAGS_IN_CONDQ) { TAILQ_REMOVE(&cond->c_queue, pthread, qe); - pthread->flags &= ~PTHREAD_FLAGS_QUEUED; + pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; } } @@ -545,6 +584,6 @@ cond_queue_enq(pthread_cond_t cond, pthread_t pthread) tid = TAILQ_NEXT(tid, qe); TAILQ_INSERT_BEFORE(tid, pthread, qe); } - pthread->flags |= PTHREAD_FLAGS_QUEUED; + pthread->flags |= PTHREAD_FLAGS_IN_CONDQ; } #endif diff --git a/lib/libc_r/uthread/uthread_condattr_destroy.c b/lib/libc_r/uthread/uthread_condattr_destroy.c index 7e6aa2dc124..62e5a4495a8 100644 --- a/lib/libc_r/uthread/uthread_condattr_destroy.c +++ b/lib/libc_r/uthread/uthread_condattr_destroy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_condattr_destroy.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_condattr_destroy.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_condattr_destroy.c,v 1.4 1999/08/28 00:03:27 peter Exp $ */ #include <stdlib.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_condattr_init.c b/lib/libc_r/uthread/uthread_condattr_init.c index 0231bc78f7b..298989ccef4 100644 --- a/lib/libc_r/uthread/uthread_condattr_init.c +++ b/lib/libc_r/uthread/uthread_condattr_init.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_condattr_init.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_condattr_init.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_condattr_init.c,v 1.4 1999/08/28 00:03:27 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libc_r/uthread/uthread_connect.c b/lib/libc_r/uthread/uthread_connect.c index 59fc0724f47..a6a2f367189 100644 --- a/lib/libc_r/uthread/uthread_connect.c +++ b/lib/libc_r/uthread/uthread_connect.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_connect.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_connect.c,v 1.2 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_connect.c,v 1.6 1999/08/28 00:03:28 peter Exp $ */ #include <errno.h> #include <sys/types.h> @@ -43,8 +44,7 @@ int connect(int fd, const struct sockaddr * name, socklen_t namelen) { struct sockaddr tmpname; - int errnolen, ret; - socklen_t tmpnamelen; + int errnolen, ret, tmpnamelen; if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { if ((ret = _thread_sys_connect(fd, name, namelen)) < 0) { diff --git a/lib/libc_r/uthread/uthread_create.c b/lib/libc_r/uthread/uthread_create.c index 002f563d14a..67811b2d583 100644 --- a/lib/libc_r/uthread/uthread_create.c +++ b/lib/libc_r/uthread/uthread_create.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_create.c,v 1.11 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_create.c,v 1.10 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_create.c,v 1.19 1999/08/28 00:03:28 peter Exp $ */ #include <errno.h> #include <stdlib.h> @@ -37,22 +38,25 @@ #include <fcntl.h> #include <unistd.h> #include <sys/time.h> +#include <sys/types.h> +#include <sys/mman.h> #ifdef _THREAD_SAFE #include <machine/reg.h> #include <pthread.h> #include "pthread_private.h" -#include "thread_private.h" int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void *(*start_routine) (void *), void *arg) { int f_gc = 0; + int i; int ret = 0; + int status; pthread_t gc_thread; pthread_t new_thread; pthread_attr_t pattr; - void *stack; + struct stack *stack; /* * Locking functions in libc are required when there are @@ -72,31 +76,24 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, } else { pattr = *attr; } - /* Check if a stack was specified in the thread attributes: */ - if ((stack = pattr->stackaddr_attr) != NULL) { - } - /* Allocate memory for the stack: */ - else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) { - /* Insufficient memory to create a thread: */ + /* Create a stack from the specified attributes: */ + if ((stack = _thread_stack_alloc(pattr->stackaddr_attr, + pattr->stacksize_attr)) == NULL) { ret = EAGAIN; free(new_thread); } + /* Check for errors: */ if (ret != 0) { } else { /* Initialise the thread structure: */ memset(new_thread, 0, sizeof(struct pthread)); + _SPINLOCK_INIT(&new_thread->lock); new_thread->slice_usec = -1; new_thread->sig_saved = 0; new_thread->stack = stack; new_thread->start_routine = start_routine; new_thread->arg = arg; -#ifdef _THREAD_RUSAGE - timerclear(&new_thread->ru_utime); - timerclear(&new_thread->ru_stime); -#endif - _SPINUNLOCK(&new_thread->lock); - new_thread->cancelstate = PTHREAD_CANCEL_ENABLE; new_thread->canceltype = PTHREAD_CANCEL_DEFERRED; @@ -106,12 +103,6 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, */ new_thread->magic = PTHREAD_MAGIC; - if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { - PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); - } else { - PTHREAD_NEW_STATE(new_thread,PS_RUNNING); - } - /* Initialise the thread for signals: */ new_thread->sigmask = _thread_run->sigmask; @@ -123,8 +114,8 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, * returned from a longjmp() to the beginning of * _thread_start(). */ - - _thread_machdep_thread_create(new_thread, _thread_start, pattr); + _thread_machdep_thread_create(new_thread, _thread_start, + pattr); /* Copy the thread attributes: */ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); @@ -135,22 +126,26 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, */ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) { /* Copy the scheduling attributes: */ - new_thread->base_priority = _thread_run->base_priority; - new_thread->attr.prio = _thread_run->base_priority; - new_thread->attr.sched_policy = _thread_run->attr.sched_policy; + new_thread->base_priority + = _thread_run->base_priority; + new_thread->attr.prio + = _thread_run->base_priority; + new_thread->attr.sched_policy + = _thread_run->attr.sched_policy; } else { /* * Use just the thread priority, leaving the * other scheduling attributes as their * default values: */ - new_thread->base_priority = new_thread->attr.prio; + new_thread->base_priority + = new_thread->attr.prio; } new_thread->active_priority = new_thread->base_priority; new_thread->inherited_priority = 0; /* Initialise the join queue for the new thread: */ - _thread_queue_init(&(new_thread->join_queue)); + TAILQ_INIT(&(new_thread->join_queue)); /* Initialize the mutex queue: */ TAILQ_INIT(&new_thread->mutexq); @@ -158,32 +153,24 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, /* Initialise hooks in the thread structure: */ new_thread->specific_data = NULL; new_thread->cleanup = NULL; - new_thread->queue = NULL; - new_thread->qnxt = NULL; new_thread->flags = 0; + new_thread->poll_data.nfds = 0; + new_thread->poll_data.fds = NULL; - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); /* * Check if the garbage collector thread * needs to be started. */ - f_gc = (_thread_link_list == _thread_initial); + f_gc = (TAILQ_FIRST(&_thread_list) == _thread_initial); /* Add the thread to the linked list of all threads: */ - new_thread->nxt = _thread_link_list; - _thread_link_list = new_thread; - - /* Unlock the thread list: */ - _unlock_thread_list(); - - /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. - */ - _thread_kern_sched_defer(); + TAILQ_INSERT_HEAD(&_thread_list, new_thread, tle); if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { new_thread->state = PS_SUSPENDED; @@ -194,10 +181,10 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, } /* - * Reenable preemption and yield if a scheduling - * signal occurred while in the critical region. + * Undefer and handle pending signals, yielding + * if necessary. */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); /* Return a pointer to the thread structure: */ if (thread != NULL) diff --git a/lib/libc_r/uthread/uthread_detach.c b/lib/libc_r/uthread/uthread_detach.c index cb51ff0e43d..181f73b942f 100644 --- a/lib/libc_r/uthread/uthread_detach.c +++ b/lib/libc_r/uthread/uthread_detach.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_detach.c,v 1.5 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_detach.c,v 1.4 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_detach.c,v 1.10 1999/08/28 00:03:28 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -40,6 +41,7 @@ int pthread_detach(pthread_t pthread) { int rval = 0; + int status; pthread_t next_thread; /* Check for invalid calling parameters: */ @@ -53,23 +55,25 @@ pthread_detach(pthread_t pthread) pthread->attr.flags |= PTHREAD_DETACHED; /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Enter a loop to bring all threads off the join queue: */ - while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) { + while ((next_thread = TAILQ_FIRST(&pthread->join_queue)) != NULL) { + /* Remove the thread from the queue: */ + TAILQ_REMOVE(&pthread->join_queue, next_thread, qe); + /* Make the thread run: */ PTHREAD_NEW_STATE(next_thread,PS_RUNNING); } /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if a + * scheduling signal occurred while in the critical region. */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } else /* Return an error: */ rval = EINVAL; diff --git a/lib/libc_r/uthread/uthread_dup.c b/lib/libc_r/uthread/uthread_dup.c index c24031b8968..8aba9a1dba6 100644 --- a/lib/libc_r/uthread/uthread_dup.c +++ b/lib/libc_r/uthread/uthread_dup.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_dup.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_dup.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_dup.c,v 1.5 1999/08/28 00:03:29 peter Exp $ */ #include <unistd.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_dup2.c b/lib/libc_r/uthread/uthread_dup2.c index 2f34b8f7d32..2dfd9d8c361 100644 --- a/lib/libc_r/uthread/uthread_dup2.c +++ b/lib/libc_r/uthread/uthread_dup2.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_dup2.c,v 1.4 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_dup2.c,v 1.3 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_dup2.c,v 1.6 1999/08/28 00:03:29 peter Exp $ */ #include <errno.h> #include <unistd.h> diff --git a/lib/libc_r/uthread/uthread_equal.c b/lib/libc_r/uthread/uthread_equal.c index 4ec9505d579..54da618366f 100644 --- a/lib/libc_r/uthread/uthread_equal.c +++ b/lib/libc_r/uthread/uthread_equal.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_equal.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_equal.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_equal.c,v 1.3 1999/08/28 00:03:29 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libc_r/uthread/uthread_execve.c b/lib/libc_r/uthread/uthread_execve.c index ba87ccf8d98..b401dd1a145 100644 --- a/lib/libc_r/uthread/uthread_execve.c +++ b/lib/libc_r/uthread/uthread_execve.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_execve.c,v 1.5 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_execve.c,v 1.4 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_execve.c,v 1.8 1999/08/28 00:03:30 peter Exp $ */ #include <errno.h> #include <fcntl.h> @@ -93,6 +94,9 @@ execve(const char *name, char *const * argv, char *const * envp) act.sa_mask = _thread_sigact[i - 1].sa_mask; act.sa_flags = _thread_sigact[i - 1].sa_flags; + /* Ensure the scheduling signal is masked: */ + sigaddset(&act.sa_mask, _SCHED_SIGNAL); + /* Change the signal action for the process: */ _thread_sys_sigaction(i, &act, &oact); } diff --git a/lib/libc_r/uthread/uthread_exit.c b/lib/libc_r/uthread/uthread_exit.c index aba20d5cee2..976ccbbf46d 100644 --- a/lib/libc_r/uthread/uthread_exit.c +++ b/lib/libc_r/uthread/uthread_exit.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_exit.c,v 1.10 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,14 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_exit.c,v 1.9 1999/06/14 23:23:40 d Exp $ + * $FreeBSD: uthread_exit.c,v 1.12 1999/08/30 15:45:42 dt Exp $ */ #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <string.h> -#include <stdio.h> -#include <stdlib.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -77,31 +76,21 @@ void _exit(int status) _thread_sys__exit(status); } -/* - * Append a small number onto the end of a string. - * This avoids the need to use sprintf, which is unsafe sometimes. - */ static void -numlcat(char *s, int num, size_t size) +numlcat(char *s, int l, size_t sz) { - int i; - char digit[7]; + char digit[2]; - if (num<0) { - num = -num; - strlcat(s, "-", size); + /* Inefficient. */ + if (l < 0) { + l = -l; + strlcat(s, "-", sz); } - digit[sizeof digit - 1] = '\0'; - for (i = sizeof digit - 2; i >= 0; i--) { - digit[i] = '0' + (num % 10); - num /= 10; - if (num == 0) - break; - } - if (i<0) - strlcat(s, "inf", size); - else - strlcat(s, &digit[i], size); + if (l >= 10) + numlcat(s, l / 10, sz); + digit[0] = "0123456789"[l % 10]; + digit[1] = '\0'; + strlcat(s, digit, sz); } void @@ -118,30 +107,36 @@ _thread_exit(const char *fname, int lineno, const char *string) strlcat(s, fname, sizeof s); strlcat(s, " (errno = ", sizeof s); numlcat(s, errno, sizeof s); - strlcat(s, ", pid = ", sizeof s); - numlcat(s, _thread_sys_getpid(), sizeof s); strlcat(s, ")\n", sizeof s); /* Write the string to the standard error file descriptor: */ _thread_sys_write(2, s, strlen(s)); - /* Write a dump of the current thread status: */ - _thread_dump_info(); - - /* Try to dump a core file: */ + /* Force this process to exit: */ + /* XXX - Do we want abort to be conditional on _PTHREADS_INVARIANTS? */ +#if defined(_PTHREADS_INVARIANTS) abort(); +#else + _exit(1); +#endif } void pthread_exit(void *status) { + int sig; + long l; pthread_t pthread; /* Check if this thread is already in the process of exiting: */ if ((_thread_run->flags & PTHREAD_EXITING) != 0) { - char msg[128]; - snprintf(msg,sizeof msg,"Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",_thread_run); - PANIC(msg); + PANIC("Thread has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!"); + } + + /* Free thread-specific poll_data structure, if allocated */ + if (_thread_run->poll_data.fds != NULL) { + free(_thread_run->poll_data.fds); + _thread_run->poll_data.fds = NULL; } /* Flag this thread as exiting: */ @@ -164,22 +159,24 @@ pthread_exit(void *status) } /* - * Guard against preemption by a scheduling signal. A change of - * thread state modifies the waiting and priority queues. + * Defer signals to protect the scheduling queues from access + * by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Check if there are any threads joined to this one: */ - while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) { + while ((pthread = TAILQ_FIRST(&(_thread_run->join_queue))) != NULL) { + /* Remove the thread from the queue: */ + TAILQ_REMOVE(&_thread_run->join_queue, pthread, qe); + /* Wake the joined thread and let it detach this thread: */ PTHREAD_NEW_STATE(pthread,PS_RUNNING); } /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); /* * Lock the garbage collector mutex to ensure that the garbage @@ -189,8 +186,21 @@ pthread_exit(void *status) PANIC("Cannot lock gc mutex"); /* Add this thread to the list of dead threads. */ - _thread_run->nxt_dead = _thread_dead; - _thread_dead = _thread_run; + TAILQ_INSERT_HEAD(&_dead_list, _thread_run, dle); + + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Remove this thread from the thread list: */ + TAILQ_REMOVE(&_thread_list, _thread_run, tle); + + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); /* * Signal the garbage collector thread that there is something diff --git a/lib/libc_r/uthread/uthread_fchmod.c b/lib/libc_r/uthread/uthread_fchmod.c index 454483e410e..652f45c0fd7 100644 --- a/lib/libc_r/uthread/uthread_fchmod.c +++ b/lib/libc_r/uthread/uthread_fchmod.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fchmod.c,v 1.3 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fchmod.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_fchmod.c,v 1.5 1999/08/28 00:03:30 peter Exp $ */ #include <sys/types.h> #include <sys/stat.h> diff --git a/lib/libc_r/uthread/uthread_fchown.c b/lib/libc_r/uthread/uthread_fchown.c index 6b1d4ff1999..ed136ad7ac5 100644 --- a/lib/libc_r/uthread/uthread_fchown.c +++ b/lib/libc_r/uthread/uthread_fchown.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fchown.c,v 1.3 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fchown.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_fchown.c,v 1.5 1999/08/28 00:03:31 peter Exp $ */ #include <sys/types.h> #include <unistd.h> diff --git a/lib/libc_r/uthread/uthread_fcntl.c b/lib/libc_r/uthread/uthread_fcntl.c index c1348a7b27e..7070a564838 100644 --- a/lib/libc_r/uthread/uthread_fcntl.c +++ b/lib/libc_r/uthread/uthread_fcntl.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fcntl.c,v 1.6 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fcntl.c,v 1.5 1999/06/09 07:16:16 d Exp $ + * $FreeBSD: uthread_fcntl.c,v 1.8 1999/08/28 00:03:31 peter Exp $ */ #include <stdarg.h> #include <unistd.h> diff --git a/lib/libc_r/uthread/uthread_fd.c b/lib/libc_r/uthread/uthread_fd.c index 0b51f75b737..39303fc0820 100644 --- a/lib/libc_r/uthread/uthread_fd.c +++ b/lib/libc_r/uthread/uthread_fd.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fd.c,v 1.6 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_fd.c,v 1.10 1999/03/23 05:07:55 jb Exp $ - * $OpenBSD: uthread_fd.c,v 1.5 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_fd.c,v 1.13 1999/08/28 00:03:31 peter Exp $ * */ #include <errno.h> @@ -80,28 +80,28 @@ _thread_fd_table_init(int fd) ret = -1; } else { /* Initialise the file locks: */ - _SPINUNLOCK(&entry->lock); + _SPINLOCK_INIT(&entry->lock); entry->r_owner = NULL; entry->w_owner = NULL; entry->r_fname = NULL; entry->w_fname = NULL; - entry->r_lineno = 0;; - entry->w_lineno = 0;; - entry->r_lockcount = 0;; - entry->w_lockcount = 0;; + entry->r_lineno = 0; + entry->w_lineno = 0; + entry->r_lockcount = 0; + entry->w_lockcount = 0; /* Initialise the read/write queues: */ - _thread_queue_init(&entry->r_queue); - _thread_queue_init(&entry->w_queue); + TAILQ_INIT(&entry->r_queue); + TAILQ_INIT(&entry->w_queue); /* Get the flags for the file: */ - if (fd >= 3 && (entry->flags = - _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) { + if (((fd >= 3) || (_pthread_stdio_flags[fd] == -1)) && + (entry->flags = _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) { ret = -1; - } + } else { /* Check if a stdio descriptor: */ - if (fd < 3) + if ((fd < 3) && (_pthread_stdio_flags[fd] != -1)) /* * Use the stdio flags read by * _pthread_init() to avoid @@ -170,6 +170,12 @@ _thread_fd_unlock(int fd, int lock_type) */ if ((ret = _thread_fd_table_init(fd)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* * Lock the file descriptor table entry to prevent * other threads for clashing with the current * thread's accesses: @@ -196,8 +202,12 @@ _thread_fd_unlock(int fd, int lock_type) * Get the next thread in the queue for a * read lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->r_owner = _thread_queue_deq(&_thread_fd_table[fd]->r_queue)) == NULL) { + else if ((_thread_fd_table[fd]->r_owner = TAILQ_FIRST(&_thread_fd_table[fd]->r_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->r_queue, + _thread_fd_table[fd]->r_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -234,8 +244,12 @@ _thread_fd_unlock(int fd, int lock_type) * Get the next thread in the queue for a * write lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->w_owner = _thread_queue_deq(&_thread_fd_table[fd]->w_queue)) == NULL) { + else if ((_thread_fd_table[fd]->w_owner = TAILQ_FIRST(&_thread_fd_table[fd]->w_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->w_queue, + _thread_fd_table[fd]->w_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -255,6 +269,12 @@ _thread_fd_unlock(int fd, int lock_type) /* Unlock the file descriptor table entry: */ _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); } /* Nothing to return. */ @@ -296,7 +316,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout) * queue of threads waiting for a * read lock on this file descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->r_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->r_queue, _thread_run, qe); /* * Save the file descriptor details @@ -369,7 +389,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout) * write lock on this file * descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->w_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->w_queue, _thread_run, qe); /* * Save the file descriptor details @@ -431,7 +451,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout) } void -_thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) +_thread_fd_unlock_debug(int fd, int lock_type, const char *fname, int lineno) { int ret; @@ -441,6 +461,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) */ if ((ret = _thread_fd_table_init(fd)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* * Lock the file descriptor table entry to prevent * other threads for clashing with the current * thread's accesses: @@ -467,8 +493,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) * Get the next thread in the queue for a * read lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->r_owner = _thread_queue_deq(&_thread_fd_table[fd]->r_queue)) == NULL) { + else if ((_thread_fd_table[fd]->r_owner = TAILQ_FIRST(&_thread_fd_table[fd]->r_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->r_queue, + _thread_fd_table[fd]->r_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -505,8 +535,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) * Get the next thread in the queue for a * write lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->w_owner = _thread_queue_deq(&_thread_fd_table[fd]->w_queue)) == NULL) { + else if ((_thread_fd_table[fd]->w_owner = TAILQ_FIRST(&_thread_fd_table[fd]->w_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->w_queue, + _thread_fd_table[fd]->w_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -526,6 +560,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) /* Unlock the file descriptor table entry: */ _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary. + */ + _thread_kern_sig_undefer(); } /* Nothing to return. */ @@ -568,7 +608,7 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, * queue of threads waiting for a * read lock on this file descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->r_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->r_queue, _thread_run, qe); /* * Save the file descriptor details @@ -650,7 +690,7 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, * write lock on this file * descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->w_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->w_queue, _thread_run, qe); /* * Save the file descriptor details diff --git a/lib/libc_r/uthread/uthread_file.c b/lib/libc_r/uthread/uthread_file.c index a4b5f922fd7..e1c234fc3d4 100644 --- a/lib/libc_r/uthread/uthread_file.c +++ b/lib/libc_r/uthread/uthread_file.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_file.c,v 1.4 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_file.c,v 1.6 1998/09/09 16:50:33 dt Exp $ - * $OpenBSD: uthread_file.c,v 1.3 1998/12/23 22:44:39 d Exp $ + * $FreeBSD: uthread_file.c,v 1.9 1999/08/28 00:03:32 peter Exp $ * * POSIX stdio FILE locking functions. These assume that the locking * is only required at FILE structure level, not at file descriptor @@ -46,6 +46,13 @@ #include "pthread_private.h" /* + * Weak symbols for externally visible functions in this file: + */ +#pragma weak flockfile=_flockfile +#pragma weak ftrylockfile=_ftrylockfile +#pragma weak funlockfile=_funlockfile + +/* * The FILE lock structure. The FILE *fp is locked if the owner is * not NULL. If not locked, the file lock structure can be * reassigned to a different file by setting fp. @@ -237,14 +244,14 @@ _flockfile_debug(FILE * fp, const char *fname, int lineno) } void -flockfile(FILE * fp) +_flockfile(FILE * fp) { _flockfile_debug(fp, "?", 1); return; } int -ftrylockfile(FILE * fp) +_ftrylockfile(FILE * fp) { int ret = -1; int idx = file_idx(fp); @@ -255,15 +262,6 @@ ftrylockfile(FILE * fp) /* Lock the hash table: */ _SPINLOCK(&hash_lock); - /* Check if the static array has not been initialised: */ - if (!init_done) { - /* Initialise the global array: */ - memset(flh,0,sizeof(flh)); - - /* Flag the initialisation as complete: */ - init_done = 1; - } - /* Get a pointer to any existing lock for the file: */ if ((p = find_lock(idx, fp)) == NULL) { /* @@ -305,13 +303,20 @@ ftrylockfile(FILE * fp) } void -funlockfile(FILE * fp) +_funlockfile(FILE * fp) { + int status; int idx = file_idx(fp); struct file_lock *p; /* Check if this is a real file: */ if (fp->_file >= 0) { + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + /* Lock the hash table: */ _SPINLOCK(&hash_lock); @@ -319,7 +324,7 @@ funlockfile(FILE * fp) * Get a pointer to the lock for the file and check that * the running thread is the one with the lock: */ - if (init_done && (p = find_lock(idx, fp)) != NULL && + if ((p = find_lock(idx, fp)) != NULL && p->owner == _thread_run) { /* * Check if this thread has locked the FILE @@ -358,6 +363,12 @@ funlockfile(FILE * fp) /* Unlock the hash table: */ _SPINUNLOCK(&hash_lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); } return; } diff --git a/lib/libc_r/uthread/uthread_find_thread.c b/lib/libc_r/uthread/uthread_find_thread.c index 21a37e679c7..42b561524b9 100644 --- a/lib/libc_r/uthread/uthread_find_thread.c +++ b/lib/libc_r/uthread/uthread_find_thread.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_find_thread.c,v 1.4 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_find_thread.c,v 1.3 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_find_thread.c,v 1.5 1999/08/28 00:03:32 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -47,20 +48,20 @@ _find_thread(pthread_t pthread) /* Invalid thread: */ return(EINVAL); - /* Lock the thread list: */ - _lock_thread_list(); - - /* Point to the first thread in the list: */ - pthread1 = _thread_link_list; + /* + * Defer signals to protect the thread list from access + * by the signal handler: + */ + _thread_kern_sig_defer(); - /* Search for the thread to join to: */ - while (pthread1 != NULL && pthread1 != pthread) { - /* Point to the next thread: */ - pthread1 = pthread1->nxt; + /* Search for the specified thread: */ + TAILQ_FOREACH(pthread1, &_thread_list, tle) { + if (pthread == pthread1) + break; } - /* Unlock the thread list: */ - _unlock_thread_list(); + /* Undefer and handle pending signals, yielding if necessary: */ + _thread_kern_sig_undefer(); /* Return zero if the thread exists: */ return ((pthread1 != NULL) ? 0:ESRCH); @@ -84,13 +85,10 @@ _find_dead_thread(pthread_t pthread) if (pthread_mutex_lock(&_gc_mutex) != 0) PANIC("Cannot lock gc mutex"); - /* Point to the first thread in the list: */ - pthread1 = _thread_dead; - - /* Search for the thread to join to: */ - while (pthread1 != NULL && pthread1 != pthread) { - /* Point to the next thread: */ - pthread1 = pthread1->nxt_dead; + /* Search for the specified thread: */ + TAILQ_FOREACH(pthread1, &_dead_list, dle) { + if (pthread1 == pthread) + break; } /* Unlock the garbage collector mutex: */ diff --git a/lib/libc_r/uthread/uthread_flock.c b/lib/libc_r/uthread/uthread_flock.c index e228762f43c..fed679bd80b 100644 --- a/lib/libc_r/uthread/uthread_flock.c +++ b/lib/libc_r/uthread/uthread_flock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_flock.c,v 1.3 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_flock.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_flock.c,v 1.5 1999/08/28 00:03:32 peter Exp $ */ #include <sys/file.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_fork.c b/lib/libc_r/uthread/uthread_fork.c index ed1566915bd..0e9aef59a20 100644 --- a/lib/libc_r/uthread/uthread_fork.c +++ b/lib/libc_r/uthread/uthread_fork.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fork.c,v 1.7 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,13 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fork.c,v 1.6 1999/06/15 00:07:39 d Exp $ + * $FreeBSD: uthread_fork.c,v 1.14 1999/09/29 15:18:38 marcel Exp $ */ #include <errno.h> #include <string.h> #include <unistd.h> #include <fcntl.h> -#include <stdlib.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -46,10 +46,13 @@ fork(void) int i, flags; pid_t ret; pthread_t pthread; - pthread_t pthread_next; + pthread_t pthread_save; - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); /* Fork a new process: */ if ((ret = _thread_sys_fork()) != 0) { @@ -60,7 +63,7 @@ fork(void) _thread_sys_close(_thread_kern_pipe[1]); /* Reset signals pending for the running thread: */ - _thread_run->sigpend = 0; + sigemptyset(&_thread_run->sigpend); /* * Create a pipe that is written to by the signal handler to @@ -90,45 +93,74 @@ fork(void) else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { /* Abort this application: */ abort(); + } + /* Reinitialize the GC mutex: */ + else if (_mutex_reinit(&_gc_mutex) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC mutex for forked process"); + } + /* Reinitialize the GC condition variable: */ + else if (_cond_reinit(&_gc_cond) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC condvar for forked process"); + } /* Initialize the ready queue: */ - } else if (_pq_init(&_readyq, PTHREAD_MIN_PRIORITY, - PTHREAD_MAX_PRIORITY) != 0) { + else if (_pq_init(&_readyq) != 0) { /* Abort this application: */ - PANIC("Cannot allocate priority ready queue."); + PANIC("Cannot initialize priority ready queue."); } else { - /* Point to the first thread in the list: */ - pthread = _thread_link_list; - /* * Enter a loop to remove all threads other than * the running thread from the thread list: */ + pthread = TAILQ_FIRST(&_thread_list); while (pthread != NULL) { - pthread_next = pthread->nxt; - if (pthread == _thread_run) { - _thread_link_list = pthread; - pthread->nxt = NULL; - } else { - if (pthread->attr.stackaddr_attr == - NULL && pthread->stack != NULL) - /* - * Free the stack of the - * dead thread: - */ - free(pthread->stack); - - if (pthread->specific_data != NULL) - free(pthread->specific_data); - - free(pthread); - } + /* Save the thread to be freed: */ + pthread_save = pthread; + + /* + * Advance to the next thread before + * destroying the current thread: + */ + pthread = TAILQ_NEXT(pthread, dle); + + /* Make sure this isn't the running thread: */ + if (pthread_save != _thread_run) { + /* Remove this thread from the list: */ + TAILQ_REMOVE(&_thread_list, + pthread_save, tle); - /* Point to the next thread: */ - pthread = pthread_next; + if(pthread_save->stack != NULL) + _thread_stack_free(pthread_save->stack); + + if (pthread_save->specific_data != NULL) + free(pthread_save->specific_data); + + if (pthread_save->poll_data.fds != NULL) + free(pthread_save->poll_data.fds); + + free(pthread_save); + } } - /* Re-init the waiting queues. */ + /* Re-init the dead thread list: */ + TAILQ_INIT(&_dead_list); + + /* Re-init the waiting and work queues. */ TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); + + /* Re-init the threads mutex queue: */ + TAILQ_INIT(&_thread_run->mutexq); + + /* No spinlocks yet: */ + _spinblock_count = 0; + + /* Don't queue signals yet: */ + _queue_signals = 0; + + /* Initialize signal handling: */ + _thread_sig_init(); /* Initialize the scheduling switch hook routine: */ _sched_switch_hook = NULL; @@ -137,7 +169,7 @@ fork(void) for (i = 0; i < _thread_dtablesize; i++) { if (_thread_fd_table[i] != NULL) { /* Initialise the file locks: */ - _SPINUNLOCK(&_thread_fd_table[i]->lock); + _SPINLOCK_INIT(&_thread_fd_table[i]->lock); _thread_fd_table[i]->r_owner = NULL; _thread_fd_table[i]->w_owner = NULL; _thread_fd_table[i]->r_fname = NULL; @@ -148,15 +180,17 @@ fork(void) _thread_fd_table[i]->w_lockcount = 0;; /* Initialise the read/write queues: */ - _thread_queue_init(&_thread_fd_table[i]->r_queue); - _thread_queue_init(&_thread_fd_table[i]->w_queue); + TAILQ_INIT(&_thread_fd_table[i]->r_queue); + TAILQ_INIT(&_thread_fd_table[i]->w_queue); } } } } - /* Unock the thread list: */ - _unlock_thread_list(); + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); /* Return the process ID: */ return (ret); diff --git a/lib/libc_r/uthread/uthread_fstat.c b/lib/libc_r/uthread/uthread_fstat.c index c1e195f0c69..29b65b5aac6 100644 --- a/lib/libc_r/uthread/uthread_fstat.c +++ b/lib/libc_r/uthread/uthread_fstat.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fstat.c,v 1.3 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fstat.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_fstat.c,v 1.5 1999/08/28 00:03:33 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_fstatfs.c b/lib/libc_r/uthread/uthread_fstatfs.c index cbd590f008a..ba809a5bef4 100644 --- a/lib/libc_r/uthread/uthread_fstatfs.c +++ b/lib/libc_r/uthread/uthread_fstatfs.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fstatfs.c,v 1.3 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fstatfs.c,v 1.2 1999/01/10 23:10:25 d Exp $ + * $FreeBSD: uthread_fstatfs.c,v 1.5 1999/08/28 00:03:33 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_fsync.c b/lib/libc_r/uthread/uthread_fsync.c index 2136d62afe7..cc5cb5046e1 100644 --- a/lib/libc_r/uthread/uthread_fsync.c +++ b/lib/libc_r/uthread/uthread_fsync.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fsync.c,v 1.5 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fsync.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_fsync.c,v 1.5 1999/08/28 00:03:33 peter Exp $ */ #include <unistd.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_gc.c b/lib/libc_r/uthread/uthread_gc.c index 1a2790c74bd..d97b602687c 100644 --- a/lib/libc_r/uthread/uthread_gc.c +++ b/lib/libc_r/uthread/uthread_gc.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_gc.c,v 1.6 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_gc.c,v 1.2 1998/09/30 19:17:51 dt Exp $ - * $OpenBSD: uthread_gc.c,v 1.5 1999/05/26 00:18:24 d Exp $ + * $FreeBSD: uthread_gc.c,v 1.10 1999/08/28 00:03:34 peter Exp $ * * Garbage collector thread. Frees memory allocated for dead threads. * @@ -38,12 +38,10 @@ #include <errno.h> #include <time.h> #include <unistd.h> -#include <stdlib.h> #include <sys/types.h> -#include <sys/time.h> -#ifdef _THREAD_SAFE +#include <sys/types.h> +#include <sys/mman.h> #include <pthread.h> -#include <pthread_np.h> #include "pthread_private.h" pthread_addr_t @@ -71,7 +69,7 @@ _thread_gc(pthread_addr_t arg) f_debug = (getenv("LIBC_R_DEBUG") != NULL); /* Set the name of this thread. */ - pthread_set_name_np(_thread_run, "GC"); + pthread_set_name_np(_thread_run,"GC"); while (!f_done) { /* Check if debugging this application. */ @@ -79,20 +77,26 @@ _thread_gc(pthread_addr_t arg) /* Dump thread info to file. */ _thread_dump_info(); - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); /* Check if this is the last running thread: */ - if (_thread_link_list == _thread_run && - _thread_link_list->nxt == NULL) + if (TAILQ_FIRST(&_thread_list) == _thread_run && + TAILQ_NEXT(_thread_run, tle) == NULL) /* * This is the last thread, so it can exit * now. */ f_done = 1; - /* Unlock the thread list: */ - _unlock_thread_list(); + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); /* * Lock the garbage collector mutex which ensures that @@ -105,98 +109,50 @@ _thread_gc(pthread_addr_t arg) p_stack = NULL; pthread_cln = NULL; - /* Point to the first dead thread (if there are any): */ - pthread = _thread_dead; - - /* There is no previous dead thread: */ - pthread_prv = NULL; - /* * Enter a loop to search for the first dead thread that * has memory to free. */ - while (p_stack == NULL && pthread_cln == NULL && - pthread != NULL) { - /* Save a pointer to the next thread: */ - pthread_nxt = pthread->nxt_dead; - + for (pthread = TAILQ_FIRST(&_dead_list); + p_stack == NULL && pthread_cln == NULL && pthread != NULL; + pthread = TAILQ_NEXT(pthread, dle)) { /* Check if the initial thread: */ - if (pthread == _thread_initial) + if (pthread == _thread_initial) { /* Don't destroy the initial thread. */ - pthread_prv = pthread; - + } /* * Check if this thread has detached: */ else if ((pthread->attr.flags & - PTHREAD_DETACHED) != 0) { - /* - * Check if there is no previous dead - * thread: - */ - if (pthread_prv == NULL) - /* - * The dead thread is at the head - * of the list: - */ - _thread_dead = pthread_nxt; - else - /* - * The dead thread is not at the - * head of the list: - */ - pthread_prv->nxt_dead = - pthread->nxt_dead; + PTHREAD_DETACHED) != 0) { + /* Remove this thread from the dead list: */ + TAILQ_REMOVE(&_dead_list, pthread, dle); /* - * Check if the stack was not specified by - * the caller to pthread_create and has not - * been destroyed yet: + * Point to the stack structure that must + * be freed outside the locks: */ - if (pthread->attr.stackaddr_attr == NULL && - pthread->stack != NULL) { - /* - * Point to the stack that must - * be freed outside the locks: - */ + if (pthread->stack != NULL) p_stack = pthread->stack; - } /* * Point to the thread structure that must * be freed outside the locks: */ pthread_cln = pthread; + } else { /* * This thread has not detached, so do - * not destroy it: + * not destroy it. + * + * But we can destroy its stack. */ - pthread_prv = pthread; - - /* - * 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) { - /* - * Point to the stack that must - * be freed outside the locks: - */ + if (pthread->stack != NULL) { p_stack = pthread->stack; - - /* - * NULL the stack pointer now - * that the memory has been freed: - */ pthread->stack = NULL; } } - - /* Point to the next thread: */ - pthread = pthread_nxt; } /* @@ -233,58 +189,18 @@ _thread_gc(pthread_addr_t arg) * locks. */ if (p_stack != NULL) - free(p_stack); - if (pthread_cln != NULL) { - /* Lock the thread list: */ - _lock_thread_list(); - - /* - * Check if the thread is at the head of the - * linked list. - */ - if (_thread_link_list == pthread_cln) - /* There is no previous thread: */ - _thread_link_list = pthread_cln->nxt; - else { - /* Point to the first thread in the list: */ - pthread = _thread_link_list; - - /* - * Enter a loop to find the thread in the - * linked list before the thread that is - * about to be freed. - */ - while (pthread != NULL && - pthread->nxt != pthread_cln) - /* Point to the next thread: */ - pthread = pthread->nxt; - - /* Check that a previous thread was found: */ - if (pthread != NULL) { - /* - * Point the previous thread to - * the one after the thread being - * freed: - */ - pthread->nxt = pthread_cln->nxt; - } - } - - /* Unlock the thread list: */ - _unlock_thread_list(); - - /* Free memory allocated for the thread's name: */ - if (pthread_cln->name != NULL) - free(pthread_cln->name); + /* Free the stack storage. */ + _thread_stack_free(p_stack); + if (pthread_cln != NULL) { /* * Free the memory allocated for the thread * structure. */ + if (pthread_cln->name != NULL) + free(pthread_cln->name); free(pthread_cln); } - } return (NULL); } -#endif /* _THREAD_SAFE */ diff --git a/lib/libc_r/uthread/uthread_getdirentries.c b/lib/libc_r/uthread/uthread_getdirentries.c index 60cd50ec6e2..1dd8d30e651 100644 --- a/lib/libc_r/uthread/uthread_getdirentries.c +++ b/lib/libc_r/uthread/uthread_getdirentries.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getdirentries.c,v 1.3 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getdirentries.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_getdirentries.c,v 1.5 1999/08/28 00:03:34 peter Exp $ */ #include <sys/types.h> #include <dirent.h> diff --git a/lib/libc_r/uthread/uthread_getpeername.c b/lib/libc_r/uthread/uthread_getpeername.c index adb3ab3587b..378f23f7416 100644 --- a/lib/libc_r/uthread/uthread_getpeername.c +++ b/lib/libc_r/uthread/uthread_getpeername.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getpeername.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getpeername.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_getpeername.c,v 1.5 1999/08/28 00:03:34 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> @@ -38,7 +39,7 @@ #include "pthread_private.h" int -getpeername(int fd, struct sockaddr *peer, socklen_t *paddrlen) +getpeername(int fd, struct sockaddr * peer, socklen_t *paddrlen) { int ret; diff --git a/lib/libc_r/uthread/uthread_getprio.c b/lib/libc_r/uthread/uthread_getprio.c index 074bff3e514..725fb0bde54 100644 --- a/lib/libc_r/uthread/uthread_getprio.c +++ b/lib/libc_r/uthread/uthread_getprio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_getprio.c,v 1.3 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_getprio.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_getprio.c,v 1.6 1999/08/28 00:03:35 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_getschedparam.c b/lib/libc_r/uthread/uthread_getschedparam.c index 7905c1960f4..3bfadd1709f 100644 --- a/lib/libc_r/uthread/uthread_getschedparam.c +++ b/lib/libc_r/uthread/uthread_getschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_getschedparam.c,v 1.1 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_getschedparam.c,v 1.2 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_getschedparam.c,v 1.3 1999/08/28 00:03:35 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_getsockname.c b/lib/libc_r/uthread/uthread_getsockname.c index 4ed580dc2cf..683cc910f15 100644 --- a/lib/libc_r/uthread/uthread_getsockname.c +++ b/lib/libc_r/uthread/uthread_getsockname.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getsockname.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getsockname.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_getsockname.c,v 1.5 1999/08/28 00:03:36 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libc_r/uthread/uthread_getsockopt.c b/lib/libc_r/uthread/uthread_getsockopt.c index 7205ac345a3..f73b54780ea 100644 --- a/lib/libc_r/uthread/uthread_getsockopt.c +++ b/lib/libc_r/uthread/uthread_getsockopt.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getsockopt.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getsockopt.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_getsockopt.c,v 1.5 1999/08/28 00:03:36 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c index 281808e75f4..cbcb33083ac 100644 --- a/lib/libc_r/uthread/uthread_init.c +++ b/lib/libc_r/uthread/uthread_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_init.c,v 1.9 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_init.c,v 1.10 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_init.c,v 1.18 1999/08/28 00:03:36 peter Exp $ */ #include <errno.h> @@ -37,80 +38,68 @@ #include <string.h> #include <fcntl.h> #include <paths.h> +#include <poll.h> #include <unistd.h> +#include <sys/param.h> +#include <sys/sysctl.h> #include <sys/time.h> #include <sys/ttycom.h> #include <sys/param.h> -#include <sys/ioctl.h> -#include <signal.h> +#include <sys/user.h> +#include <sys/mman.h> #ifdef _THREAD_SAFE #include <machine/reg.h> #include <pthread.h> -#include <pthread_np.h> #include "pthread_private.h" -/* Allocate space for global thread variables here: */ - -static struct pthread kern_thread; -struct pthread * volatile _thread_kern_threadp = &kern_thread; -struct pthread * volatile _thread_run = &kern_thread; -struct pthread * volatile _last_user_thread = &kern_thread; -struct pthread * volatile _thread_single = NULL; -struct pthread * volatile _thread_link_list = NULL; -int _thread_kern_pipe[2] = { -1, -1 }; -int _thread_kern_in_select = 0; -int _thread_kern_in_sched = 0; -struct timeval kern_inc_prio_time = { 0, 0 }; -struct pthread * volatile _thread_dead = NULL; -struct pthread * _thread_initial = NULL; -struct pthread_attr pthread_attr_default = { - SCHED_RR, /* sched_policy */ - 0, /* sched_inherit */ - TIMESLICE_USEC, /* sched_interval */ - PTHREAD_DEFAULT_PRIORITY, /* prio */ - PTHREAD_CREATE_RUNNING, /* suspend */ - PTHREAD_CREATE_JOINABLE, /* flags */ - NULL, /* arg_attr */ - NULL, /* cleanup_attr */ - NULL, /* stackaddr_attr */ - PTHREAD_STACK_DEFAULT /* stacksize_attr */ -}; -struct pthread_mutex_attr pthread_mutexattr_default = { - PTHREAD_MUTEX_DEFAULT, /* m_type */ - PTHREAD_PRIO_NONE, /* m_protocol */ - 0, /* m_ceiling */ - 0 /* m_flags */ -}; -struct pthread_cond_attr pthread_condattr_default = { - COND_TYPE_FAST, /* c_type */ - 0 /* c_flags */ -}; -int _pthread_stdio_flags[3]; -struct fd_table_entry ** _thread_fd_table = NULL; -int _thread_dtablesize = NOFILE_MAX; -pthread_mutex_t _gc_mutex = NULL; -pthread_cond_t _gc_cond = NULL; -struct sigaction _thread_sigact[NSIG]; - -const int dtablecount = 4096/sizeof(struct fd_table_entry); -pq_queue_t _readyq; -_waitingq_t _waitingq; -volatile int _waitingq_check_reqd = 0; -pthread_switch_routine_t _sched_switch_hook = NULL; - -/* Automatic init module. */ +/* Global thread variables. */ +struct pthread _thread_kern_thread; +struct pthread *volatile _thread_run = &_thread_kern_thread; +struct pthread *volatile _last_user_thread = &_thread_kern_thread; +struct pthread *volatile _thread_single = NULL; +_thread_list_t _thread_list = TAILQ_HEAD_INITIALIZER(_thread_list); +int _thread_kern_pipe[2] = { -1, -1 }; +int volatile _queue_signals = 0; +int _thread_kern_in_sched = 0; +struct timeval kern_inc_prio_time = { 0, 0 }; +_thread_list_t _dead_list = TAILQ_HEAD_INITIALIZER(_dead_list); +struct pthread *_thread_initial = NULL; +struct pthread_attr pthread_attr_default = { + SCHED_RR, 0, TIMESLICE_USEC, PTHREAD_DEFAULT_PRIORITY, + PTHREAD_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, + NULL, NULL, NULL, PTHREAD_STACK_DEFAULT }; +struct pthread_mutex_attr pthread_mutexattr_default = { + PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, 0 }; +struct pthread_cond_attr pthread_condattr_default = { COND_TYPE_FAST, 0 }; +int _pthread_stdio_flags[3]; +struct fd_table_entry **_thread_fd_table = NULL; +struct pollfd *_thread_pfd_table = NULL; +const int dtablecount = 4096/sizeof(struct fd_table_entry); +int _thread_dtablesize = 0; +int _clock_res_nsec = CLOCK_RES_NSEC; +pthread_mutex_t _gc_mutex = NULL; +pthread_cond_t _gc_cond = NULL; +struct sigaction _thread_sigact[NSIG]; +pq_queue_t _readyq; +_thread_list_t _waitingq; +_thread_list_t _workq; +volatile int _spinblock_count = 0; +volatile int _sigq_check_reqd = 0; +pthread_switch_routine_t _sched_switch_hook = NULL; +_stack_list_t _stackq; +int _thread_kern_new_state = 0; + extern int _thread_autoinit_dummy_decl; #ifdef GCC_2_8_MADE_THREAD_AWARE -/* see src/gnu/usr.bin/gcc/libgcc2.c */ typedef void *** (*dynamic_handler_allocator)(); extern void __set_dynamic_handler_allocator(dynamic_handler_allocator); static pthread_key_t except_head_key; typedef struct { - void **__dynamic_handler_chain; - void *top_elt[2]; + void **__dynamic_handler_chain; + void *top_elt[2]; } except_struct; static void ***dynamic_allocator_handler_fn() @@ -136,6 +125,9 @@ _thread_init(void) int fd; int flags; int i; + size_t len; + int mib[2]; + struct clockinfo clockinfo; struct sigaction act; /* Check if this function has already been called: */ @@ -152,26 +144,27 @@ _thread_init(void) * Setup a new session for this process which is * assumed to be running as root. */ - if (setsid() == -1) + if (setsid() == -1) PANIC("Can't set session ID"); - if (revoke(_PATH_CONSOLE) != 0) + if (revoke(_PATH_CONSOLE) != 0) PANIC("Can't revoke console"); - if ((fd = _thread_sys_open(_PATH_CONSOLE, O_RDWR)) < 0) + if ((fd = _thread_sys_open(_PATH_CONSOLE, O_RDWR)) < 0) PANIC("Can't open console"); - if (setlogin("root") == -1) + if (setlogin("root") == -1) PANIC("Can't set login to root"); - if (_thread_sys_ioctl(fd,TIOCSCTTY, (char *) NULL) == -1) + if (_thread_sys_ioctl(fd,TIOCSCTTY, (char *) NULL) == -1) PANIC("Can't set controlling terminal"); - if (_thread_sys_dup2(fd,0) == -1 || - _thread_sys_dup2(fd,1) == -1 || - _thread_sys_dup2(fd,2) == -1) + if (_thread_sys_dup2(fd,0) == -1 || + _thread_sys_dup2(fd,1) == -1 || + _thread_sys_dup2(fd,2) == -1) PANIC("Can't dup2"); } /* Get the standard I/O flags before messing with them : */ for (i = 0; i < 3; i++) - if ((_pthread_stdio_flags[i] = - _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) + if (((_pthread_stdio_flags[i] = + _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) && + (errno != EBADF)) PANIC("Cannot get stdio flags"); /* @@ -202,9 +195,8 @@ _thread_init(void) /* Abort this application: */ PANIC("Cannot get kernel write pipe flags"); } - /* Initialize the ready queue: */ - else if (_pq_init(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_MAX_PRIORITY) -!= 0) { + /* Allocate and initialize the ready queue: */ + else if (_pq_alloc(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_MAX_PRIORITY) != 0) { /* Abort this application: */ PANIC("Cannot allocate priority ready queue."); } @@ -217,23 +209,19 @@ _thread_init(void) PANIC("Cannot allocate memory for initial thread"); } else { /* Zero the global kernel thread structure: */ - memset(_thread_kern_threadp, 0, sizeof(struct pthread)); - _thread_kern_threadp->magic = PTHREAD_MAGIC; - - /* Set the kernel's name for the debugger: */ - pthread_set_name_np(_thread_kern_threadp, "kern"); - - /* The kernel thread is a library thread: */ - _thread_kern_threadp->flags = PTHREAD_FLAGS_PRIVATE; + memset(&_thread_kern_thread, 0, sizeof(struct pthread)); + _thread_kern_thread.flags = PTHREAD_FLAGS_PRIVATE; + memset(_thread_initial, 0, sizeof(struct pthread)); - /* Initialize the waiting queue: */ + /* Initialize the waiting and work queues: */ TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); /* Initialize the scheduling switch hook routine: */ _sched_switch_hook = NULL; - /* Zero the initial thread: */ - memset(_thread_initial, 0, sizeof(struct pthread)); + /* Initialize the thread stack cache: */ + SLIST_INIT(&_stackq); /* * Write a magic value to the thread structure @@ -250,27 +238,29 @@ _thread_init(void) _thread_initial->state = PS_RUNNING; /* Initialise the queue: */ - _thread_queue_init(&(_thread_initial->join_queue)); + TAILQ_INIT(&(_thread_initial->join_queue)); /* Initialize the owned mutex queue and count: */ TAILQ_INIT(&(_thread_initial->mutexq)); _thread_initial->priority_mutex_count = 0; + /* Give it a useful name */ + pthread_set_name_np(_thread_initial, "main"); + /* Initialise the rest of the fields: */ - _thread_initial->sched_defer_count = 0; - _thread_initial->yield_on_sched_undefer = 0; + _thread_initial->poll_data.nfds = 0; + _thread_initial->poll_data.fds = NULL; + _thread_initial->sig_defer_count = 0; + _thread_initial->yield_on_sig_undefer = 0; _thread_initial->specific_data = NULL; _thread_initial->cleanup = NULL; - _thread_initial->queue = NULL; - _thread_initial->qnxt = NULL; - _thread_initial->nxt = NULL; _thread_initial->flags = 0; _thread_initial->error = 0; _thread_initial->cancelstate = PTHREAD_CANCEL_ENABLE; _thread_initial->canceltype = PTHREAD_CANCEL_DEFERRED; - pthread_set_name_np(_thread_initial, "init"); - _SPINUNLOCK(&_thread_initial->lock); - _thread_link_list = _thread_initial; + _SPINLOCK_INIT(&_thread_initial->lock); + TAILQ_INIT(&_thread_list); + TAILQ_INSERT_HEAD(&_thread_list, _thread_initial, tle); _thread_run = _thread_initial; /* Initialise the global signal action structure: */ @@ -278,6 +268,9 @@ _thread_init(void) act.sa_handler = (void (*) ()) _thread_sig_handler; act.sa_flags = 0; + /* Initialize signal handling: */ + _thread_sig_init(); + /* Enter a loop to get the existing signal status: */ for (i = 1; i < NSIG; i++) { /* Check for signals which cannot be trapped: */ @@ -286,7 +279,7 @@ _thread_init(void) /* Get the signal handler details: */ else if (_thread_sys_sigaction(i, NULL, - &_thread_sigact[i - 1]) != 0) { + &_thread_sigact[i - 1]) != 0) { /* * Abort this process if signal * initialisation fails: @@ -309,6 +302,13 @@ _thread_init(void) PANIC("Cannot initialise signal handler"); } + /* Get the kernel clockrate: */ + mib[0] = CTL_KERN; + mib[1] = KERN_CLOCKRATE; + len = sizeof (struct clockinfo); + if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0) + _clock_res_nsec = clockinfo.tick * 1000; + /* Get the table size: */ if ((_thread_dtablesize = getdtablesize()) < 0) { /* @@ -319,11 +319,22 @@ _thread_init(void) } /* Allocate memory for the file descriptor table: */ if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry *) * _thread_dtablesize)) == NULL) { + /* Avoid accesses to file descriptor table on exit: */ + _thread_dtablesize = 0; + /* * Cannot allocate memory for the file descriptor * table, so abort this process. */ PANIC("Cannot allocate memory for file descriptor table"); + } + /* Allocate memory for the pollfd table: */ + if ((_thread_pfd_table = (struct pollfd *) malloc(sizeof(struct pollfd) * _thread_dtablesize)) == NULL) { + /* + * Cannot allocate memory for the file descriptor + * table, so abort this process. + */ + PANIC("Cannot allocate memory for pollfd table"); } else { /* * Enter a loop to initialise the file descriptor @@ -333,13 +344,21 @@ _thread_init(void) /* Initialise the file descriptor table: */ _thread_fd_table[i] = NULL; } + + /* Initialize stdio file descriptor table entries: */ + for (i = 0; i < 3; i++) { + if ((_thread_fd_table_init(i) != 0) && + (errno != EBADF)) + PANIC("Cannot initialize stdio file " + "descriptor table entry"); + } } } #ifdef GCC_2_8_MADE_THREAD_AWARE /* Create the thread-specific data for the exception linked list. */ if(pthread_key_create(&except_head_key, NULL) != 0) - PANIC("Failed to create thread specific execption head"); + PANIC("Failed to create thread specific execption head"); /* Setup the gcc exception handler per thread. */ __set_dynamic_handler_allocator( dynamic_allocator_handler_fn ); @@ -352,10 +371,8 @@ _thread_init(void) gettimeofday(&kern_inc_prio_time, NULL); - /* Pull in automatic thread unit. */ - _thread_autoinit_dummy_decl = 1; + _thread_autoinit_dummy_decl = 0; return; } - -#endif _THREAD_SAFE +#endif diff --git a/lib/libc_r/uthread/uthread_ioctl.c b/lib/libc_r/uthread/uthread_ioctl.c index e26b7174797..d7daa17196b 100644 --- a/lib/libc_r/uthread/uthread_ioctl.c +++ b/lib/libc_r/uthread/uthread_ioctl.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_ioctl.c,v 1.3 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_ioctl.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_ioctl.c,v 1.6 1999/08/28 00:03:37 peter Exp $ */ #include <stdarg.h> #include <sys/ioctl.h> diff --git a/lib/libc_r/uthread/uthread_join.c b/lib/libc_r/uthread/uthread_join.c index 42ef1f778bc..374a5d45b90 100644 --- a/lib/libc_r/uthread/uthread_join.c +++ b/lib/libc_r/uthread/uthread_join.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_join.c,v 1.6 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_join.c,v 1.5 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_join.c,v 1.9 1999/08/28 00:03:37 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -40,34 +41,26 @@ int pthread_join(pthread_t pthread, void **thread_return) { int ret = 0; - pthread_t pthread1 = NULL; - /* This operation is a cancel point: */ + /* This is a cancellation point: */ _thread_enter_cancellation_point(); /* Check if the caller has specified an invalid thread: */ - if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) { + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) /* Invalid thread: */ - _thread_leave_cancellation_point(); - return(EINVAL); - } + ret = EINVAL; /* Check if the caller has specified itself: */ - if (pthread == _thread_run) { + else if (pthread == _thread_run) /* Avoid a deadlock condition: */ - _thread_leave_cancellation_point(); - return(EDEADLK); - } + ret = EDEADLK; /* * Find the thread in the list of active threads or in the * list of dead threads: */ - if (_find_thread(pthread) == 0 || - _find_dead_thread(pthread) == 0) - pthread1 = pthread; - - if (pthread1 == NULL) + else if (_find_thread(pthread) != 0 && + _find_dead_thread(pthread) != 0) /* Return an error: */ ret = ESRCH; @@ -79,7 +72,7 @@ pthread_join(pthread_t pthread, void **thread_return) /* Check if the thread is not dead: */ else if (pthread->state != PS_DEAD) { /* Add the running thread to the join queue: */ - _thread_queue_enq(&(pthread->join_queue), _thread_run); + TAILQ_INSERT_TAIL(&(pthread->join_queue), _thread_run, qe); /* Schedule the next thread: */ _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c index 78223f4ad10..56d6c7a3999 100644 --- a/lib/libc_r/uthread/uthread_kern.c +++ b/lib/libc_r/uthread/uthread_kern.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_kern.c,v 1.8 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_kern.c,v 1.9 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -30,22 +30,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_kern.c,v 1.18 1999/05/08 07:50:05 jasone Exp $ + * $FreeBSD: uthread_kern.c,v 1.23 1999/09/29 15:18:39 marcel Exp $ * */ #include <errno.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> +#include <poll.h> #include <unistd.h> #include <setjmp.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/socket.h> -#ifdef _THREAD_RUSAGE -#include <sys/resource.h> -#endif #include <sys/uio.h> #include <sys/syscall.h> #include <fcntl.h> @@ -55,26 +53,34 @@ /* Static function prototype definitions: */ static void -_thread_kern_select(int wait_reqd); +_thread_kern_poll(int wait_reqd); + +static void +dequeue_signals(void); static inline void thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in); +static void +_thread_check_cancel() +{ + if (!(_thread_run->flags & PTHREAD_FLAGS_CANCELPT) && + (_thread_run->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)) + /* + * Check if an async-cancellable thread + * has been cancelled. + */ + _thread_cancellation_point(); +} + void _thread_kern_sched(struct sigcontext * scp) { - pthread_t pthread; - pthread_t pthread_h = NULL; - pthread_t last_thread = NULL; + pthread_t pthread, pthread_h = NULL; struct itimerval itimer; - struct timespec ts; - struct timespec ts1; - struct timeval tv; - struct timeval tv1; -#ifdef _THREAD_RUSAGE - struct rusage ru; - static struct rusage ru_prev; -#endif + struct timespec ts, ts1; + struct timeval tv, tv1; + int set_timer = 0; /* * Flag the pthread kernel as executing scheduler code @@ -91,7 +97,9 @@ _thread_kern_sched(struct sigcontext * scp) */ memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext)); - /* Save the floating point data: */ + /* + * Save floating point state. + */ _thread_machdep_save_float_state(_thread_run); /* Flag the signal context as the last state saved: */ @@ -112,25 +120,7 @@ _thread_kern_sched(struct sigcontext * scp) thread_run_switch_hook(_last_user_thread, _thread_run); } - if (!(_thread_run->flags & PTHREAD_AT_CANCEL_POINT) && - (_thread_run->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)) { - /* - * Cancelations override signals. - * - * Stick a cancellation point at the start of - * each async-cancellable thread's resumption. - * - * We allow threads woken at cancel points to do their - * own checks. - */ - _thread_cancellation_point(); - } - - /* - * There might be pending signals for this thread, so - * dispatch any that aren't blocked: - */ - _dispatch_signals(); + _thread_check_cancel(); return; } else @@ -144,18 +134,6 @@ _thread_kern_sched(struct sigcontext * scp) /* Save errno. */ _thread_run->error = errno; -#ifdef _THREAD_RUSAGE - /* Accumulate time spent */ - if (getrusage(RUSAGE_SELF, &ru)) - PANIC("Cannot get resource usage"); - timersub(&ru.ru_utime, &ru_prev.ru_utime, &tv); - timeradd(&tv, &_thread_run->ru_utime, &_thread_run->ru_utime); - timersub(&ru.ru_stime, &ru_prev.ru_stime, &tv); - timeradd(&tv, &_thread_run->ru_stime, &_thread_run->ru_stime); - memcpy(&ru_prev.ru_utime, &ru.ru_utime, sizeof ru_prev.ru_utime); - memcpy(&ru_prev.ru_stime, &ru.ru_stime, sizeof ru_prev.ru_stime); -#endif /* _THREAD_RUSAGE */ - /* * Enter a scheduling loop that finds the next thread that is * ready to run. This loop completes when there are no more threads @@ -163,238 +141,208 @@ _thread_kern_sched(struct sigcontext * scp) * either a sigreturn (if the state was saved as a sigcontext) or a * longjmp (if the state was saved by a setjmp). */ - while (_thread_link_list != NULL) { + while (!(TAILQ_EMPTY(&_thread_list))) { /* Get the current time of day: */ gettimeofday(&tv, NULL); TIMEVAL_TO_TIMESPEC(&tv, &ts); /* - * Poll file descriptors to update the state of threads - * waiting on file I/O where data may be available: + * Protect the scheduling queues from access by the signal + * handler. */ - _thread_kern_select(0); + _queue_signals = 1; - /* - * Define the maximum time before a scheduling signal - * is required: - */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = TIMESLICE_USEC; - - /* - * The interval timer is not reloaded when it - * times out. The interval time needs to be - * calculated every time. - */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = 0; - - /* - * Enter a loop to look for sleeping threads that are ready - * or timedout. While we're at it, also find the smallest - * timeout value for threads waiting for a time. - */ - _waitingq_check_reqd = 0; /* reset flag before loop */ - TAILQ_FOREACH(pthread, &_waitingq, pqe) { - /* Check if this thread is ready: */ - if (pthread->state == PS_RUNNING) { - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); - } + if (_thread_run != &_thread_kern_thread) { /* - * Check if this thread is blocked by an - * atomic lock: + * This thread no longer needs to yield the CPU. + */ + _thread_run->yield_on_sig_undefer = 0; + + /* + * Save the current time as the time that the thread + * became inactive: + */ + _thread_run->last_inactive.tv_sec = tv.tv_sec; + _thread_run->last_inactive.tv_usec = tv.tv_usec; + + /* + * Place the currently running thread into the + * appropriate queue(s). */ - else if (pthread->state == PS_SPINBLOCK) { + switch (_thread_run->state) { + case PS_DEAD: /* - * If the lock is available, let - * the thread run. + * Dead threads are not placed in any queue: */ - if (pthread->data.spinlock->access_lock == 0) { - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - } + break; - /* Check if this thread is to timeout: */ - } else if (pthread->state == PS_COND_WAIT || - pthread->state == PS_SLEEP_WAIT || - pthread->state == PS_FDR_WAIT || - pthread->state == PS_FDW_WAIT || - pthread->state == PS_SELECT_WAIT) { - /* Check if this thread is to wait forever: */ - if (pthread->wakeup_time.tv_sec == -1) { - } + case PS_RUNNING: /* - * Check if this thread is to wakeup - * immediately or if it is past its wakeup - * time: + * Runnable threads can't be placed in the + * priority queue until after waiting threads + * are polled (to preserve round-robin + * scheduling). */ - else if ((pthread->wakeup_time.tv_sec == 0 && - pthread->wakeup_time.tv_nsec == 0) || - (ts.tv_sec > pthread->wakeup_time.tv_sec) || - ((ts.tv_sec == pthread->wakeup_time.tv_sec) && - (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) { + if ((_thread_run->slice_usec != -1) && + (_thread_run->attr.sched_policy != SCHED_FIFO)) { /* - * Check if this thread is waiting on - * select: + * Accumulate the number of microseconds that + * this thread has run for: */ - if (pthread->state == PS_SELECT_WAIT) { - /* - * The select has timed out, so - * zero the file descriptor - * sets: - */ - FD_ZERO(&pthread->data.select_data->readfds); - FD_ZERO(&pthread->data.select_data->writefds); - FD_ZERO(&pthread->data.select_data->exceptfds); - pthread->data.select_data->nfds = 0; - } - /* - * Return an error as an interrupted - * wait: - */ - _thread_seterrno(pthread, EINTR); + _thread_run->slice_usec += + (_thread_run->last_inactive.tv_sec - + _thread_run->last_active.tv_sec) * 1000000 + + _thread_run->last_inactive.tv_usec - + _thread_run->last_active.tv_usec; + + /* Check for time quantum exceeded: */ + if (_thread_run->slice_usec > TIMESLICE_USEC) + _thread_run->slice_usec = -1; + } + break; - /* - * Flag the timeout in the thread - * structure: - */ - pthread->timeout = 1; + /* + * States which do not depend on file descriptor I/O + * operations or timeouts: + */ + case PS_DEADLOCK: + case PS_FDLR_WAIT: + case PS_FDLW_WAIT: + case PS_FILE_WAIT: + case PS_JOIN: + case PS_MUTEX_WAIT: + case PS_SIGSUSPEND: + case PS_SIGTHREAD: + case PS_SIGWAIT: + case PS_SUSPENDED: + case PS_WAIT_WAIT: + /* No timeouts for these states: */ + _thread_run->wakeup_time.tv_sec = -1; + _thread_run->wakeup_time.tv_nsec = -1; - /* - * Change the threads state to allow - * it to be restarted: - */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - } else { - /* - * Calculate the time until this thread - * is ready, allowing for the clock - * resolution: - */ - ts1.tv_sec = pthread->wakeup_time.tv_sec - - ts.tv_sec; - ts1.tv_nsec = pthread->wakeup_time.tv_nsec - - ts.tv_nsec + CLOCK_RES_NSEC; + /* Restart the time slice: */ + _thread_run->slice_usec = -1; - /* - * Check for underflow of the - * nanosecond field: - */ - if (ts1.tv_nsec < 0) { - /* - * Allow for the underflow - * of the nanosecond field: - */ - ts1.tv_sec--; - ts1.tv_nsec += 1000000000; - } - /* - * Check for overflow of the nanosecond - * field: - */ - if (ts1.tv_nsec >= 1000000000) { - /* - * Allow for the overflow of - * the nanosecond field: - */ - ts1.tv_sec++; - ts1.tv_nsec -= 1000000000; - } - /* - * Convert the timespec structure - * to a timeval structure: - */ - TIMESPEC_TO_TIMEVAL(&tv1, &ts1); + /* Insert into the waiting queue: */ + PTHREAD_WAITQ_INSERT(_thread_run); + break; - /* - * Check if the thread will be ready - * sooner than the earliest ones found - * so far: - */ - if (timercmp(&tv1, &itimer.it_value, <)) { - /* - * Update the time value: - */ - itimer.it_value.tv_sec = tv1.tv_sec; - itimer.it_value.tv_usec = tv1.tv_usec; - } - } + /* States which can timeout: */ + case PS_COND_WAIT: + case PS_SLEEP_WAIT: + /* Restart the time slice: */ + _thread_run->slice_usec = -1; + /* Insert into the waiting queue: */ + PTHREAD_WAITQ_INSERT(_thread_run); + break; + + /* States that require periodic work: */ + case PS_SPINBLOCK: + /* No timeouts for this state: */ + _thread_run->wakeup_time.tv_sec = -1; + _thread_run->wakeup_time.tv_nsec = -1; + + /* Increment spinblock count: */ + _spinblock_count++; + + /* fall through */ + case PS_FDR_WAIT: + case PS_FDW_WAIT: + case PS_POLL_WAIT: + case PS_SELECT_WAIT: + /* Restart the time slice: */ + _thread_run->slice_usec = -1; + + /* Insert into the waiting queue: */ + PTHREAD_WAITQ_INSERT(_thread_run); + + /* Insert into the work queue: */ + PTHREAD_WORKQ_INSERT(_thread_run); } } - /* Check if there is a current thread: */ - if (_thread_run != _thread_kern_threadp) { - /* - * This thread no longer needs to yield the CPU. - */ - _thread_run->yield_on_sched_undefer = 0; + /* Unprotect the scheduling queues: */ + _queue_signals = 0; - /* - * Save the current time as the time that the thread - * became inactive: - */ - _thread_run->last_inactive.tv_sec = tv.tv_sec; - _thread_run->last_inactive.tv_usec = tv.tv_usec; + /* + * Poll file descriptors to update the state of threads + * waiting on file I/O where data may be available: + */ + _thread_kern_poll(0); + /* Protect the scheduling queues: */ + _queue_signals = 1; + + /* + * Wake up threads that have timedout. This has to be + * done after polling in case a thread does a poll or + * select with zero time. + */ + PTHREAD_WAITQ_SETACTIVE(); + while (((pthread = TAILQ_FIRST(&_waitingq)) != NULL) && + (pthread->wakeup_time.tv_sec != -1) && + (((pthread->wakeup_time.tv_sec == 0) && + (pthread->wakeup_time.tv_nsec == 0)) || + (pthread->wakeup_time.tv_sec < ts.tv_sec) || + ((pthread->wakeup_time.tv_sec == ts.tv_sec) && + (pthread->wakeup_time.tv_nsec <= ts.tv_nsec)))) { + switch (pthread->state) { + case PS_POLL_WAIT: + case PS_SELECT_WAIT: + /* Return zero file descriptors ready: */ + pthread->data.poll_data->nfds = 0; + /* fall through */ + default: + /* + * Remove this thread from the waiting queue + * (and work queue if necessary) and place it + * in the ready queue. + */ + PTHREAD_WAITQ_CLEARACTIVE(); + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); + break; + } /* - * Accumulate the number of microseconds that this - * thread has run for: + * Flag the timeout in the thread structure: */ - if ((_thread_run->slice_usec != -1) && - (_thread_run->attr.sched_policy != SCHED_FIFO)) { - _thread_run->slice_usec += - (_thread_run->last_inactive.tv_sec - - _thread_run->last_active.tv_sec) * 1000000 + - _thread_run->last_inactive.tv_usec - - _thread_run->last_active.tv_usec; - - /* Check for time quantum exceeded: */ - if (_thread_run->slice_usec > TIMESLICE_USEC) - _thread_run->slice_usec = -1; - } - if (_thread_run->state == PS_RUNNING) { - if (_thread_run->slice_usec == -1) { - /* - * The thread exceeded its time - * quantum or it yielded the CPU; - * place it at the tail of the - * queue for its priority. - */ - PTHREAD_PRIOQ_INSERT_TAIL(_thread_run); - } else { - /* - * The thread hasn't exceeded its - * interval. Place it at the head - * of the queue for its priority. - */ - PTHREAD_PRIOQ_INSERT_HEAD(_thread_run); - } - } - else if (_thread_run->state == PS_DEAD) { + pthread->timeout = 1; + } + PTHREAD_WAITQ_CLEARACTIVE(); + + /* + * Check if there is a current runnable thread that isn't + * already in the ready queue: + */ + if ((_thread_run != &_thread_kern_thread) && + (_thread_run->state == PS_RUNNING) && + ((_thread_run->flags & PTHREAD_FLAGS_IN_PRIOQ) == 0)) { + if (_thread_run->slice_usec == -1) { /* - * Don't add dead threads to the waiting - * queue, because when they're reaped, it - * will corrupt the queue. + * The thread exceeded its time + * quantum or it yielded the CPU; + * place it at the tail of the + * queue for its priority. */ - } - else { + PTHREAD_PRIOQ_INSERT_TAIL(_thread_run); + } else { /* - * This thread has changed state and needs - * to be placed in the waiting queue. + * The thread hasn't exceeded its + * interval. Place it at the head + * of the queue for its priority. */ - PTHREAD_WAITQ_INSERT(_thread_run); - - /* Restart the time slice: */ - _thread_run->slice_usec = -1; + PTHREAD_PRIOQ_INSERT_HEAD(_thread_run); } } /* * Get the highest priority thread in the ready queue. */ - pthread_h = PTHREAD_PRIOQ_FIRST; + pthread_h = PTHREAD_PRIOQ_FIRST(); /* Check if there are no threads ready to run: */ if (pthread_h == NULL) { @@ -403,20 +351,86 @@ _thread_kern_sched(struct sigcontext * scp) * the running thread to point to the global kernel * thread structure: */ - _thread_run = _thread_kern_threadp; + _thread_run = &_thread_kern_thread; + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; /* * There are no threads ready to run, so wait until * something happens that changes this condition: */ - _thread_kern_select(1); - } else { + _thread_kern_poll(1); + } + else { + /* Remove the thread from the ready queue: */ + PTHREAD_PRIOQ_REMOVE(pthread_h); + + /* Get first thread on the waiting list: */ + pthread = TAILQ_FIRST(&_waitingq); + + /* Check to see if there is more than one thread: */ + if (pthread_h != TAILQ_FIRST(&_thread_list) || + TAILQ_NEXT(pthread_h, tle) != NULL) + set_timer = 1; + else + set_timer = 0; + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; + + /* + * Check for signals queued while the scheduling + * queues were protected: + */ + while (_sigq_check_reqd != 0) { + /* Clear before handling queued signals: */ + _sigq_check_reqd = 0; + + /* Protect the scheduling queues again: */ + _queue_signals = 1; + + dequeue_signals(); + + /* + * Check for a higher priority thread that + * became runnable due to signal handling. + */ + if (((pthread = PTHREAD_PRIOQ_FIRST()) != NULL) && + (pthread->active_priority > pthread_h->active_priority)) { + /* + * Insert the lower priority thread + * at the head of its priority list: + */ + PTHREAD_PRIOQ_INSERT_HEAD(pthread_h); + + /* Remove the thread from the ready queue: */ + PTHREAD_PRIOQ_REMOVE(pthread); + + /* There's a new thread in town: */ + pthread_h = pthread; + } + + /* Get first thread on the waiting list: */ + pthread = TAILQ_FIRST(&_waitingq); + + /* + * Check to see if there is more than one + * thread: + */ + if (pthread_h != TAILQ_FIRST(&_thread_list) || + TAILQ_NEXT(pthread_h, tle) != NULL) + set_timer = 1; + else + set_timer = 0; + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; + } + /* Make the selected thread the current thread: */ _thread_run = pthread_h; - /* Remove the thread from the ready queue. */ - PTHREAD_PRIOQ_REMOVE(_thread_run); - /* * Save the current time as the time that the thread * became active: @@ -425,6 +439,76 @@ _thread_kern_sched(struct sigcontext * scp) _thread_run->last_active.tv_usec = tv.tv_usec; /* + * Define the maximum time before a scheduling signal + * is required: + */ + itimer.it_value.tv_sec = 0; + itimer.it_value.tv_usec = TIMESLICE_USEC; + + /* + * The interval timer is not reloaded when it + * times out. The interval time needs to be + * calculated every time. + */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = 0; + + /* Get first thread on the waiting list: */ + if ((pthread != NULL) && + (pthread->wakeup_time.tv_sec != -1)) { + /* + * Calculate the time until this thread + * is ready, allowing for the clock + * resolution: + */ + ts1.tv_sec = pthread->wakeup_time.tv_sec + - ts.tv_sec; + ts1.tv_nsec = pthread->wakeup_time.tv_nsec + - ts.tv_nsec + _clock_res_nsec; + + /* + * Check for underflow of the nanosecond field: + */ + while (ts1.tv_nsec < 0) { + /* + * Allow for the underflow of the + * nanosecond field: + */ + ts1.tv_sec--; + ts1.tv_nsec += 1000000000; + } + /* + * Check for overflow of the nanosecond field: + */ + while (ts1.tv_nsec >= 1000000000) { + /* + * Allow for the overflow of the + * nanosecond field: + */ + ts1.tv_sec++; + ts1.tv_nsec -= 1000000000; + } + /* + * Convert the timespec structure to a + * timeval structure: + */ + TIMESPEC_TO_TIMEVAL(&tv1, &ts1); + + /* + * Check if the thread will be ready + * sooner than the earliest ones found + * so far: + */ + if (timercmp(&tv1, &itimer.it_value, <)) { + /* + * Update the time value: + */ + itimer.it_value.tv_sec = tv1.tv_sec; + itimer.it_value.tv_usec = tv1.tv_usec; + } + } + + /* * Check if this thread is running for the first time * or running again after using its full time slice * allocation: @@ -435,7 +519,7 @@ _thread_kern_sched(struct sigcontext * scp) } /* Check if there is more than one thread: */ - if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) { + if (set_timer != 0) { /* * Start the interval timer for the * calculated time interval: @@ -454,8 +538,9 @@ _thread_kern_sched(struct sigcontext * scp) /* Check if a signal context was saved: */ if (_thread_run->sig_saved == 1) { - - /* Restore the floating point state: */ + /* + * Restore floating point state. + */ _thread_machdep_restore_float_state(_thread_run); /* @@ -474,13 +559,14 @@ _thread_kern_sched(struct sigcontext * scp) _thread_run); } _thread_sys_sigreturn(&_thread_run->saved_sigcontext); - } else + } else { /* * Do a longjmp to restart the thread that * was context switched out (by a longjmp to * a different thread): */ _thread_machdep_longjmp(_thread_run->saved_jmp_buf, 1); + } /* This point should not be reached. */ PANIC("Thread has returned from sigreturn or longjmp"); @@ -494,6 +580,19 @@ _thread_kern_sched(struct sigcontext * scp) void _thread_kern_sched_state(enum pthread_state state, const char *fname, int lineno) { + /* + * Flag the pthread kernel as executing scheduler code + * to avoid a scheduler signal from interrupting this + * execution and calling the scheduler again. + */ + _thread_kern_in_sched = 1; + + /* + * Prevent the signal handler from fiddling with this thread + * before its state is set and is placed into the proper queue. + */ + _queue_signals = 1; + /* Change the state of the current thread: */ _thread_run->state = state; _thread_run->fname = fname; @@ -508,6 +607,20 @@ void _thread_kern_sched_state_unlock(enum pthread_state state, spinlock_t *lock, char *fname, int lineno) { + /* + * Flag the pthread kernel as executing scheduler code + * to avoid a scheduler signal from interrupting this + * execution and calling the scheduler again. + */ + _thread_kern_in_sched = 1; + + /* + * Prevent the signal handler from fiddling with this thread + * before its state is set and it is placed into the proper + * queue(s). + */ + _queue_signals = 1; + /* Change the state of the current thread: */ _thread_run->state = state; _thread_run->fname = fname; @@ -521,385 +634,193 @@ _thread_kern_sched_state_unlock(enum pthread_state state, } static void -_thread_kern_select(int wait_reqd) +_thread_kern_poll(int wait_reqd) { - char bufr[128]; - fd_set fd_set_except; - fd_set fd_set_read; - fd_set fd_set_write; int count = 0; - int count_dec; - int found_one; - int i; - int nfds = -1; - int settimeout; - pthread_t pthread; - ssize_t num; + int i, found; + int kern_pipe_added = 0; + int nfds = 0; + int timeout_ms = 0; + struct pthread *pthread; struct timespec ts; - struct timespec ts1; - struct timeval *p_tv; struct timeval tv; - struct timeval tv1; - - /* Zero the file descriptor sets: */ - FD_ZERO(&fd_set_read); - FD_ZERO(&fd_set_write); - FD_ZERO(&fd_set_except); /* Check if the caller wants to wait: */ - if (wait_reqd) { - /* - * Add the pthread kernel pipe file descriptor to the read - * set: - */ - FD_SET(_thread_kern_pipe[0], &fd_set_read); - nfds = _thread_kern_pipe[0]; - + if (wait_reqd == 0) { + timeout_ms = 0; + } + else { /* Get the current time of day: */ gettimeofday(&tv, NULL); TIMEVAL_TO_TIMESPEC(&tv, &ts); + + _queue_signals = 1; + pthread = TAILQ_FIRST(&_waitingq); + _queue_signals = 0; + + if ((pthread == NULL) || (pthread->wakeup_time.tv_sec == -1)) { + /* + * Either there are no threads in the waiting queue, + * or there are no threads that can timeout. + */ + timeout_ms = -1; + } + else { + /* + * Calculate the time left for the next thread to + * timeout allowing for the clock resolution: + */ + timeout_ms = ((pthread->wakeup_time.tv_sec - ts.tv_sec) * + 1000) + ((pthread->wakeup_time.tv_nsec - ts.tv_nsec + + _clock_res_nsec) / 1000000); + /* + * Don't allow negative timeouts: + */ + if (timeout_ms < 0) + timeout_ms = 0; + } } - /* Initialise the time value structure: */ - tv.tv_sec = 0; - tv.tv_usec = 0; + + /* Protect the scheduling queues: */ + _queue_signals = 1; /* - * Enter a loop to process threads waiting on either file descriptors - * or times: + * Check to see if the signal queue needs to be walked to look + * for threads awoken by a signal while in the scheduler. */ - _waitingq_check_reqd = 0; /* reset flag before loop */ - TAILQ_FOREACH (pthread, &_waitingq, pqe) { - /* Assume that this state does not time out: */ - settimeout = 0; + if (_sigq_check_reqd != 0) { + /* Reset flag before handling queued signals: */ + _sigq_check_reqd = 0; - /* Process according to thread state: */ - switch (pthread->state) { + dequeue_signals(); + } + + /* + * Check for a thread that became runnable due to a signal: + */ + if (PTHREAD_PRIOQ_FIRST() != NULL) { /* - * States which do not depend on file descriptor I/O - * operations or timeouts: + * Since there is at least one runnable thread, + * disable the wait. */ - case PS_DEAD: - case PS_DEADLOCK: - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FILE_WAIT: - case PS_JOIN: - case PS_MUTEX_WAIT: - case PS_SIGTHREAD: - case PS_SIGWAIT: - case PS_STATE_MAX: - case PS_WAIT_WAIT: - case PS_SUSPENDED: - case PS_SIGSUSPEND: - /* Nothing to do here. */ - break; + timeout_ms = 0; + } + + /* + * Form the poll table: + */ + nfds = 0; + if (timeout_ms != 0) { + /* Add the kernel pipe to the poll table: */ + _thread_pfd_table[nfds].fd = _thread_kern_pipe[0]; + _thread_pfd_table[nfds].events = POLLRDNORM; + _thread_pfd_table[nfds].revents = 0; + nfds++; + kern_pipe_added = 1; + } - case PS_RUNNING: + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { + switch (pthread->state) { + case PS_SPINBLOCK: /* - * A signal occurred and made this thread ready - * while in the scheduler or while the scheduling - * queues were protected. + * If the lock is available, let the thread run. */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); + /* One less thread in a spinblock state: */ + _spinblock_count--; + /* + * Since there is at least one runnable + * thread, disable the wait. + */ + timeout_ms = 0; + } break; /* File descriptor read wait: */ case PS_FDR_WAIT: - /* Add the file descriptor to the read set: */ - FD_SET(pthread->data.fd.fd, &fd_set_read); - - /* - * Check if this file descriptor is greater than any - * of those seen so far: - */ - if (pthread->data.fd.fd > nfds) { - /* Remember this file descriptor: */ - nfds = pthread->data.fd.fd; + /* Limit number of polled files to table size: */ + if (nfds < _thread_dtablesize) { + _thread_pfd_table[nfds].events = POLLRDNORM; + _thread_pfd_table[nfds].fd = pthread->data.fd.fd; + nfds++; } - /* Increment the file descriptor count: */ - count++; - - /* This state can time out: */ - settimeout = 1; break; /* File descriptor write wait: */ case PS_FDW_WAIT: - /* Add the file descriptor to the write set: */ - FD_SET(pthread->data.fd.fd, &fd_set_write); - - /* - * Check if this file descriptor is greater than any - * of those seen so far: - */ - if (pthread->data.fd.fd > nfds) { - /* Remember this file descriptor: */ - nfds = pthread->data.fd.fd; + /* Limit number of polled files to table size: */ + if (nfds < _thread_dtablesize) { + _thread_pfd_table[nfds].events = POLLWRNORM; + _thread_pfd_table[nfds].fd = pthread->data.fd.fd; + nfds++; } - /* Increment the file descriptor count: */ - count++; - - /* This state can time out: */ - settimeout = 1; - break; - - /* States that time out: */ - case PS_SLEEP_WAIT: - case PS_COND_WAIT: - /* Flag a timeout as required: */ - settimeout = 1; break; - /* Select wait: */ + /* File descriptor poll or select wait: */ + case PS_POLL_WAIT: case PS_SELECT_WAIT: - /* - * Enter a loop to process each file descriptor in - * the thread-specific file descriptor sets: - */ - for (i = 0; i < pthread->data.select_data->nfds; i++) { - /* - * Check if this file descriptor is set for - * exceptions: - */ - if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) { - /* - * Add the file descriptor to the - * exception set: - */ - FD_SET(i, &fd_set_except); - - /* - * Increment the file descriptor - * count: - */ - count++; - - /* - * Check if this file descriptor is - * greater than any of those seen so - * far: - */ - if (i > nfds) { - /* - * Remember this file - * descriptor: - */ - nfds = i; - } - } - /* - * Check if this file descriptor is set for - * write: - */ - if (FD_ISSET(i, &pthread->data.select_data->writefds)) { - /* - * Add the file descriptor to the - * write set: - */ - FD_SET(i, &fd_set_write); - - /* - * Increment the file descriptor - * count: - */ - count++; - - /* - * Check if this file descriptor is - * greater than any of those seen so - * far: - */ - if (i > nfds) { - /* - * Remember this file - * descriptor: - */ - nfds = i; - } - } - /* - * Check if this file descriptor is set for - * read: - */ - if (FD_ISSET(i, &pthread->data.select_data->readfds)) { - /* - * Add the file descriptor to the - * read set: - */ - FD_SET(i, &fd_set_read); - - /* - * Increment the file descriptor - * count: - */ - count++; - - /* - * Check if this file descriptor is - * greater than any of those seen so - * far: - */ - if (i > nfds) { - /* - * Remember this file - * descriptor: - */ - nfds = i; - } + /* Limit number of polled files to table size: */ + if (pthread->data.poll_data->nfds + nfds < + _thread_dtablesize) { + for (i = 0; i < pthread->data.poll_data->nfds; i++) { + _thread_pfd_table[nfds + i].fd = + pthread->data.poll_data->fds[i].fd; + _thread_pfd_table[nfds + i].events = + pthread->data.poll_data->fds[i].events; } + nfds += pthread->data.poll_data->nfds; } - - /* This state can time out: */ - settimeout = 1; break; - } - - /* - * Check if the caller wants to wait and if the thread state - * is one that times out: - */ - if (wait_reqd && settimeout) { - /* Check if this thread wants to wait forever: */ - if (pthread->wakeup_time.tv_sec == -1) { - } - /* Check if this thread doesn't want to wait at all: */ - else if (pthread->wakeup_time.tv_sec == 0 && - pthread->wakeup_time.tv_nsec == 0) { - /* Override the caller's request to wait: */ - wait_reqd = 0; - } else { - /* - * Calculate the time until this thread is - * ready, allowing for the clock resolution: - */ - ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec; - ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec + - CLOCK_RES_NSEC; - /* - * Check for underflow of the nanosecond - * field: - */ - if (ts1.tv_nsec < 0) { - /* - * Allow for the underflow of the - * nanosecond field: - */ - ts1.tv_sec--; - ts1.tv_nsec += 1000000000; - } - /* - * Check for overflow of the nanosecond - * field: - */ - if (ts1.tv_nsec >= 1000000000) { - /* - * Allow for the overflow of the - * nanosecond field: - */ - ts1.tv_sec++; - ts1.tv_nsec -= 1000000000; - } - /* - * Convert the timespec structure to a - * timeval structure: - */ - TIMESPEC_TO_TIMEVAL(&tv1, &ts1); - - /* - * Check if no time value has been found yet, - * or if the thread will be ready sooner that - * the earliest one found so far: - */ - if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) { - /* Update the time value: */ - tv.tv_sec = tv1.tv_sec; - tv.tv_usec = tv1.tv_usec; - } - } + /* Other states do not depend on file I/O. */ + default: + break; } } + PTHREAD_WAITQ_CLEARACTIVE(); - /* Check if the caller wants to wait: */ - if (wait_reqd) { - /* Check if no threads were found with timeouts: */ - if (tv.tv_sec == 0 && tv.tv_usec == 0) { - /* Wait forever: */ - p_tv = NULL; - } else { - /* - * Point to the time value structure which contains - * the earliest time that a thread will be ready: - */ - p_tv = &tv; - } + /* + * Wait for a file descriptor to be ready for read, write, or + * an exception, or a timeout to occur: + */ + count = _thread_sys_poll(_thread_pfd_table, nfds, timeout_ms); + if (kern_pipe_added != 0) /* - * Flag the pthread kernel as in a select. This is to avoid - * the window between the next statement that unblocks - * signals and the select statement which follows. + * Remove the pthread kernel pipe file descriptor + * from the pollfd table: */ - _thread_kern_in_select = 1; + nfds = 1; + else + nfds = 0; + /* + * Check if it is possible that there are bytes in the kernel + * read pipe waiting to be read: + */ + if (count < 0 || ((kern_pipe_added != 0) && + (_thread_pfd_table[0].revents & POLLRDNORM))) { /* - * Wait for a file descriptor to be ready for read, write, or - * an exception, or a timeout to occur: + * If the kernel read pipe was included in the + * count: */ - count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv); + if (count > 0) { + /* Decrement the count of file descriptors: */ + count--; + } - /* Reset the kernel in select flag: */ - _thread_kern_in_select = 0; + if (_sigq_check_reqd != 0) { + /* Reset flag before handling signals: */ + _sigq_check_reqd = 0; - /* - * Check if it is possible that there are bytes in the kernel - * read pipe waiting to be read: - */ - if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) { - /* - * Check if the kernel read pipe was included in the - * count: - */ - if (count > 0) { - /* - * Remove the kernel read pipe from the - * count: - */ - FD_CLR(_thread_kern_pipe[0], &fd_set_read); - - /* Decrement the count of file descriptors: */ - count--; - } - /* - * Enter a loop to read (and trash) bytes from the - * pthread kernel pipe: - */ - while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) { - /* - * The buffer read contains one byte per - * signal and each byte is the signal number. - * This data is not used, but the fact that - * the signal handler wrote to the pipe *is* - * used to cause the _select call - * to complete if the signal occurred between - * the time when signals were unblocked and - * the _select select call being - * made. - */ - } + dequeue_signals(); } } - /* Check if there are file descriptors to poll: */ - else if (count > 0) { - /* - * Point to the time value structure which has been zeroed so - * that the call to _select will not wait: - */ - p_tv = &tv; - - /* Poll file descrptors without wait: */ - count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv); - } /* * Check if any file descriptors are ready: @@ -908,302 +829,133 @@ _thread_kern_select(int wait_reqd) /* * Enter a loop to look for threads waiting on file * descriptors that are flagged as available by the - * _select syscall: + * _poll syscall: */ - TAILQ_FOREACH (pthread, &_waitingq, pqe) { - /* Process according to thread state: */ + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { switch (pthread->state) { - /* - * States which do not depend on file - * descriptor I/O operations: - */ - case PS_COND_WAIT: - case PS_DEAD: - case PS_DEADLOCK: - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FILE_WAIT: - case PS_JOIN: - case PS_MUTEX_WAIT: - case PS_SIGWAIT: - case PS_SLEEP_WAIT: - case PS_WAIT_WAIT: - case PS_SIGTHREAD: - case PS_STATE_MAX: - case PS_SUSPENDED: - case PS_SIGSUSPEND: - /* Nothing to do here. */ - break; - - case PS_RUNNING: + case PS_SPINBLOCK: /* - * A signal occurred and made this thread - * ready while in the scheduler. + * If the lock is available, let the thread run. */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); - break; + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); - /* File descriptor read wait: */ - case PS_FDR_WAIT: - /* - * Check if the file descriptor is available - * for read: - */ - if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) { /* - * Change the thread state to allow - * it to read from the file when it - * is scheduled next: + * One less thread in a spinblock state: */ - pthread->state = PS_RUNNING; + _spinblock_count--; + } + break; - /* - * Remove it from the waiting queue - * and add it to the ready queue: - */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + /* File descriptor read wait: */ + case PS_FDR_WAIT: + if ((nfds < _thread_dtablesize) && + (_thread_pfd_table[nfds].revents & POLLRDNORM)) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); } + nfds++; break; /* File descriptor write wait: */ case PS_FDW_WAIT: - /* - * Check if the file descriptor is available - * for write: - */ - if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) { - /* - * Change the thread state to allow - * it to write to the file when it is - * scheduled next: - */ - pthread->state = PS_RUNNING; - - /* - * Remove it from the waiting queue - * and add it to the ready queue: - */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + if ((nfds < _thread_dtablesize) && + (_thread_pfd_table[nfds].revents & POLLWRNORM)) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); } + nfds++; break; - /* Select wait: */ + /* File descriptor poll or select wait: */ + case PS_POLL_WAIT: case PS_SELECT_WAIT: - /* - * Reset the flag that indicates if a file - * descriptor is ready for some type of - * operation: - */ - count_dec = 0; - - /* - * Enter a loop to search though the - * thread-specific select file descriptors - * for the first descriptor that is ready: - */ - for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) { - /* - * Check if this file descriptor does - * not have an exception: - */ - if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) { - /* - * Flag this file descriptor - * as ready: - */ - count_dec = 1; - } + if (pthread->data.poll_data->nfds + nfds < + _thread_dtablesize) { /* - * Check if this file descriptor is - * not ready for write: + * Enter a loop looking for I/O + * readiness: */ - if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) { - /* - * Flag this file descriptor - * as ready: - */ - count_dec = 1; + found = 0; + for (i = 0; i < pthread->data.poll_data->nfds; i++) { + if (_thread_pfd_table[nfds + i].revents != 0) { + pthread->data.poll_data->fds[i].revents = + _thread_pfd_table[nfds + i].revents; + found++; + } } - /* - * Check if this file descriptor is - * not ready for read: - */ - if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) { - /* - * Flag this file descriptor - * as ready: - */ - count_dec = 1; + + /* Increment before destroying: */ + nfds += pthread->data.poll_data->nfds; + + if (found != 0) { + pthread->data.poll_data->nfds = found; + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); } } + else + nfds += pthread->data.poll_data->nfds; + break; + /* Other states do not depend on file I/O. */ + default: + break; + } + } + PTHREAD_WAITQ_CLEARACTIVE(); + } + else if (_spinblock_count != 0) { + /* + * Enter a loop to look for threads waiting on a spinlock + * that is now available. + */ + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { + if (pthread->state == PS_SPINBLOCK) { /* - * Check if any file descriptors are ready - * for the current thread: + * If the lock is available, let the thread run. */ - if (count_dec) { - /* - * Reset the count of file - * descriptors that are ready for - * this thread: - */ - found_one = 0; - - /* - * Enter a loop to search though the - * thread-specific select file - * descriptors: - */ - for (i = 0; i < pthread->data.select_data->nfds; i++) { - /* - * Reset the count of - * operations for which the - * current file descriptor is - * ready: - */ - count_dec = 0; - - /* - * Check if this file - * descriptor is selected for - * exceptions: - */ - if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) { - /* - * Check if this file - * descriptor has an - * exception: - */ - if (FD_ISSET(i, &fd_set_except)) { - /* - * Increment - * the count - * for this - * file: - */ - count_dec++; - } else { - /* - * Clear the - * file - * descriptor - * in the - * thread-spec - * ific file - * descriptor - * set: - */ - FD_CLR(i, &pthread->data.select_data->exceptfds); - } - } - /* - * Check if this file - * descriptor is selected for - * write: - */ - if (FD_ISSET(i, &pthread->data.select_data->writefds)) { - /* - * Check if this file - * descriptor is - * ready for write: - */ - if (FD_ISSET(i, &fd_set_write)) { - /* - * Increment - * the count - * for this - * file: - */ - count_dec++; - } else { - /* - * Clear the - * file - * descriptor - * in the - * thread-spec - * ific file - * descriptor - * set: - */ - FD_CLR(i, &pthread->data.select_data->writefds); - } - } - /* - * Check if this file - * descriptor is selected for - * read: - */ - if (FD_ISSET(i, &pthread->data.select_data->readfds)) { - /* - * Check if this file - * descriptor is - * ready for read: - */ - if (FD_ISSET(i, &fd_set_read)) { - /* - * Increment - * the count - * for this - * file: - */ - count_dec++; - } else { - /* - * Clear the - * file - * descriptor - * in the - * thread-spec - * ific file - * descriptor - * set: - */ - FD_CLR(i, &pthread->data.select_data->readfds); - } - } - /* - * Check if the current file - * descriptor is ready for - * any one of the operations: - */ - if (count_dec > 0) { - /* - * Increment the - * count of file - * descriptors that - * are ready for the - * current thread: - */ - found_one++; - } - } - - /* - * Return the number of file - * descriptors that are ready: - */ - pthread->data.select_data->nfds = found_one; - - /* - * Change the state of the current - * thread to run: - */ - pthread->state = PS_RUNNING; + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); /* - * Remove it from the waiting queue - * and add it to the ready queue: + * One less thread in a spinblock state: */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + _spinblock_count--; } - break; } } + PTHREAD_WAITQ_CLEARACTIVE(); + } + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; + + while (_sigq_check_reqd != 0) { + /* Handle queued signals: */ + _sigq_check_reqd = 0; + + /* Protect the scheduling queues: */ + _queue_signals = 1; + + dequeue_signals(); + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; } /* Nothing to return. */ @@ -1253,59 +1005,101 @@ _thread_kern_set_timeout(struct timespec * timeout) } void -_thread_kern_sched_defer(void) +_thread_kern_sig_defer(void) { - /* Allow scheduling deferral to be recursive. */ - _thread_run->sched_defer_count++; + /* Allow signal deferral to be recursive. */ + _thread_run->sig_defer_count++; } void -_thread_kern_sched_undefer(void) +_thread_kern_sig_undefer(void) { pthread_t pthread; int need_resched = 0; /* * Perform checks to yield only if we are about to undefer - * scheduling. + * signals. */ - if (_thread_run->sched_defer_count == 1) { + if (_thread_run->sig_defer_count > 1) { + /* Decrement the signal deferral count. */ + _thread_run->sig_defer_count--; + } + else if (_thread_run->sig_defer_count == 1) { + /* Reenable signals: */ + _thread_run->sig_defer_count = 0; + /* - * Check if the waiting queue needs to be examined for - * threads that are now ready: + * Check if there are queued signals: */ - while (_waitingq_check_reqd != 0) { - /* Clear the flag before checking the waiting queue: */ - _waitingq_check_reqd = 0; - - TAILQ_FOREACH(pthread, &_waitingq, pqe) { - if (pthread->state == PS_RUNNING) { - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); - } + while (_sigq_check_reqd != 0) { + /* Defer scheduling while we process queued signals: */ + _thread_run->sig_defer_count = 1; + + /* Clear the flag before checking the signal queue: */ + _sigq_check_reqd = 0; + + /* Dequeue and handle signals: */ + dequeue_signals(); + + /* + * Avoiding an unnecessary check to reschedule, check + * to see if signal handling caused a higher priority + * thread to become ready. + */ + if ((need_resched == 0) && + (((pthread = PTHREAD_PRIOQ_FIRST()) != NULL) && + (pthread->active_priority > _thread_run->active_priority))) { + need_resched = 1; } + + /* Reenable signals: */ + _thread_run->sig_defer_count = 0; } - /* - * We need to yield if a thread change of state caused a - * higher priority thread to become ready, or if a - * scheduling signal occurred while preemption was disabled. - */ - if ((((pthread = PTHREAD_PRIOQ_FIRST) != NULL) && - (pthread->active_priority > _thread_run->active_priority)) || - (_thread_run->yield_on_sched_undefer != 0)) { - _thread_run->yield_on_sched_undefer = 0; - need_resched = 1; + /* Yield the CPU if necessary: */ + if (need_resched || _thread_run->yield_on_sig_undefer != 0) { + _thread_run->yield_on_sig_undefer = 0; + _thread_kern_sched(NULL); } } +} - if (_thread_run->sched_defer_count > 0) { - /* Decrement the scheduling deferral count. */ - _thread_run->sched_defer_count--; +static void +dequeue_signals(void) +{ + char bufr[128]; + int i, num; - /* Yield the CPU if necessary: */ - if (need_resched) - _thread_kern_sched(NULL); + /* + * Enter a loop to read and handle queued signals from the + * pthread kernel pipe: + */ + while (((num = _thread_sys_read(_thread_kern_pipe[0], bufr, + sizeof(bufr))) > 0) || (num == -1 && errno == EINTR)) { + /* + * The buffer read contains one byte per signal and + * each byte is the signal number. + */ + for (i = 0; i < num; i++) { + if ((int) bufr[i] == _SCHED_SIGNAL) { + /* + * Scheduling signals shouldn't ever be + * queued; just ignore it for now. + */ + } + else { + /* Handle this signal: */ + _thread_sig_handle((int) bufr[i], NULL); + } + } + } + if ((num < 0) && (errno != EAGAIN)) { + /* + * The only error we should expect is if there is + * no data to read. + */ + PANIC("Unable to read from thread kernel pipe"); } } @@ -1316,10 +1110,10 @@ thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in) pthread_t tid_in = thread_in; if ((tid_out != NULL) && - (tid_out->flags & PTHREAD_FLAGS_PRIVATE != 0)) + ((tid_out->flags & PTHREAD_FLAGS_PRIVATE) != 0)) tid_out = NULL; if ((tid_in != NULL) && - (tid_in->flags & PTHREAD_FLAGS_PRIVATE != 0)) + ((tid_in->flags & PTHREAD_FLAGS_PRIVATE) != 0)) tid_in = NULL; if ((_sched_switch_hook != NULL) && (tid_out != tid_in)) { diff --git a/lib/libc_r/uthread/uthread_kill.c b/lib/libc_r/uthread/uthread_kill.c index dc698ff1660..172d3817513 100644 --- a/lib/libc_r/uthread/uthread_kill.c +++ b/lib/libc_r/uthread/uthread_kill.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_kill.c,v 1.6 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_kill.c,v 1.7 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -21,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_kill.c,v 1.9 1999/08/28 00:03:38 peter Exp $ */ #include <errno.h> #include <signal.h> @@ -47,18 +48,18 @@ pthread_kill(pthread_t pthread, int sig) /* Invalid signal: */ ret = EINVAL; - /* Ignored signals get dropped on the floor. */ - else if (_thread_sigact[sig - 1].sa_handler == SIG_IGN) - ret = 0; - - /* Find the thread in the list of active threads: */ - else if ((ret = _find_thread(pthread)) == 0) { + /* + * Ensure the thread is in the list of active threads, and the + * signal is valid (signal 0 specifies error checking only) and + * not being ignored: + */ + else if (((ret = _find_thread(pthread)) == 0) && (sig > 0) && + (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); switch (pthread->state) { case PS_SIGSUSPEND: @@ -91,15 +92,19 @@ pthread_kill(pthread_t pthread, int sig) sigaddset(&pthread->sigpend,sig); break; - case PS_SELECT_WAIT: case PS_FDR_WAIT: case PS_FDW_WAIT: + case PS_POLL_WAIT: case PS_SLEEP_WAIT: + case PS_SELECT_WAIT: if (!sigismember(&pthread->sigmask, sig) && (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { /* Flag the operation as interrupted: */ pthread->interrupted = 1; + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + /* Change the state of the thread to run: */ PTHREAD_NEW_STATE(pthread,PS_RUNNING); @@ -117,11 +122,43 @@ pthread_kill(pthread_t pthread, int sig) break; } + + /* + * Check that a custom handler is installed + * and if the signal is not blocked: + */ + if (_thread_sigact[sig - 1].sa_handler != SIG_DFL && + _thread_sigact[sig - 1].sa_handler != SIG_IGN && + sigismember(&pthread->sigpend, sig) && + !sigismember(&pthread->sigmask, sig)) { + pthread_t pthread_saved = _thread_run; + + /* Current thread inside critical region? */ + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count++; + + _thread_run = pthread; + + /* Clear the pending signal: */ + sigdelset(&pthread->sigpend, sig); + + /* + * Dispatch the signal via the custom signal + * handler: + */ + (*(_thread_sigact[sig - 1].sa_handler))(sig); + + _thread_run = pthread_saved; + + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count--; + } + /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ diff --git a/lib/libc_r/uthread/uthread_listen.c b/lib/libc_r/uthread/uthread_listen.c index 880cb4c6b12..0f9b312b3bb 100644 --- a/lib/libc_r/uthread/uthread_listen.c +++ b/lib/libc_r/uthread/uthread_listen.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_listen.c,v 1.3 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_listen.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_listen.c,v 1.5 1999/08/28 00:03:38 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libc_r/uthread/uthread_mattr_init.c b/lib/libc_r/uthread/uthread_mattr_init.c index 65b79e9539f..172ddb45b35 100644 --- a/lib/libc_r/uthread/uthread_mattr_init.c +++ b/lib/libc_r/uthread/uthread_mattr_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mattr_init.c,v 1.3 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_mattr_init.c,v 1.4 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1996 Jeffrey Hsu <hsu@freebsd.org>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mattr_init.c,v 1.5 1999/08/28 00:03:39 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libc_r/uthread/uthread_mattr_kind_np.c b/lib/libc_r/uthread/uthread_mattr_kind_np.c index 5f5d1b3a992..073c30da4e9 100644 --- a/lib/libc_r/uthread/uthread_mattr_kind_np.c +++ b/lib/libc_r/uthread/uthread_mattr_kind_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_mattr_kind_np.c,v 1.5 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1996 Jeffrey Hsu <hsu@freebsd.org>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_mattr_kind_np.c,v 1.4 1999/05/26 00:18:25 d Exp $ + * $FreeBSD: uthread_mattr_kind_np.c,v 1.4 1999/08/28 00:03:39 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -68,7 +69,8 @@ pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { int ret; if (attr == NULL || *attr == NULL || type >= MUTEX_TYPE_MAX) { - return EINVAL; + errno = EINVAL; + ret = -1; } else { (*attr)->m_type = type; ret = 0; diff --git a/lib/libc_r/uthread/uthread_msync.c b/lib/libc_r/uthread/uthread_msync.c index fb7d5a7e86e..3edde1a31d4 100644 --- a/lib/libc_r/uthread/uthread_msync.c +++ b/lib/libc_r/uthread/uthread_msync.c @@ -1,7 +1,7 @@ /* * David Leonard <d@openbsd.org>, 1999. Public Domain. * - * $OpenBSD: uthread_msync.c,v 1.2 1999/06/09 07:16:17 d Exp $ + * $OpenBSD: uthread_msync.c,v 1.3 1999/11/25 07:01:38 d Exp $ */ #include <sys/types.h> @@ -18,13 +18,6 @@ msync(addr, len, flags) { int ret; - /* - * XXX This is quite pointless unless we know how to get the - * file descriptor associated with the memory, and lock it for - * write. The only real use of this wrapper is to guarantee - * a cancellation point, as per the standard. sigh. - */ - /* This is a cancellation point: */ _thread_enter_cancellation_point(); diff --git a/lib/libc_r/uthread/uthread_multi_np.c b/lib/libc_r/uthread/uthread_multi_np.c index 4da9793804c..88c6cbbfddf 100644 --- a/lib/libc_r/uthread/uthread_multi_np.c +++ b/lib/libc_r/uthread/uthread_multi_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_multi_np.c,v 1.3 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_multi_np.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_multi_np.c,v 1.3 1999/08/28 00:03:40 peter Exp $ */ #include <string.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_mutex.c b/lib/libc_r/uthread/uthread_mutex.c index 8cb8760046c..1ddce4f6131 100644 --- a/lib/libc_r/uthread/uthread_mutex.c +++ b/lib/libc_r/uthread/uthread_mutex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex.c,v 1.8 1999/06/09 07:06:54 d Exp $ */ +/* $OpenBSD: uthread_mutex.c,v 1.9 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mutex.c,v 1.16 1999/08/28 00:03:40 peter Exp $ */ #include <stdlib.h> #include <errno.h> @@ -40,6 +41,25 @@ #include <pthread.h> #include "pthread_private.h" +#if defined(_PTHREADS_INVARIANTS) +#define _MUTEX_INIT_LINK(m) do { \ + (m)->m_qe.tqe_prev = NULL; \ + (m)->m_qe.tqe_next = NULL; \ +} while (0) +#define _MUTEX_ASSERT_IS_OWNED(m) do { \ + if ((m)->m_qe.tqe_prev == NULL) \ + PANIC("mutex is not on list"); \ +} while (0) +#define _MUTEX_ASSERT_NOT_OWNED(m) do { \ + if (((m)->m_qe.tqe_prev != NULL) || \ + ((m)->m_qe.tqe_next != NULL)) \ + PANIC("mutex is on list"); \ +} while (0) +#else +#define _MUTEX_INIT_LINK(m) +#define _MUTEX_ASSERT_IS_OWNED(m) +#define _MUTEX_ASSERT_NOT_OWNED(m) +#endif /* * Prototypes @@ -56,6 +76,34 @@ static inline void mutex_queue_enq(pthread_mutex_t, pthread_t); static spinlock_t static_init_lock = _SPINLOCK_INITIALIZER; +/* Reinitialize a mutex to defaults. */ +int +_mutex_reinit(pthread_mutex_t * mutex) +{ + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + else if (*mutex == NULL) + ret = pthread_mutex_init(mutex, NULL); + else { + /* + * Initialize the mutex structure: + */ + (*mutex)->m_type = PTHREAD_MUTEX_DEFAULT; + (*mutex)->m_protocol = PTHREAD_PRIO_NONE; + TAILQ_INIT(&(*mutex)->m_queue); + (*mutex)->m_owner = NULL; + (*mutex)->m_data.m_count = 0; + (*mutex)->m_flags = MUTEX_FLAGS_INITED; + (*mutex)->m_refcount = 0; + (*mutex)->m_prio = 0; + (*mutex)->m_saved_prio = 0; + _MUTEX_INIT_LINK(*mutex); + _SPINLOCK_INIT(&(*mutex)->lock); + } + return (ret); +} int pthread_mutex_init(pthread_mutex_t * mutex, @@ -139,7 +187,8 @@ pthread_mutex_init(pthread_mutex_t * mutex, else pmutex->m_prio = 0; pmutex->m_saved_prio = 0; - _SPINUNLOCK(&pmutex->lock); + _MUTEX_INIT_LINK(pmutex); + memset(&pmutex->lock, 0, sizeof(pmutex->lock)); *mutex = pmutex; } else { free(pmutex); @@ -148,7 +197,7 @@ pthread_mutex_init(pthread_mutex_t * mutex, } } /* Return the completion status: */ - return (ret); + return(ret); } int @@ -178,6 +227,7 @@ pthread_mutex_destroy(pthread_mutex_t * mutex) * Free the memory allocated for the mutex * structure: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); free(*mutex); /* @@ -223,28 +273,24 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) */ else if (*mutex != NULL || (ret = init_static(mutex)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* * If the mutex was statically allocated, properly * initialize the tail queue. */ if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) { TAILQ_INIT(&(*mutex)->m_queue); + _MUTEX_INIT_LINK(*mutex); (*mutex)->m_flags |= MUTEX_FLAGS_INITED; } - /* - * Guard against being preempted by a scheduling signal. - * To support priority inheritence mutexes, we need to - * maintain lists of mutex ownerships for each thread as - * well as lists of waiting threads for each mutex. In - * order to propagate priorities we need to atomically - * walk these lists and cannot rely on a single mutex - * lock to provide protection against modification. - */ - _thread_kern_sched_defer(); - - /* Lock the mutex structure: */ - _SPINLOCK(&(*mutex)->lock); - /* Process according to mutex type: */ switch ((*mutex)->m_protocol) { /* Default POSIX mutex: */ @@ -255,6 +301,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) (*mutex)->m_owner = _thread_run; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -283,6 +330,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) _thread_run->inherited_priority; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -318,6 +366,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) (*mutex)->m_prio; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -338,10 +387,10 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) _SPINUNLOCK(&(*mutex)->lock); /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -362,28 +411,24 @@ pthread_mutex_lock(pthread_mutex_t * mutex) */ else if (*mutex != NULL || (ret = init_static(mutex)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* * If the mutex was statically allocated, properly * initialize the tail queue. */ if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) { TAILQ_INIT(&(*mutex)->m_queue); (*mutex)->m_flags |= MUTEX_FLAGS_INITED; + _MUTEX_INIT_LINK(*mutex); } - /* - * Guard against being preempted by a scheduling signal. - * To support priority inheritence mutexes, we need to - * maintain lists of mutex ownerships for each thread as - * well as lists of waiting threads for each mutex. In - * order to propagate priorities we need to atomically - * walk these lists and cannot rely on a single mutex - * lock to provide protection against modification. - */ - _thread_kern_sched_defer(); - - /* Lock the mutex structure: */ - _SPINLOCK(&(*mutex)->lock); - /* Process according to mutex type: */ switch ((*mutex)->m_protocol) { /* Default POSIX mutex: */ @@ -393,6 +438,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) (*mutex)->m_owner = _thread_run; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); @@ -420,12 +466,6 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Lock the mutex structure again: */ _SPINLOCK(&(*mutex)->lock); - - /* - * This thread is no longer waiting for - * the mutex: - */ - _thread_run->data.mutex = NULL; } break; @@ -450,6 +490,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) (*mutex)->m_prio; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); @@ -482,12 +523,6 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Lock the mutex structure again: */ _SPINLOCK(&(*mutex)->lock); - - /* - * This thread is no longer waiting for - * the mutex: - */ - _thread_run->data.mutex = NULL; } break; @@ -520,6 +555,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) (*mutex)->m_prio; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -557,12 +593,6 @@ pthread_mutex_lock(pthread_mutex_t * mutex) */ ret = _thread_run->error; _thread_run->error = 0; - - /* - * This thread is no longer waiting for - * the mutex: - */ - _thread_run->data.mutex = NULL; } break; @@ -577,10 +607,10 @@ pthread_mutex_lock(pthread_mutex_t * mutex) _SPINUNLOCK(&(*mutex)->lock); /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -684,15 +714,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) ret = EINVAL; } else { /* - * Guard against being preempted by a scheduling signal. - * To support priority inheritence mutexes, we need to - * maintain lists of mutex ownerships for each thread as - * well as lists of waiting threads for each mutex. In - * order to propagate priorities we need to atomically - * walk these lists and cannot rely on a single mutex - * lock to provide protection against modification. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Lock the mutex structure: */ _SPINLOCK(&(*mutex)->lock); @@ -707,8 +732,8 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ if ((*mutex)->m_owner != _thread_run) { /* - * Return a permission error when the thread - * doesn't own the lock: + * Return a permission error when the + * thread doesn't own the lock. */ ret = EPERM; } @@ -724,8 +749,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) (*mutex)->m_data.m_count = 0; /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); /* * Get the next thread from the queue of @@ -739,6 +766,19 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ PTHREAD_NEW_STATE((*mutex)->m_owner, PS_RUNNING); + + /* + * Add the mutex to the threads list of + * owned mutexes: + */ + TAILQ_INSERT_TAIL(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + + /* + * The owner is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; } } break; @@ -751,8 +791,8 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ if ((*mutex)->m_owner != _thread_run) { /* - * Return a permission error when the thread - * doesn't own the lock: + * Return a permission error when the + * thread doesn't own the lock. */ ret = EPERM; } @@ -785,8 +825,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) _thread_run->priority_mutex_count--; /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); /* * Get the next thread from the queue of threads @@ -858,8 +900,8 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ if ((*mutex)->m_owner != _thread_run) { /* - * Return a permission error when the thread - * doesn't own the lock: + * Return a permission error when the + * thread doesn't own the lock. */ ret = EPERM; } @@ -892,8 +934,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) _thread_run->priority_mutex_count--; /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, - (*mutex), m_qe); + (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); /* * Enter a loop to find a waiting thread whose @@ -914,6 +958,11 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) (*mutex)->m_owner->error = EINVAL; PTHREAD_NEW_STATE((*mutex)->m_owner, PS_RUNNING); + /* + * The thread is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; } /* Check for a new owner: */ @@ -979,10 +1028,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) _SPINUNLOCK(&(*mutex)->lock); /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -991,11 +1040,11 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) /* - * This function is called when a change in base priority occurs - * for a thread that is thread holding, or waiting for, a priority - * protection or inheritence mutex. A change in a threads base - * priority can effect changes to active priorities of other threads - * and to the ordering of mutex locking by waiting threads. + * This function is called when a change in base priority occurs for + * a thread that is holding or waiting for a priority protection or + * inheritence mutex. A change in a threads base priority can effect + * changes to active priorities of other threads and to the ordering + * of mutex locking by waiting threads. * * This must be called while thread scheduling is deferred. */ @@ -1232,8 +1281,7 @@ mutex_rescan_owned (pthread_t pthread, pthread_mutex_t mutex) * If this thread is in the priority queue, it must be * removed and reinserted for its new priority. */ - if ((pthread != _thread_run) && - (pthread->state == PS_RUNNING)) { + if (pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) { /* * Remove the thread from the priority queue * before changing its priority: diff --git a/lib/libc_r/uthread/uthread_mutex_prioceiling.c b/lib/libc_r/uthread/uthread_mutex_prioceiling.c index 779c238cfe7..afcd9372d47 100644 --- a/lib/libc_r/uthread/uthread_mutex_prioceiling.c +++ b/lib/libc_r/uthread/uthread_mutex_prioceiling.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex_prioceiling.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_mutex_prioceiling.c,v 1.2 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mutex_prioceiling.c,v 1.3 1999/08/28 00:03:40 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libc_r/uthread/uthread_mutex_protocol.c b/lib/libc_r/uthread/uthread_mutex_protocol.c index fa0b9804d57..6b075ee4f2b 100644 --- a/lib/libc_r/uthread/uthread_mutex_protocol.c +++ b/lib/libc_r/uthread/uthread_mutex_protocol.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex_protocol.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_mutex_protocol.c,v 1.2 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mutex_protocol.c,v 1.3 1999/08/28 00:03:41 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libc_r/uthread/uthread_mutexattr_destroy.c b/lib/libc_r/uthread/uthread_mutexattr_destroy.c index fcb3863bcab..5749e43d35f 100644 --- a/lib/libc_r/uthread/uthread_mutexattr_destroy.c +++ b/lib/libc_r/uthread/uthread_mutexattr_destroy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_mutexattr_destroy.c,v 1.3 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_mutexattr_destroy.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_mutexattr_destroy.c,v 1.4 1999/08/28 00:03:41 peter Exp $ */ #include <stdlib.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_nanosleep.c b/lib/libc_r/uthread/uthread_nanosleep.c index 4e182adfb6c..583e94e983f 100644 --- a/lib/libc_r/uthread/uthread_nanosleep.c +++ b/lib/libc_r/uthread/uthread_nanosleep.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_nanosleep.c,v 1.5 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_nanosleep.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_nanosleep.c,v 1.10 1999/08/28 00:03:41 peter Exp $ */ #include <stdio.h> #include <errno.h> @@ -42,9 +43,8 @@ nanosleep(const struct timespec * time_to_sleep, struct timespec * time_remaining) { int ret = 0; - struct timespec start_time; - struct timespec wakeup_time; struct timespec current_time; + struct timespec current_time1; struct timespec remaining_time; struct timeval tv; @@ -52,20 +52,26 @@ nanosleep(const struct timespec * time_to_sleep, _thread_enter_cancellation_point(); /* Check if the time to sleep is legal: */ - if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000 || time_to_sleep->tv_sec < 0) { + if (time_to_sleep == NULL || time_to_sleep->tv_sec < 0 || + time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec >= 1000000000) { /* Return an EINVAL error : */ errno = EINVAL; ret = -1; } else { /* Get the current time: */ gettimeofday(&tv, NULL); - TIMEVAL_TO_TIMESPEC(&tv, &start_time); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); /* Calculate the time for the current thread to wake up: */ - timespecadd(time_to_sleep, &start_time, &wakeup_time); + _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec; + _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec; - _thread_run->wakeup_time.tv_sec = wakeup_time.tv_sec; - _thread_run->wakeup_time.tv_nsec = wakeup_time.tv_nsec; + /* Check if the nanosecond field has overflowed: */ + if (_thread_run->wakeup_time.tv_nsec >= 1000000000) { + /* Wrap the nanosecond field: */ + _thread_run->wakeup_time.tv_sec += 1; + _thread_run->wakeup_time.tv_nsec -= 1000000000; + } _thread_run->interrupted = 0; /* Reschedule the current thread to sleep: */ @@ -73,15 +79,31 @@ nanosleep(const struct timespec * time_to_sleep, /* Get the current time: */ gettimeofday(&tv, NULL); - TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1); /* Calculate the remaining time to sleep: */ - timespecsub(&wakeup_time, ¤t_time, &remaining_time); + remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec; + remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec; + + /* Check if the nanosecond field has underflowed: */ + if (remaining_time.tv_nsec < 0) { + /* Handle the underflow: */ + remaining_time.tv_sec -= 1; + remaining_time.tv_nsec += 1000000000; + } + + /* Check if the nanosecond field has overflowed: */ + if (remaining_time.tv_nsec >= 1000000000) { + /* Handle the overflow: */ + remaining_time.tv_sec += 1; + remaining_time.tv_nsec -= 1000000000; + } /* Check if the sleep was longer than the required time: */ if (remaining_time.tv_sec < 0) { /* Reset the time left: */ - timespecclear(&remaining_time); + remaining_time.tv_sec = 0; + remaining_time.tv_nsec = 0; } /* Check if the time remaining is to be returned: */ diff --git a/lib/libc_r/uthread/uthread_once.c b/lib/libc_r/uthread/uthread_once.c index 43ce7c39266..27b3a4d594e 100644 --- a/lib/libc_r/uthread/uthread_once.c +++ b/lib/libc_r/uthread/uthread_once.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_once.c,v 1.3 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_once.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_once.c,v 1.3 1999/08/28 00:03:42 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libc_r/uthread/uthread_open.c b/lib/libc_r/uthread/uthread_open.c index bfdcea73091..944e46cd109 100644 --- a/lib/libc_r/uthread/uthread_open.c +++ b/lib/libc_r/uthread/uthread_open.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_open.c,v 1.5 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_open.c,v 1.4 1998/04/29 09:59:07 jb Exp $ - * $OpenBSD: uthread_open.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_open.c,v 1.6 1999/08/28 00:03:42 peter Exp $ * */ #include <stdarg.h> @@ -47,6 +47,7 @@ open(const char *path, int flags,...) { int fd; int mode = 0; + int status; va_list ap; /* This is a cancellation point: */ diff --git a/lib/libc_r/uthread/uthread_pipe.c b/lib/libc_r/uthread/uthread_pipe.c index 65610f01302..6288ab82cbc 100644 --- a/lib/libc_r/uthread/uthread_pipe.c +++ b/lib/libc_r/uthread/uthread_pipe.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_pipe.c,v 1.3 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_pipe.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_pipe.c,v 1.5 1999/08/28 00:03:42 peter Exp $ */ #include <unistd.h> #include <fcntl.h> diff --git a/lib/libc_r/uthread/uthread_poll.c b/lib/libc_r/uthread/uthread_poll.c index da3e98d1547..6392cfcb169 100644 --- a/lib/libc_r/uthread/uthread_poll.c +++ b/lib/libc_r/uthread/uthread_poll.c @@ -1,138 +1,97 @@ +/* $OpenBSD: uthread_poll.c,v 1.3 1999/11/25 07:01:41 d Exp $ */ /* - * David Leonard <d@openbsd.org>, 1999. Public Domain. + * Copyright (c) 1999 Daniel Eischen <eischen@vigrid.com> + * All rights reserved. * - * $OpenBSD: uthread_poll.c,v 1.2 1999/01/08 05:09:22 d Exp $ + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Daniel Eischen. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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: uthread_poll.c,v 1.4 1999/08/30 00:02:08 deischen Exp $ */ #include <unistd.h> #include <errno.h> #include <string.h> +#include <poll.h> #include <sys/types.h> #include <sys/time.h> -#include <poll.h> -#include <stdlib.h> +#include <sys/fcntl.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" -static void -poll_helper(nfds, fds, data) - int nfds; - struct pollfd *fds; - struct pthread_select_data *data; -{ - int maxfd; - int i; - int event; - int fd; - - FD_ZERO(&data->readfds); - FD_ZERO(&data->writefds); - FD_ZERO(&data->exceptfds); - - maxfd = -1; - for (i = 0; i < nfds; i++) { - event = fds[i].events; - fd = fds[i].fd; - - if (event & POLLIN) - FD_SET(fd, &data->readfds); - if (event & POLLOUT) - FD_SET(fd, &data->writefds); - if (fd > maxfd) - maxfd = fd; - } - data->nfds = maxfd + 1; -} -int -poll(fds, nfds, timeout) - struct pollfd fds[]; - int nfds; - int timeout; +int +poll(struct pollfd fds[], int nfds, int timeout) { - fd_set rfds, wfds, rwfds; - int i; - struct timespec ts; - int fd, event; - struct pthread_select_data data; - struct timeval zero_timeout = { 0, 0 }; - int ret; + struct timespec ts; + int numfds = nfds; + int i, ret = 0, found = 0; + struct pthread_poll_data data; - if (timeout < 0) { - /* Wait forever: */ + if (numfds > _thread_dtablesize) { + numfds = _thread_dtablesize; + } + /* Check if a timeout was specified: */ + if (timeout == -1) { + /* Wait for ever: */ _thread_kern_set_timeout(NULL); - } else { + } else if (timeout > 0) { + /* Convert the timeout in msec to a timespec: */ ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000L; + ts.tv_nsec = (timeout % 1000) * 1000; + + /* Set the wake up time: */ _thread_kern_set_timeout(&ts); + } else if (timeout < 0) { + /* a timeout less than zero but not == -1 is invalid */ + errno = EINVAL; + return (-1); } - /* Obtain locks needed: */ - ret = 0; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&rwfds); - for (i = 0; i < nfds; i++) { - event = fds[i].events; - fd = fds[i].fd; - - if (event & (POLLIN|POLLOUT)) - if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds) && - !FD_ISSET(fd, &wfds)) { - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) != 0) - break; - FD_SET(fd, &rwfds); - continue; - } - - if (event & POLLIN) - if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds)) { - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) != 0) - break; - FD_SET(fd, &rfds); - } - - if (event & POLLOUT) - if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &wfds)) { - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) != 0) - break; - FD_SET(fd, &wfds); - } - } + if (((ret = _thread_sys_poll(fds, numfds, 0)) == 0) && (timeout != 0)) { + data.nfds = numfds; + data.fds = fds; - if (ret == 0) { - poll_helper(nfds, fds, &data); - ret = _thread_sys_select(data.nfds, &data.readfds, - &data.writefds, NULL, &zero_timeout); - if (ret == 0) { - poll_helper(nfds, fds, &data); - _thread_run->data.select_data = &data; - _thread_run->interrupted = 0; - _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); - if (_thread_run->interrupted) { - errno = EINTR; - ret = -1; - } + /* + * Clear revents in case of a timeout which leaves fds + * unchanged: + */ + for (i = 0; i < numfds; i++) { + fds[i].revents = 0; } - if (ret >= 0) - ret = _thread_sys_poll(fds, nfds, 0); - } - - /* Clean up the locks: */ - for (i = 0; i < nfds; i++) { - fd = fds[i].fd; - if (FD_ISSET(fd, &rwfds)) { - _FD_UNLOCK(fd, FD_RDWR); - FD_CLR(fd, &rwfds); - } - if (FD_ISSET(fd, &rfds)) { - _FD_UNLOCK(fd, FD_READ); - FD_CLR(fd, &rfds); - } - if (FD_ISSET(fd, &wfds)) { - _FD_UNLOCK(fd, FD_WRITE); - FD_CLR(fd, &wfds); + _thread_run->data.poll_data = &data; + _thread_run->interrupted = 0; + _thread_kern_sched_state(PS_POLL_WAIT, __FILE__, __LINE__); + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + } else { + ret = data.nfds; } } diff --git a/lib/libc_r/uthread/uthread_priority_queue.c b/lib/libc_r/uthread/uthread_priority_queue.c index a5f45ef7064..eef7ed65379 100644 --- a/lib/libc_r/uthread/uthread_priority_queue.c +++ b/lib/libc_r/uthread/uthread_priority_queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_priority_queue.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_priority_queue.c,v 1.2 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_priority_queue.c,v 1.3 1999/08/28 00:03:43 peter Exp $ */ #include <stdlib.h> #include <sys/queue.h> @@ -41,9 +42,51 @@ /* Prototypes: */ static void pq_insert_prio_list(pq_queue_t *pq, int prio); +#if defined(_PTHREADS_INVARIANTS) + +static int _pq_active = 0; + +#define _PQ_IN_SCHEDQ (PTHREAD_FLAGS_IN_PRIOQ | PTHREAD_FLAGS_IN_WAITQ | PTHREAD_FLAGS_IN_WORKQ) + +#define _PQ_SET_ACTIVE() _pq_active = 1 +#define _PQ_CLEAR_ACTIVE() _pq_active = 0 +#define _PQ_ASSERT_ACTIVE(msg) do { \ + if (_pq_active == 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_INACTIVE(msg) do { \ + if (_pq_active != 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_IN_WAITQ(thrd, msg) do { \ + if (((thrd)->flags & PTHREAD_FLAGS_IN_WAITQ) == 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_IN_PRIOQ(thrd, msg) do { \ + if (((thrd)->flags & PTHREAD_FLAGS_IN_PRIOQ) == 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_NOT_QUEUED(thrd, msg) do { \ + if ((thrd)->flags & _PQ_IN_SCHEDQ) \ + PANIC(msg); \ +} while (0) + +#else + +#define _PQ_SET_ACTIVE() +#define _PQ_CLEAR_ACTIVE() +#define _PQ_ASSERT_ACTIVE(msg) +#define _PQ_ASSERT_INACTIVE(msg) +#define _PQ_ASSERT_IN_WAITQ(thrd, msg) +#define _PQ_ASSERT_IN_PRIOQ(thrd, msg) +#define _PQ_ASSERT_NOT_QUEUED(thrd, msg) +#define _PQ_CHECK_PRIO() + +#endif + int -_pq_init(pq_queue_t *pq, int minprio, int maxprio) +_pq_alloc(pq_queue_t *pq, int minprio, int maxprio) { int i, ret = 0; int prioslots = maxprio - minprio + 1; @@ -57,8 +100,26 @@ _pq_init(pq_queue_t *pq, int minprio, int maxprio) ret = -1; else { + /* Remember the queue size: */ + pq->pq_size = prioslots; + + ret = _pq_init(pq); + + } + return (ret); +} + +int +_pq_init(pq_queue_t *pq) +{ + int i, ret = 0; + + if ((pq == NULL) || (pq->pq_lists == NULL)) + ret = -1; + + else { /* Initialize the queue for each priority slot: */ - for (i = 0; i < prioslots; i++) { + for (i = 0; i < pq->pq_size; i++) { TAILQ_INIT(&pq->pq_lists[i].pl_head); pq->pq_lists[i].pl_prio = i; pq->pq_lists[i].pl_queued = 0; @@ -66,9 +127,7 @@ _pq_init(pq_queue_t *pq, int minprio, int maxprio) /* Initialize the priority queue: */ TAILQ_INIT(&pq->pq_queue); - - /* Remember the queue size: */ - pq->pq_size = prioslots; + _PQ_CLEAR_ACTIVE(); } return (ret); } @@ -78,7 +137,27 @@ _pq_remove(pq_queue_t *pq, pthread_t pthread) { int prio = pthread->active_priority; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_remove: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_IN_PRIOQ(pthread, "_pq_remove: Not in priority queue"); + + /* + * Remove this thread from priority list. Note that if + * the priority list becomes empty, it is not removed + * from the priority queue because another thread may be + * added to the priority list (resulting in a needless + * removal/insertion). Priority lists are only removed + * from the priority queue when _pq_first is called. + */ TAILQ_REMOVE(&pq->pq_lists[prio].pl_head, pthread, pqe); + + /* This thread is now longer in the priority queue. */ + pthread->flags &= ~PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); } @@ -87,10 +166,23 @@ _pq_insert_head(pq_queue_t *pq, pthread_t pthread) { int prio = pthread->active_priority; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_insert_head: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, + "_pq_insert_head: Already in priority queue"); + TAILQ_INSERT_HEAD(&pq->pq_lists[prio].pl_head, pthread, pqe); if (pq->pq_lists[prio].pl_queued == 0) /* Insert the list into the priority queue: */ pq_insert_prio_list(pq, prio); + + /* Mark this thread as being in the priority queue. */ + pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); } @@ -99,10 +191,23 @@ _pq_insert_tail(pq_queue_t *pq, pthread_t pthread) { int prio = pthread->active_priority; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_insert_tail: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, + "_pq_insert_tail: Already in priority queue"); + TAILQ_INSERT_TAIL(&pq->pq_lists[prio].pl_head, pthread, pqe); if (pq->pq_lists[prio].pl_queued == 0) /* Insert the list into the priority queue: */ pq_insert_prio_list(pq, prio); + + /* Mark this thread as being in the priority queue. */ + pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); } @@ -112,6 +217,12 @@ _pq_first(pq_queue_t *pq) pq_list_t *pql; pthread_t pthread = NULL; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_first: pq_active"); + _PQ_SET_ACTIVE(); + while (((pql = TAILQ_FIRST(&pq->pq_queue)) != NULL) && (pthread == NULL)) { if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) { @@ -125,6 +236,8 @@ _pq_first(pq_queue_t *pq) pql->pl_queued = 0; } } + + _PQ_CLEAR_ACTIVE(); return (pthread); } @@ -135,9 +248,14 @@ pq_insert_prio_list(pq_queue_t *pq, int prio) pq_list_t *pql; /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_ACTIVE("pq_insert_prio_list: pq_active"); + + /* * The priority queue is in descending priority order. Start at * the beginning of the queue and find the list before which the - * new list should to be inserted. + * new list should be inserted. */ pql = TAILQ_FIRST(&pq->pq_queue); while ((pql != NULL) && (pql->pl_prio > prio)) @@ -153,4 +271,66 @@ pq_insert_prio_list(pq_queue_t *pq, int prio) pq->pq_lists[prio].pl_queued = 1; } +#if defined(_PTHREADS_INVARIANTS) +void +_waitq_insert(pthread_t pthread) +{ + pthread_t tid; + + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_waitq_insert: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, "_waitq_insert: Already in queue"); + + if (pthread->wakeup_time.tv_sec == -1) + TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe); + else { + tid = TAILQ_FIRST(&_waitingq); + while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) && + ((tid->wakeup_time.tv_sec < pthread->wakeup_time.tv_sec) || + ((tid->wakeup_time.tv_sec == pthread->wakeup_time.tv_sec) && + (tid->wakeup_time.tv_nsec <= pthread->wakeup_time.tv_nsec)))) + tid = TAILQ_NEXT(tid, pqe); + if (tid == NULL) + TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe); + else + TAILQ_INSERT_BEFORE(tid, pthread, pqe); + } + pthread->flags |= PTHREAD_FLAGS_IN_WAITQ; + + _PQ_CLEAR_ACTIVE(); +} + +void +_waitq_remove(pthread_t pthread) +{ + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_waitq_remove: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_IN_WAITQ(pthread, "_waitq_remove: Not in queue"); + + TAILQ_REMOVE(&_waitingq, pthread, pqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_WAITQ; + + _PQ_CLEAR_ACTIVE(); +} + +void +_waitq_setactive(void) +{ + _PQ_ASSERT_INACTIVE("_waitq_setactive: pq_active"); + _PQ_SET_ACTIVE(); +} + +void +_waitq_clearactive(void) +{ + _PQ_ASSERT_ACTIVE("_waitq_clearactive: ! pq_active"); + _PQ_CLEAR_ACTIVE(); +} +#endif #endif diff --git a/lib/libc_r/uthread/uthread_queue.c b/lib/libc_r/uthread/uthread_queue.c deleted file mode 100644 index b30b5b9d425..00000000000 --- a/lib/libc_r/uthread/uthread_queue.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by John Birrell. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $OpenBSD: uthread_queue.c,v 1.2 1999/01/06 05:29:25 d Exp $ - */ -#include <stdio.h> -#ifdef _THREAD_SAFE -#include <pthread.h> -#include "pthread_private.h" - -void -_thread_queue_init(struct pthread_queue * queue) -{ - /* Initialise the pointers in the queue structure: */ - queue->q_next = NULL; - queue->q_last = NULL; - queue->q_data = NULL; - return; -} - -void -_thread_queue_enq(struct pthread_queue * queue, struct pthread * thread) -{ - if (queue->q_last) { - queue->q_last->qnxt = thread; - } else { - queue->q_next = thread; - } - queue->q_last = thread; - thread->queue = queue; - thread->qnxt = NULL; - return; -} - -struct pthread * -_thread_queue_get(struct pthread_queue * queue) -{ - /* Return the pointer to the next thread in the queue: */ - return (queue->q_next); -} - -struct pthread * -_thread_queue_deq(struct pthread_queue * queue) -{ - struct pthread *thread = NULL; - - if (queue->q_next) { - thread = queue->q_next; - if (!(queue->q_next = queue->q_next->qnxt)) { - queue->q_last = NULL; - } - thread->queue = NULL; - thread->qnxt = NULL; - } - return (thread); -} - -int -_thread_queue_remove(struct pthread_queue * queue, struct pthread * thread) -{ - struct pthread **current = &(queue->q_next); - struct pthread *prev = NULL; - int ret = -1; - - while (*current) { - if (*current == thread) { - if ((*current)->qnxt) { - *current = (*current)->qnxt; - } else { - queue->q_last = prev; - *current = NULL; - } - ret = 0; - break; - } - prev = *current; - current = &((*current)->qnxt); - } - thread->queue = NULL; - thread->qnxt = NULL; - return (ret); -} - -int -pthread_llist_remove(struct pthread ** llist, struct pthread * thread) -{ - while (*llist) { - if (*llist == thread) { - *llist = thread->qnxt; - return (0); - } - llist = &(*llist)->qnxt; - } - return (-1); -} - -#endif diff --git a/lib/libc_r/uthread/uthread_read.c b/lib/libc_r/uthread/uthread_read.c index 6b9c96352d0..08c12241ed7 100644 --- a/lib/libc_r/uthread/uthread_read.c +++ b/lib/libc_r/uthread/uthread_read.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_read.c,v 1.5 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_read.c,v 1.6 1998/06/10 22:28:43 jb Exp $ - * $OpenBSD: uthread_read.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_read.c,v 1.8 1999/08/28 00:03:43 peter Exp $ * */ #include <sys/types.h> @@ -52,14 +52,11 @@ read(int fd, void *buf, size_t nbytes) _thread_enter_cancellation_point(); /* POSIX says to do just this: */ - if (nbytes == 0) { - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (0); - } + if (nbytes == 0) + ret = 0; /* Lock the file descriptor for read: */ - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + else if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { /* Get the read/write mode type: */ type = _thread_fd_table[fd]->flags & O_ACCMODE; @@ -67,14 +64,11 @@ read(int fd, void *buf, size_t nbytes) if (type != O_RDONLY && type != O_RDWR) { /* File is not open for read: */ errno = EBADF; - _FD_UNLOCK(fd, FD_READ); - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (-1); + ret = -1; } /* Perform a non-blocking read syscall: */ - while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { + else while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_run->data.fd.fd = fd; @@ -101,8 +95,10 @@ read(int fd, void *buf, size_t nbytes) } _FD_UNLOCK(fd, FD_READ); } + /* No longer in a cancellation point: */ _thread_leave_cancellation_point(); + return (ret); } #endif diff --git a/lib/libc_r/uthread/uthread_readv.c b/lib/libc_r/uthread/uthread_readv.c index 293adfe0e53..1ef0ac51ba1 100644 --- a/lib/libc_r/uthread/uthread_readv.c +++ b/lib/libc_r/uthread/uthread_readv.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_readv.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_readv.c,v 1.6 1998/06/10 22:28:44 jb Exp $ - * $OpenBSD: uthread_readv.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_readv.c,v 1.8 1999/08/28 00:03:43 peter Exp $ * */ #include <sys/types.h> diff --git a/lib/libc_r/uthread/uthread_recvfrom.c b/lib/libc_r/uthread/uthread_recvfrom.c index e259eb62138..18c0c6ce8ed 100644 --- a/lib/libc_r/uthread/uthread_recvfrom.c +++ b/lib/libc_r/uthread/uthread_recvfrom.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_recvfrom.c,v 1.4 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_recvfrom.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_recvfrom.c,v 1.5 1999/08/28 00:03:44 peter Exp $ */ #include <errno.h> #include <sys/types.h> @@ -40,8 +41,7 @@ #include "pthread_private.h" ssize_t -recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, - socklen_t *from_len) +recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, socklen_t *from_len) { int ret; diff --git a/lib/libc_r/uthread/uthread_recvmsg.c b/lib/libc_r/uthread/uthread_recvmsg.c index 0b99b11c78d..c92b7a1c420 100644 --- a/lib/libc_r/uthread/uthread_recvmsg.c +++ b/lib/libc_r/uthread/uthread_recvmsg.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_recvmsg.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_recvmsg.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_recvmsg.c,v 1.4 1999/08/28 00:03:44 peter Exp $ */ #include <errno.h> #include <sys/types.h> diff --git a/lib/libc_r/uthread/uthread_resume_np.c b/lib/libc_r/uthread/uthread_resume_np.c index e4be286bde6..8816f76e4c8 100644 --- a/lib/libc_r/uthread/uthread_resume_np.c +++ b/lib/libc_r/uthread/uthread_resume_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_resume_np.c,v 1.4 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_resume_np.c,v 1.3 1999/05/26 00:18:25 d Exp $ + * $FreeBSD: uthread_resume_np.c,v 1.7 1999/08/28 00:03:44 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -47,20 +48,19 @@ pthread_resume_np(pthread_t thread) /* The thread exists. Is it suspended? */ if (thread->state != PS_SUSPENDED) { /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues + * from access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Allow the thread to run. */ PTHREAD_NEW_STATE(thread,PS_RUNNING); /* - * Reenable preemption and yield if a scheduling - * signal occurred while in the critical region. + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } } return(ret); diff --git a/lib/libc_r/uthread/uthread_rwlock.c b/lib/libc_r/uthread/uthread_rwlock.c index e9ca20b00fa..259f1898402 100644 --- a/lib/libc_r/uthread/uthread_rwlock.c +++ b/lib/libc_r/uthread/uthread_rwlock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_rwlock.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /*- * Copyright (c) 1998 Alex Nash * All rights reserved. @@ -23,8 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_rwlock.c,v 1.3 1998/09/07 21:07:59 alex Exp $ - * $OpenBSD: uthread_rwlock.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_rwlock.c,v 1.4 1999/08/28 00:03:45 peter Exp $ */ #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_rwlockattr.c b/lib/libc_r/uthread/uthread_rwlockattr.c index 41a9d89333c..8e7f7a5e1d0 100644 --- a/lib/libc_r/uthread/uthread_rwlockattr.c +++ b/lib/libc_r/uthread/uthread_rwlockattr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_rwlockattr.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /*- * Copyright (c) 1998 Alex Nash * All rights reserved. @@ -23,8 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_rwlockattr.c,v 1.2 1998/09/07 19:23:55 alex Exp $ - * $OpenBSD: uthread_rwlockattr.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_rwlockattr.c,v 1.3 1999/08/28 00:03:45 peter Exp $ */ #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_select.c b/lib/libc_r/uthread/uthread_select.c index dd9714e7b3e..a7cd5c3d260 100644 --- a/lib/libc_r/uthread/uthread_select.c +++ b/lib/libc_r/uthread/uthread_select.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_select.c,v 1.4 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,13 +30,17 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_select.c,v 1.3 1999/05/26 00:18:25 d Exp $ + * $FreeBSD: uthread_select.c,v 1.13 1999/08/30 00:02:08 deischen Exp $ */ #include <unistd.h> #include <errno.h> +#include <poll.h> +#include <stdlib.h> #include <string.h> +#include <sys/param.h> #include <sys/types.h> #include <sys/time.h> +#include <sys/fcntl.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -44,18 +49,22 @@ int select(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) { - fd_set read_locks, write_locks, rdwr_locks; struct timespec ts; - struct timeval zero_timeout = {0, 0}; - int i, ret = 0, got_all_locks = 1; - int f_wait = 1; - struct pthread_select_data data; + int i, ret = 0, f_wait = 1; + int pfd_index, got_one = 0, fd_count = 0; + struct pthread_poll_data data; if (numfds > _thread_dtablesize) { numfds = _thread_dtablesize; } /* Check if a timeout was specified: */ if (timeout) { + if (timeout->tv_sec < 0 || + timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) { + errno = EINVAL; + return (-1); + } + /* Convert the timeval to a timespec: */ TIMEVAL_TO_TIMESPEC(timeout, &ts); @@ -68,112 +77,129 @@ select(int numfds, fd_set * readfds, fd_set * writefds, _thread_kern_set_timeout(NULL); } - FD_ZERO(&read_locks); - FD_ZERO(&write_locks); - FD_ZERO(&rdwr_locks); - - /* lock readfds */ + /* Count the number of file descriptors to be polled: */ if (readfds || writefds || exceptfds) { for (i = 0; i < numfds; i++) { - if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) { - if (writefds && FD_ISSET(i, writefds)) { - if ((ret = _FD_LOCK(i, FD_RDWR, NULL)) != 0) { - got_all_locks = 0; - break; - } - FD_SET(i, &rdwr_locks); - } else { - if ((ret = _FD_LOCK(i, FD_READ, NULL)) != 0) { - got_all_locks = 0; - break; - } - FD_SET(i, &read_locks); - } - } else { - if (writefds && FD_ISSET(i, writefds)) { - if ((ret = _FD_LOCK(i, FD_WRITE, NULL)) != 0) { - got_all_locks = 0; - break; - } - FD_SET(i, &write_locks); - } + if ((readfds && FD_ISSET(i, readfds)) || + (exceptfds && FD_ISSET(i, exceptfds)) || + (writefds && FD_ISSET(i, writefds))) { + fd_count++; } } } - if (got_all_locks) { - data.nfds = numfds; - FD_ZERO(&data.readfds); - FD_ZERO(&data.writefds); - FD_ZERO(&data.exceptfds); - if (readfds != NULL) { - memcpy(&data.readfds, readfds, sizeof(data.readfds)); - } - if (writefds != NULL) { - memcpy(&data.writefds, writefds, sizeof(data.writefds)); + + /* + * Allocate memory for poll data if it hasn't already been + * allocated or if previously allocated memory is insufficient. + */ + if ((_thread_run->poll_data.fds == NULL) || + (_thread_run->poll_data.nfds < fd_count)) { + data.fds = (struct pollfd *) realloc(_thread_run->poll_data.fds, + sizeof(struct pollfd) * MAX(128, fd_count)); + if (data.fds == NULL) { + errno = ENOMEM; + ret = -1; } - if (exceptfds != NULL) { - memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds)); + else { + /* + * Note that the threads poll data always + * indicates what is allocated, not what is + * currently being polled. + */ + _thread_run->poll_data.fds = data.fds; + _thread_run->poll_data.nfds = MAX(128, fd_count); } - if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0 && f_wait) { - data.nfds = numfds; - FD_ZERO(&data.readfds); - FD_ZERO(&data.writefds); - FD_ZERO(&data.exceptfds); - if (readfds != NULL) { - memcpy(&data.readfds, readfds, sizeof(data.readfds)); + } + if (ret == 0) { + /* Setup the wait data. */ + data.fds = _thread_run->poll_data.fds; + data.nfds = fd_count; + + /* + * Setup the array of pollfds. Optimize this by + * running the loop in reverse and stopping when + * the number of selected file descriptors is reached. + */ + for (i = numfds - 1, pfd_index = fd_count - 1; + (i >= 0) && (pfd_index >= 0); i--) { + data.fds[pfd_index].events = 0; + if (readfds && FD_ISSET(i, readfds)) { + data.fds[pfd_index].events = POLLRDNORM; } - if (writefds != NULL) { - memcpy(&data.writefds, writefds, sizeof(data.writefds)); + if (exceptfds && FD_ISSET(i, exceptfds)) { + data.fds[pfd_index].events |= POLLRDBAND; } - if (exceptfds != NULL) { - memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds)); + if (writefds && FD_ISSET(i, writefds)) { + data.fds[pfd_index].events |= POLLWRNORM; + } + if (data.fds[pfd_index].events != 0) { + /* + * Set the file descriptor to be polled and + * clear revents in case of a timeout which + * leaves fds unchanged: + */ + data.fds[pfd_index].fd = i; + data.fds[pfd_index].revents = 0; + pfd_index--; } - _thread_run->data.select_data = &data; + } + if (((ret = _thread_sys_poll(data.fds, data.nfds, 0)) == 0) && + (f_wait != 0)) { + _thread_run->data.poll_data = &data; _thread_run->interrupted = 0; _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); if (_thread_run->interrupted) { errno = EINTR; + data.nfds = 0; ret = -1; } else ret = data.nfds; } } - /* clean up the locks */ - for (i = 0; i < numfds; i++) - if (FD_ISSET(i, &read_locks)) - _FD_UNLOCK(i, FD_READ); - for (i = 0; i < numfds; i++) - if (FD_ISSET(i, &rdwr_locks)) - _FD_UNLOCK(i, FD_RDWR); - for (i = 0; i < numfds; i++) - if (FD_ISSET(i, &write_locks)) - _FD_UNLOCK(i, FD_WRITE); if (ret >= 0) { - if (readfds != NULL) { - for (i = 0; i < numfds; i++) { - if (FD_ISSET(i, readfds) && - !FD_ISSET(i, &data.readfds)) { - FD_CLR(i, readfds); + numfds = 0; + for (i = 0; i < fd_count; i++) { + /* + * Check the results of the poll and clear + * this file descriptor from the fdset if + * the requested event wasn't ready. + */ + got_one = 0; + if (readfds != NULL) { + if (FD_ISSET(data.fds[i].fd, readfds)) { + if (data.fds[i].revents & (POLLIN | + POLLRDNORM)) + got_one = 1; + else + FD_CLR(data.fds[i].fd, readfds); } } - } - if (writefds != NULL) { - for (i = 0; i < numfds; i++) { - if (FD_ISSET(i, writefds) && - !FD_ISSET(i, &data.writefds)) { - FD_CLR(i, writefds); + if (writefds != NULL) { + if (FD_ISSET(data.fds[i].fd, writefds)) { + if (data.fds[i].revents & (POLLOUT | + POLLWRNORM | POLLWRBAND)) + got_one = 1; + else + FD_CLR(data.fds[i].fd, + writefds); } } - } - if (exceptfds != NULL) { - for (i = 0; i < numfds; i++) { - if (FD_ISSET(i, exceptfds) && - !FD_ISSET(i, &data.exceptfds)) { - FD_CLR(i, exceptfds); + if (exceptfds != NULL) { + if (FD_ISSET(data.fds[i].fd, exceptfds)) { + if (data.fds[i].revents & (POLLRDBAND | + POLLPRI | POLLHUP | POLLERR | + POLLNVAL)) + got_one = 1; + else + FD_CLR(data.fds[i].fd, + exceptfds); } } + if (got_one) + numfds++; } + ret = numfds; } return (ret); diff --git a/lib/libc_r/uthread/uthread_self.c b/lib/libc_r/uthread/uthread_self.c index d9a5b26092b..0ff4f7f3ba6 100644 --- a/lib/libc_r/uthread/uthread_self.c +++ b/lib/libc_r/uthread/uthread_self.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_self.c,v 1.3 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_self.c,v 1.2 1999/01/10 23:10:26 d Exp $ + * $FreeBSD: uthread_self.c,v 1.3 1999/08/28 00:03:46 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libc_r/uthread/uthread_sendmsg.c b/lib/libc_r/uthread/uthread_sendmsg.c index db1b49d2016..36bc6a62439 100644 --- a/lib/libc_r/uthread/uthread_sendmsg.c +++ b/lib/libc_r/uthread/uthread_sendmsg.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sendmsg.c,v 1.3 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sendmsg.c,v 1.2 1999/01/06 05:29:26 d Exp $ + * $FreeBSD: uthread_sendmsg.c,v 1.4 1999/08/28 00:03:46 peter Exp $ */ #include <errno.h> #include <sys/types.h> diff --git a/lib/libc_r/uthread/uthread_sendto.c b/lib/libc_r/uthread/uthread_sendto.c index 8eacbd509d9..b0a8c059a1e 100644 --- a/lib/libc_r/uthread/uthread_sendto.c +++ b/lib/libc_r/uthread/uthread_sendto.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sendto.c,v 1.4 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sendto.c,v 1.3 1999/02/16 16:41:13 millert Exp $ + * $FreeBSD: uthread_sendto.c,v 1.5 1999/08/28 00:03:46 peter Exp $ */ #include <errno.h> #include <sys/types.h> @@ -40,7 +41,7 @@ #include "pthread_private.h" ssize_t -sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t to_len) +sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * to, socklen_t to_len) { int ret; diff --git a/lib/libc_r/uthread/uthread_seterrno.c b/lib/libc_r/uthread/uthread_seterrno.c index e63e9ba8d4d..41425e5b134 100644 --- a/lib/libc_r/uthread/uthread_seterrno.c +++ b/lib/libc_r/uthread/uthread_seterrno.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_seterrno.c,v 1.3 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_seterrno.c,v 1.2 1999/01/06 05:29:26 d Exp $ + * $FreeBSD: uthread_seterrno.c,v 1.4 1999/08/28 00:03:46 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libc_r/uthread/uthread_setprio.c b/lib/libc_r/uthread/uthread_setprio.c index 575eb62da2c..b0be80a20ad 100644 --- a/lib/libc_r/uthread/uthread_setprio.c +++ b/lib/libc_r/uthread/uthread_setprio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_setprio.c,v 1.4 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_setprio.c,v 1.5 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_setprio.c,v 1.6 1999/08/28 00:03:47 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_setschedparam.c b/lib/libc_r/uthread/uthread_setschedparam.c index 0024460c003..26e1b61d017 100644 --- a/lib/libc_r/uthread/uthread_setschedparam.c +++ b/lib/libc_r/uthread/uthread_setschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_setschedparam.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_setschedparam.c,v 1.2 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_setschedparam.c,v 1.3 1999/08/28 00:03:47 peter Exp $ */ #include <errno.h> #include <sys/param.h> @@ -51,10 +52,10 @@ pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *p /* Find the thread in the list of active threads: */ else if ((ret = _find_thread(pthread)) == 0) { /* - * Guard against being preempted by a scheduling - * signal: + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); if (param->sched_priority != pthread->base_priority) { /* @@ -62,8 +63,7 @@ pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *p * queue before any adjustments are made to its * active priority: */ - if ((pthread != _thread_run) && - (pthread->state == PS_RUNNING)) { + if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0) { in_readyq = 1; old_prio = pthread->active_priority; PTHREAD_PRIOQ_REMOVE(pthread); @@ -104,10 +104,10 @@ pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *p pthread->attr.sched_policy = policy; /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } return(ret); } diff --git a/lib/libc_r/uthread/uthread_setsockopt.c b/lib/libc_r/uthread/uthread_setsockopt.c index 67be1fe195d..77cda0a65c1 100644 --- a/lib/libc_r/uthread/uthread_setsockopt.c +++ b/lib/libc_r/uthread/uthread_setsockopt.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_setsockopt.c,v 1.4 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_setsockopt.c,v 1.3 1999/02/16 16:40:01 deraadt Exp $ + * $FreeBSD: uthread_setsockopt.c,v 1.5 1999/08/28 00:03:47 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libc_r/uthread/uthread_shutdown.c b/lib/libc_r/uthread/uthread_shutdown.c index 4923d34cec4..991fb2c932d 100644 --- a/lib/libc_r/uthread/uthread_shutdown.c +++ b/lib/libc_r/uthread/uthread_shutdown.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_shutdown.c,v 1.3 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_shutdown.c,v 1.2 1999/01/06 05:29:27 d Exp $ + * $FreeBSD: uthread_shutdown.c,v 1.6 1999/08/28 00:03:48 peter Exp $ */ #include <errno.h> #include <sys/types.h> diff --git a/lib/libc_r/uthread/uthread_sig.c b/lib/libc_r/uthread/uthread_sig.c index 1d32d376fe0..465d5d06e99 100644 --- a/lib/libc_r/uthread/uthread_sig.c +++ b/lib/libc_r/uthread/uthread_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sig.c,v 1.5 1999/05/26 00:18:26 d Exp $ */ +/* $OpenBSD: uthread_sig.c,v 1.6 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -21,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_sig.c,v 1.20 1999/09/29 15:18:39 marcel Exp $ */ #include <signal.h> #include <fcntl.h> @@ -39,115 +40,51 @@ #include <pthread.h> #include "pthread_private.h" -/* - * State change macro for signal handler: - */ -#define PTHREAD_SIG_NEW_STATE(thrd, newstate) { \ - if ((_thread_run->sched_defer_count == 0) && \ - (_thread_kern_in_sched == 0)) { \ - PTHREAD_NEW_STATE(thrd, newstate); \ - } else { \ - _waitingq_check_reqd = 1; \ - PTHREAD_SET_STATE(thrd, newstate); \ - } \ -} - /* Static variables: */ -static int volatile yield_on_unlock_thread = 0; -static spinlock_t thread_link_list_lock = _SPINLOCK_INITIALIZER; - -int _thread_sig_statistics[NSIG]; +static spinlock_t signal_lock = _SPINLOCK_INITIALIZER; +unsigned int pending_sigs[NSIG]; +unsigned int handled_sigs[NSIG]; +int volatile check_pending = 0; -/* Lock the thread list: */ +/* Initialize signal handling facility: */ void -_lock_thread_list() +_thread_sig_init(void) { - /* Lock the thread list: */ - _SPINLOCK(&thread_link_list_lock); -} - -/* Lock the thread list: */ -void -_unlock_thread_list() -{ - /* Unlock the thread list: */ - _SPINUNLOCK(&thread_link_list_lock); - - /* - * Check if a scheduler interrupt occurred while the thread - * list was locked: - */ - if (yield_on_unlock_thread) { - /* Reset the interrupt flag: */ - yield_on_unlock_thread = 0; + int i; - /* This thread has overstayed it's welcome: */ - sched_yield(); + /* Clear pending and handled signal counts: */ + for (i = 1; i < NSIG; i++) { + pending_sigs[i - 1] = 0; + handled_sigs[i - 1] = 0; } + + /* Clear the lock: */ + signal_lock.access_lock = 0; } void _thread_sig_handler(int sig, int code, struct sigcontext * scp) { - char c; - int i; - pthread_t pthread; - - /* - * Record the number of times this signal has been received - */ - _thread_sig_statistics[sig]++; - - /* - * Check if the pthread kernel has unblocked signals (or is about to) - * and was on its way into a _select when the current - * signal interrupted it: - */ - if (_thread_kern_in_select) { - /* Cast the signal number to a character variable: */ - c = sig; - - /* - * Write the signal number to the kernel pipe so that it will - * be ready to read when this signal handler returns. This - * means that the _select call will complete - * immediately. - */ - _thread_sys_write(_thread_kern_pipe[1], &c, 1); - } - - /* Check if the signal requires a dump of thread information: */ - if (sig == SIGINFO) - /* Dump thread information to file: */ - _thread_dump_info(); + char c; + int i; /* Check if an interval timer signal: */ - else if (sig == _SCHED_SIGNAL) { - /* Check if the scheduler interrupt has come at an - * unfortunate time which one of the threads is - * modifying the thread list: - */ - if (_atomic_is_locked(&thread_link_list_lock.access_lock)) + if (sig == _SCHED_SIGNAL) { + if (_thread_kern_in_sched != 0) { /* - * Set a flag so that the thread that has - * the lock yields when it unlocks the - * thread list: + * The scheduler is already running; ignore this + * signal. */ - yield_on_unlock_thread = 1; - + } /* * Check if the scheduler interrupt has come when * the currently running thread has deferred thread - * scheduling. + * signals. */ - else if (_thread_run->sched_defer_count) - _thread_run->yield_on_sched_undefer = 1; + else if (_thread_run->sig_defer_count > 0) + _thread_run->yield_on_sig_undefer = 1; - /* - * Check if the kernel has not been interrupted while - * executing scheduler code: - */ - else if (!_thread_kern_in_sched) { + else { /* * Schedule the next thread. This function is not * expected to return because it will do a longjmp @@ -161,6 +98,72 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) */ PANIC("Returned to signal function from scheduler"); } + } + /* + * Check if the kernel has been interrupted while the scheduler + * is accessing the scheduling queues or if there is a currently + * running thread that has deferred signals. + */ + else if ((_queue_signals != 0) || ((_thread_kern_in_sched == 0) && + (_thread_run->sig_defer_count > 0))) { + /* Cast the signal number to a character variable: */ + c = sig; + + /* + * Write the signal number to the kernel pipe so that it will + * be ready to read when this signal handler returns. + */ + _thread_sys_write(_thread_kern_pipe[1], &c, 1); + + /* Indicate that there are queued signals in the pipe. */ + _sigq_check_reqd = 1; + } + else { + if (_atomic_lock(&signal_lock.access_lock)) { + /* There is another signal handler running: */ + pending_sigs[sig - 1]++; + check_pending = 1; + } + else { + /* It's safe to handle the signal now. */ + _thread_sig_handle(sig, scp); + + /* Reset the pending and handled count back to 0: */ + pending_sigs[sig - 1] = 0; + handled_sigs[sig - 1] = 0; + + signal_lock.access_lock = 0; + } + + /* Enter a loop to process pending signals: */ + while ((check_pending != 0) && + (_atomic_lock(&signal_lock.access_lock) == 0)) { + check_pending = 0; + for (i = 1; i < NSIG; i++) { + if (pending_sigs[i - 1] > handled_sigs[i - 1]) + _thread_sig_handle(i, scp); + } + signal_lock.access_lock = 0; + } + } +} + +void +_thread_sig_handle(int sig, struct sigcontext * scp) +{ + int i; + pthread_t pthread, pthread_next; + + /* Check if the signal requires a dump of thread information: */ + if (sig == SIGINFO) + /* Dump thread information to file: */ + _thread_dump_info(); + + /* Check if an interval timer signal: */ + else if (sig == _SCHED_SIGNAL) { + /* + * This shouldn't ever occur (should this panic?). + */ } else { /* Check if a child has terminated: */ if (sig == SIGCHLD) { @@ -192,10 +195,9 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) * Enter a loop to discard pending SIGCONT * signals: */ - for (pthread = _thread_link_list; - pthread != NULL; - pthread = pthread->nxt) + TAILQ_FOREACH(pthread, &_thread_list, tle) { sigdelset(&pthread->sigpend,SIGCONT); + } } /* @@ -205,11 +207,18 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) * if there are multiple waiters, we'll give it to the * first one we find. */ - TAILQ_FOREACH(pthread, &_waitingq, pqe) { + for (pthread = TAILQ_FIRST(&_waitingq); + pthread != NULL; pthread = pthread_next) { + /* + * Grab the next thread before possibly destroying + * the link entry. + */ + pthread_next = TAILQ_NEXT(pthread, pqe); + if ((pthread->state == PS_SIGWAIT) && sigismember(pthread->data.sigwait, sig)) { /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; @@ -228,18 +237,26 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) * Enter a loop to process each thread in the linked * list: */ - for (pthread = _thread_link_list; pthread != NULL; - pthread = pthread->nxt) { + TAILQ_FOREACH(pthread, &_thread_list, tle) { pthread_t pthread_saved = _thread_run; + /* Current thread inside critical region? */ + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count++; + _thread_run = pthread; _thread_signal(pthread,sig); + /* * Dispatch pending signals to the * running thread: */ _dispatch_signals(); _thread_run = pthread_saved; + + /* Current thread inside critical region? */ + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count--; } } @@ -292,7 +309,7 @@ _thread_signal(pthread_t pthread, int sig) pthread->interrupted = 1; /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; @@ -304,6 +321,7 @@ _thread_signal(pthread_t pthread, int sig) */ case PS_FDR_WAIT: case PS_FDW_WAIT: + case PS_POLL_WAIT: case PS_SLEEP_WAIT: case PS_SELECT_WAIT: if (sig != SIGCHLD || @@ -311,8 +329,11 @@ _thread_signal(pthread_t pthread, int sig) /* Flag the operation as interrupted: */ pthread->interrupted = 1; + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; @@ -327,7 +348,7 @@ _thread_signal(pthread_t pthread, int sig) if (!sigismember(&pthread->sigmask, sig) && _thread_sigact[sig - 1].sa_handler != SIG_DFL) { /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; diff --git a/lib/libc_r/uthread/uthread_sigaction.c b/lib/libc_r/uthread/uthread_sigaction.c index 6d709a8803f..de0aaeb7bfe 100644 --- a/lib/libc_r/uthread/uthread_sigaction.c +++ b/lib/libc_r/uthread/uthread_sigaction.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigaction.c,v 1.5 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigaction.c,v 1.4 1999/05/26 00:18:26 d Exp $ + * $FreeBSD: uthread_sigaction.c,v 1.8 1999/08/28 00:03:48 peter Exp $ */ #include <signal.h> #include <errno.h> @@ -78,6 +79,9 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact) gact.sa_mask = act->sa_mask; gact.sa_flags = 0; + /* Ensure the scheduling signal is masked: */ + sigaddset(&gact.sa_mask, _SCHED_SIGNAL); + /* * Check if the signal handler is being set to * the default or ignore handlers: diff --git a/lib/libc_r/uthread/uthread_sigaltstack.c b/lib/libc_r/uthread/uthread_sigaltstack.c index 9a1f9614542..fff62da3be2 100644 --- a/lib/libc_r/uthread/uthread_sigaltstack.c +++ b/lib/libc_r/uthread/uthread_sigaltstack.c @@ -1,6 +1,4 @@ -/* - * $OpenBSD: uthread_sigaltstack.c,v 1.1 1998/11/09 03:13:20 d Exp $ - */ +/* $OpenBSD: uthread_sigaltstack.c,v 1.2 1999/11/25 07:01:44 d Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_sigblock.c b/lib/libc_r/uthread/uthread_sigblock.c index 5b317d01472..dd08126ce70 100644 --- a/lib/libc_r/uthread/uthread_sigblock.c +++ b/lib/libc_r/uthread/uthread_sigblock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigblock.c,v 1.3 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigblock.c,v 1.2 1999/01/06 05:29:27 d Exp $ + * $FreeBSD: uthread_sigblock.c,v 1.4 1999/08/28 00:03:49 peter Exp $ */ #include <signal.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_sigmask.c b/lib/libc_r/uthread/uthread_sigmask.c index bdaf30e09f8..6de570535e4 100644 --- a/lib/libc_r/uthread/uthread_sigmask.c +++ b/lib/libc_r/uthread/uthread_sigmask.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigmask.c,v 1.3 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigmask.c,v 1.2 1999/01/06 05:29:27 d Exp $ + * $FreeBSD: uthread_sigmask.c,v 1.5 1999/09/29 15:18:40 marcel Exp $ */ #include <errno.h> #include <signal.h> diff --git a/lib/libc_r/uthread/uthread_signal.c b/lib/libc_r/uthread/uthread_signal.c index 2e1f3d21f60..bd9b488b3d0 100644 --- a/lib/libc_r/uthread/uthread_signal.c +++ b/lib/libc_r/uthread/uthread_signal.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_signal.c,v 1.4 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_signal.c,v 1.3 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_signal.c,v 1.4 1999/08/28 00:03:49 peter Exp $ */ #include <signal.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_sigpending.c b/lib/libc_r/uthread/uthread_sigpending.c index 2daf3159b59..9921ee5a237 100644 --- a/lib/libc_r/uthread/uthread_sigpending.c +++ b/lib/libc_r/uthread/uthread_sigpending.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sigpending.c,v 1.1 1999/05/26 00:18:26 d Exp $ */ +/* $OpenBSD: uthread_sigpending.c,v 1.2 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1999 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -21,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_sigpending.c,v 1.3 1999/08/28 00:03:50 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_sigprocmask.c b/lib/libc_r/uthread/uthread_sigprocmask.c index c3f0b1dda16..28d4c3b1efe 100644 --- a/lib/libc_r/uthread/uthread_sigprocmask.c +++ b/lib/libc_r/uthread/uthread_sigprocmask.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigprocmask.c,v 1.3 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigprocmask.c,v 1.2 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_sigprocmask.c,v 1.6 1999/09/29 15:18:40 marcel Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_sigsetmask.c b/lib/libc_r/uthread/uthread_sigsetmask.c index 1f416551142..878efe36add 100644 --- a/lib/libc_r/uthread/uthread_sigsetmask.c +++ b/lib/libc_r/uthread/uthread_sigsetmask.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigsetmask.c,v 1.3 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigsetmask.c,v 1.2 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_sigsetmask.c,v 1.4 1999/08/28 00:03:50 peter Exp $ */ #include <signal.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_sigsuspend.c b/lib/libc_r/uthread/uthread_sigsuspend.c index e0035c0fa1a..bd7e2094bd9 100644 --- a/lib/libc_r/uthread/uthread_sigsuspend.c +++ b/lib/libc_r/uthread/uthread_sigsuspend.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigsuspend.c,v 1.4 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigsuspend.c,v 1.3 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_sigsuspend.c,v 1.7 1999/08/28 00:03:50 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libc_r/uthread/uthread_sigwait.c b/lib/libc_r/uthread/uthread_sigwait.c index 00cf99ef20b..84db32d0470 100644 --- a/lib/libc_r/uthread/uthread_sigwait.c +++ b/lib/libc_r/uthread/uthread_sigwait.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigwait.c,v 1.7 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigwait.c,v 1.6 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_sigwait.c,v 1.10 1999/09/30 14:51:31 marcel Exp $ */ #include <signal.h> #include <errno.h> @@ -42,7 +43,7 @@ sigwait(const sigset_t * set, int *sig) { int ret = 0; int i; - sigset_t tempset; + sigset_t tempset, waitset; struct sigaction act; /* This is a cancellation point: */ @@ -55,17 +56,23 @@ sigwait(const sigset_t * set, int *sig) act.sa_flags = SA_RESTART; act.sa_mask = *set; + /* Ensure the scheduling signal is masked: */ + sigaddset(&act.sa_mask, _SCHED_SIGNAL); + /* - * These signals can't be waited on. + * Initialize the set of signals that will be waited on: */ - sigdelset(&act.sa_mask, SIGKILL); - sigdelset(&act.sa_mask, SIGSTOP); - sigdelset(&act.sa_mask, _SCHED_SIGNAL); - sigdelset(&act.sa_mask, SIGCHLD); - sigdelset(&act.sa_mask, SIGINFO); + waitset = *set; + + /* These signals can't be waited on. */ + sigdelset(&waitset, SIGKILL); + sigdelset(&waitset, SIGSTOP); + sigdelset(&waitset, _SCHED_SIGNAL); + sigdelset(&waitset, SIGCHLD); + sigdelset(&waitset, SIGINFO); /* Check to see if a pending signal is in the wait mask. */ - if ((tempset = (_thread_run->sigpend & act.sa_mask))) { + if (tempset = (_thread_run->sigpend & waitset)) { /* Enter a loop to find a pending signal: */ for (i = 1; i < NSIG; i++) { if (sigismember (&tempset, i)) @@ -80,6 +87,7 @@ sigwait(const sigset_t * set, int *sig) /* No longer in a cancellation point: */ _thread_leave_cancellation_point(); + return (0); } @@ -87,17 +95,17 @@ sigwait(const sigset_t * set, int *sig) * Enter a loop to find the signals that are SIG_DFL. For * these signals we must install a dummy signal handler in * order for the kernel to pass them in to us. POSIX says - * that the application must explicitly install a dummy + * that the _application_ must explicitly install a dummy * handler for signals that are SIG_IGN in order to sigwait * on them. Note that SIG_IGN signals are left in the * mask because a subsequent sigaction could enable an * ignored signal. */ for (i = 1; i < NSIG; i++) { - if (sigismember(&act.sa_mask, i)) { - if (_thread_sigact[i - 1].sa_handler == SIG_DFL) - if (_thread_sys_sigaction(i,&act,NULL) != 0) - ret = -1; + if (sigismember(&waitset, i) && + (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { + if (_thread_sys_sigaction(i,&act,NULL) != 0) + ret = -1; } } if (ret == 0) { @@ -107,7 +115,7 @@ sigwait(const sigset_t * set, int *sig) * mask is independent of the threads signal mask * and requires separate storage. */ - _thread_run->data.sigwait = &act.sa_mask; + _thread_run->data.sigwait = &waitset; /* Wait for a signal: */ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); @@ -125,7 +133,7 @@ sigwait(const sigset_t * set, int *sig) /* Restore the sigactions: */ act.sa_handler = SIG_DFL; for (i = 1; i < NSIG; i++) { - if (sigismember(&act.sa_mask, i) && + if (sigismember(&waitset, i) && (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { if (_thread_sys_sigaction(i,&act,NULL) != 0) ret = -1; diff --git a/lib/libc_r/uthread/uthread_single_np.c b/lib/libc_r/uthread/uthread_single_np.c index 39c90837653..84208893b16 100644 --- a/lib/libc_r/uthread/uthread_single_np.c +++ b/lib/libc_r/uthread/uthread_single_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_single_np.c,v 1.3 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_single_np.c,v 1.2 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_single_np.c,v 1.3 1999/08/28 00:03:51 peter Exp $ */ #include <string.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_socket.c b/lib/libc_r/uthread/uthread_socket.c index ea848d3c144..b4a96b8185a 100644 --- a/lib/libc_r/uthread/uthread_socket.c +++ b/lib/libc_r/uthread/uthread_socket.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_socket.c,v 1.3 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_socket.c,v 1.2 1999/01/06 05:29:29 d Exp $ + * $FreeBSD: uthread_socket.c,v 1.5 1999/08/28 00:03:51 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libc_r/uthread/uthread_socketpair.c b/lib/libc_r/uthread/uthread_socketpair.c index d78eaad0197..482a3d71b6c 100644 --- a/lib/libc_r/uthread/uthread_socketpair.c +++ b/lib/libc_r/uthread/uthread_socketpair.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_socketpair.c,v 1.3 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,14 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_socketpair.c,v 1.4 1998/04/29 09:59:27 jb Exp $ - * $OpenBSD: uthread_socketpair.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_socketpair.c,v 1.6 1999/08/28 00:03:52 peter Exp $ * */ #include <sys/types.h> #include <sys/socket.h> #include <fcntl.h> -#include <unistd.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" diff --git a/lib/libc_r/uthread/uthread_spec.c b/lib/libc_r/uthread/uthread_spec.c index 6a4b9c9c5e4..1ac1df46fe4 100644 --- a/lib/libc_r/uthread/uthread_spec.c +++ b/lib/libc_r/uthread/uthread_spec.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_spec.c,v 1.6 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_spec.c,v 1.5 1999/05/14 22:29:52 alex Exp $ + * $FreeBSD: uthread_spec.c,v 1.13 1999/08/28 00:03:52 peter Exp $ */ #include <signal.h> #include <stdlib.h> @@ -113,7 +114,7 @@ _thread_cleanupspecific(void) _SPINUNLOCK(&key_table[key].lock); /* - * If there is a destructor, call it + * If there is a destructore, call it * with the key table entry unlocked: */ if (destructor) diff --git a/lib/libc_r/uthread/uthread_spinlock.c b/lib/libc_r/uthread/uthread_spinlock.c index 3ea96013bc6..6e7a60706c4 100644 --- a/lib/libc_r/uthread/uthread_spinlock.c +++ b/lib/libc_r/uthread/uthread_spinlock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_spinlock.c,v 1.6 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_spinlock.c,v 1.5 1999/03/23 05:07:56 jb Exp $ - * $OpenBSD: uthread_spinlock.c,v 1.5 1999/05/26 00:18:26 d Exp $ + * $FreeBSD: uthread_spinlock.c,v 1.7 1999/08/28 00:03:52 peter Exp $ * */ @@ -63,7 +63,7 @@ _spinlock(spinlock_t *lck) } /* The running thread now owns the lock: */ - lck->lock_owner = _thread_run; + lck->lock_owner = (long) _thread_run; } /* @@ -101,7 +101,7 @@ _spinlock_debug(spinlock_t *lck, const char *fname, int lineno) } /* The running thread now owns the lock: */ - lck->lock_owner = _thread_run; + lck->lock_owner = (long) _thread_run; lck->fname = fname; lck->lineno = lineno; } diff --git a/lib/libc_r/uthread/uthread_stack.c b/lib/libc_r/uthread/uthread_stack.c new file mode 100644 index 00000000000..940f295efd3 --- /dev/null +++ b/lib/libc_r/uthread/uthread_stack.c @@ -0,0 +1,97 @@ +/* $OpenBSD: uthread_stack.c,v 1.1 1999/11/25 07:01:46 d Exp $ */ + +/* + * Thread stack allocation. + * + * Stack pointers are assumed to work their way down (backwards) to the + * beginning of the stack storage. The first page of this storage is + * protected using mprotect() so as to generate a SIGSEGV if a thread + * overflows its stack. + */ + +#include <stddef.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/user.h> +#include <sys/mman.h> +#include <pthread.h> +#include <pthread_np.h> +#include "pthread_private.h" + +struct stack * +_thread_stack_alloc(base, size) + void *base; + size_t size; +{ + struct stack *stack; + + /* Maintain a queue of default-sized stacks that we can re-use. */ + if (size == PTHREAD_STACK_DEFAULT) { + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + if ((stack = SLIST_FIRST(&_stackq)) != NULL) { + SLIST_REMOVE_HEAD(&_stackq, qe); + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + return stack; + } + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + } + + /* Allocate some storage to hold information about the stack: */ + stack = (struct stack *)malloc(sizeof (struct stack)); + if (stack == NULL) + return NULL; + + if (base != NULL) { + /* Use the user's storage */ + stack->base = base; + stack->size = size; + stack->redzone = NULL; + stack->storage = NULL; + return stack; + } + + /* Allocate some storage for the stack, with some overhead: */ + stack->storage = malloc(size + NBPG * 2); + if (stack->storage == NULL) { + free(stack); + return NULL; + } + + /* The red zone is the first physical page of the storage: */ + stack->redzone = (void*)(((int)stack->storage + NBPG - 1) & + ~(NBPG - 1)); + if (mprotect(stack->redzone, NBPG, 0) == -1) + PANIC("Cannot protect stack red zone"); + + /* Find the useful range of the stack. */ + stack->base = stack->redzone + NBPG; + stack->size = size; + + return stack; +} + +void +_thread_stack_free(stack) + struct stack *stack; +{ + /* Cache allocated stacks of default size. */ + if (stack->storage != NULL && stack->size == PTHREAD_STACK_DEFAULT) + SLIST_INSERT_HEAD(&_stackq, stack, qe); + else { + /* Restore storage protection to what malloc expects: */ + if (stack->redzone) + mprotect(stack->redzone, NBPG, PROT_READ|PROT_WRITE); + + /* Free storage */ + if (stack->storage) + free(stack->storage); + + /* Free stack information storage. */ + free(stack); + } +} diff --git a/lib/libc_r/uthread/uthread_suspend_np.c b/lib/libc_r/uthread/uthread_suspend_np.c index daeb60a661a..8c455e0a11d 100644 --- a/lib/libc_r/uthread/uthread_suspend_np.c +++ b/lib/libc_r/uthread/uthread_suspend_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_suspend_np.c,v 1.4 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_suspend_np.c,v 1.3 1999/05/26 00:18:26 d Exp $ + * $FreeBSD: uthread_suspend_np.c,v 1.7 1999/08/28 00:03:53 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -53,20 +54,19 @@ pthread_suspend_np(pthread_t thread) } /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Suspend the thread. */ PTHREAD_NEW_STATE(thread,PS_SUSPENDED); /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } return(ret); } diff --git a/lib/libc_r/uthread/uthread_switch_np.c b/lib/libc_r/uthread/uthread_switch_np.c index 598edacd2bb..2e7351b9697 100644 --- a/lib/libc_r/uthread/uthread_switch_np.c +++ b/lib/libc_r/uthread/uthread_switch_np.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_switch_np.c,v 1.1 1999/05/26 00:18:26 d Exp $ */ +/* $OpenBSD: uthread_switch_np.c,v 1.2 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_switch_np.c,v 1.3 1999/08/28 00:03:53 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libc_r/uthread/uthread_vfork.c b/lib/libc_r/uthread/uthread_vfork.c index a3b0ee5bb06..32ac5cd33c1 100644 --- a/lib/libc_r/uthread/uthread_vfork.c +++ b/lib/libc_r/uthread/uthread_vfork.c @@ -1,6 +1,4 @@ -/* - * $OpenBSD: uthread_vfork.c,v 1.1 1998/11/09 03:13:21 d Exp $ - */ +/* $OpenBSD: uthread_vfork.c,v 1.2 1999/11/25 07:01:47 d Exp $ */ #include <unistd.h> #ifdef _THREAD_SAFE @@ -9,4 +7,4 @@ vfork(void) { return (fork()); } -#endif /* _THREAD_SAFE */ +#endif diff --git a/lib/libc_r/uthread/uthread_wait4.c b/lib/libc_r/uthread/uthread_wait4.c index aef609468d4..0c3efa803f2 100644 --- a/lib/libc_r/uthread/uthread_wait4.c +++ b/lib/libc_r/uthread/uthread_wait4.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_wait4.c,v 1.5 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_wait4.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_wait4.c,v 1.5 1999/08/28 00:03:53 peter Exp $ */ #include <errno.h> #include <sys/wait.h> @@ -45,6 +46,8 @@ wait4(pid_t pid, int *istat, int options, struct rusage * rusage) /* This is a cancellation point: */ _thread_enter_cancellation_point(); + _thread_kern_sig_defer(); + /* Perform a non-blocking wait4 syscall: */ while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) { /* Reset the interrupted operation flag: */ @@ -61,6 +64,8 @@ wait4(pid_t pid, int *istat, int options, struct rusage * rusage) } } + _thread_kern_sig_undefer(); + /* No longer in a cancellation point: */ _thread_leave_cancellation_point(); diff --git a/lib/libc_r/uthread/uthread_write.c b/lib/libc_r/uthread/uthread_write.c index 7d91092f9ae..cac06ef3bb5 100644 --- a/lib/libc_r/uthread/uthread_write.c +++ b/lib/libc_r/uthread/uthread_write.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_write.c,v 1.5 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_write.c,v 1.10 1998/09/07 21:55:01 alex Exp $ - * $OpenBSD: uthread_write.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_write.c,v 1.12 1999/08/28 00:03:54 peter Exp $ * */ #include <sys/types.h> @@ -51,18 +51,12 @@ write(int fd, const void *buf, size_t nbytes) ssize_t num = 0; ssize_t ret; - /* This is a cancellation point: */ - _thread_enter_cancellation_point(); - /* POSIX says to do just this: */ - if (nbytes == 0) { - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (0); - } + if (nbytes == 0) + ret = 0; /* Lock the file descriptor for write: */ - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + else if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { /* Get the read/write mode type: */ type = _thread_fd_table[fd]->flags & O_ACCMODE; @@ -70,12 +64,10 @@ write(int fd, const void *buf, size_t nbytes) if (type != O_WRONLY && type != O_RDWR) { /* File is not open for write: */ errno = EBADF; - _FD_UNLOCK(fd, FD_WRITE); - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (-1); + ret = -1; } + else { /* Check if file operations are to block */ blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0); @@ -136,7 +128,8 @@ write(int fd, const void *buf, size_t nbytes) /* Return the number of bytes written: */ ret = num; } - _FD_UNLOCK(fd, FD_RDWR); + } + _FD_UNLOCK(fd, FD_WRITE); } /* No longer in a cancellation point: */ diff --git a/lib/libc_r/uthread/uthread_writev.c b/lib/libc_r/uthread/uthread_writev.c index dc280c9145c..411b3bc0238 100644 --- a/lib/libc_r/uthread/uthread_writev.c +++ b/lib/libc_r/uthread/uthread_writev.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_writev.c,v 1.3 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_writev.c,v 1.10 1998/06/14 09:36:14 jb Exp $ - * $OpenBSD: uthread_writev.c,v 1.2 1998/12/23 22:49:47 d Exp $ + * $FreeBSD: uthread_writev.c,v 1.12 1999/08/28 00:03:55 peter Exp $ * */ #include <sys/types.h> diff --git a/lib/libc_r/uthread/uthread_yield.c b/lib/libc_r/uthread/uthread_yield.c index 1844be51fcc..0dfaaf14438 100644 --- a/lib/libc_r/uthread/uthread_yield.c +++ b/lib/libc_r/uthread/uthread_yield.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_yield.c,v 1.3 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_yield.c,v 1.2 1999/01/06 05:29:29 d Exp $ + * $FreeBSD: uthread_yield.c,v 1.4 1999/08/28 00:03:55 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libpthread/arch/alpha/uthread_machdep.h b/lib/libpthread/arch/alpha/uthread_machdep.h index 7ee0653367d..9a7c52da977 100644 --- a/lib/libpthread/arch/alpha/uthread_machdep.h +++ b/lib/libpthread/arch/alpha/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/alpha machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.4 1999/02/04 23:37:39 niklas Exp $ + * $OpenBSD: uthread_machdep.h,v 1.5 1999/11/25 07:01:27 d Exp $ */ /* save the floating point state of a thread */ @@ -50,11 +50,11 @@ do { \ { \ /* entry */ \ (thr)->saved_jmp_buf[2] = (long) entry; \ - (thr)->saved_jmp_buf[4+R_RA] = 0; \ - (thr)->saved_jmp_buf[4+R_T12] = (long) entry; \ + (thr)->saved_jmp_buf[4 + R_RA] = 0; \ + (thr)->saved_jmp_buf[4 + R_T12] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[4 + R_SP] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[4 + R_SP] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libpthread/arch/hppa/uthread_machdep.h b/lib/libpthread/arch/hppa/uthread_machdep.h index 773bd90e22f..0d80d718ded 100644 --- a/lib/libpthread/arch/hppa/uthread_machdep.h +++ b/lib/libpthread/arch/hppa/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/hppa machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.2 1999/01/17 23:49:48 d Exp $$ + * $OpenBSD: uthread_machdep.h,v 1.3 1999/11/25 07:01:27 d Exp $$ */ /* save the floating point state of a thread */ @@ -23,8 +23,8 @@ /* entry */ \ (thr)->saved_jmp_buf[5] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[2] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[2] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libpthread/arch/i386/uthread_machdep.h b/lib/libpthread/arch/i386/uthread_machdep.h index cac445509ca..dab5c413932 100644 --- a/lib/libpthread/arch/i386/uthread_machdep.h +++ b/lib/libpthread/arch/i386/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/i386 machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.5 1999/03/10 09:50:33 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.6 1999/11/25 07:01:28 d Exp $ */ #include <machine/reg.h> @@ -59,9 +59,10 @@ struct _machdep_struct { /* entry */ \ (thr)->saved_jmp_buf.mjb_eip = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf.mjb_esp = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ - - sizeof(double); \ + (thr)->saved_jmp_buf.mjb_esp = \ + (long) (thr)->stack->base + \ + (thr)->stack->size \ + - sizeof(double); \ } static __inline int diff --git a/lib/libpthread/arch/m68k/uthread_machdep.h b/lib/libpthread/arch/m68k/uthread_machdep.h index 4ed702981b5..8bda374924d 100644 --- a/lib/libpthread/arch/m68k/uthread_machdep.h +++ b/lib/libpthread/arch/m68k/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/m68k machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.2 1999/01/17 23:49:49 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.3 1999/11/25 07:01:28 d Exp $ */ /* save the floating point state of a thread */ @@ -23,8 +23,8 @@ /* entry */ \ (thr)->saved_jmp_buf[5] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[2] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[2] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libpthread/arch/m88k/uthread_machdep.h b/lib/libpthread/arch/m88k/uthread_machdep.h index dcad59d851d..0fcad5cf0ae 100644 --- a/lib/libpthread/arch/m88k/uthread_machdep.h +++ b/lib/libpthread/arch/m88k/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/m88k machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.1 1999/03/03 06:00:10 smurph Exp $ + * $OpenBSD: uthread_machdep.h,v 1.2 1999/11/25 07:01:28 d Exp $ */ /* save the floating point state of a thread */ @@ -23,8 +23,8 @@ /* entry */ \ (thr)->saved_jmp_buf[5] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[2] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[2] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libpthread/arch/mips/uthread_machdep.h b/lib/libpthread/arch/mips/uthread_machdep.h index 6052b2003da..89fb399d629 100644 --- a/lib/libpthread/arch/mips/uthread_machdep.h +++ b/lib/libpthread/arch/mips/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/mips machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.3 1999/01/17 23:49:49 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.4 1999/11/25 07:01:28 d Exp $ */ #include <machine/regnum.h> @@ -23,8 +23,8 @@ j->sc_regs[RA] = j->sc_pc; /* for gdb */ \ j->sc_pc = (int)entry; \ /* stack */ \ - j->sc_regs[SP] = (int) (thr)->stack \ - + (pattr)->stacksize_attr \ + j->sc_regs[SP] = (int) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } diff --git a/lib/libpthread/arch/powerpc/uthread_machdep.h b/lib/libpthread/arch/powerpc/uthread_machdep.h index bd713b5ff0e..6041279d95e 100644 --- a/lib/libpthread/arch/powerpc/uthread_machdep.h +++ b/lib/libpthread/arch/powerpc/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/powerpc machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.3 1999/04/21 03:45:21 rahnds Exp $ + * $OpenBSD: uthread_machdep.h,v 1.4 1999/11/25 07:01:29 d Exp $ */ /* save the floating point state of a thread */ @@ -24,8 +24,8 @@ (thr)->saved_jmp_buf[JMP_lr] = \ (unsigned int) entry; \ (thr)->saved_jmp_buf[JMP_r1] = \ - ((unsigned int) (thr)->stack \ - + (pattr)->stacksize_attr \ + ((unsigned int) (thr)->stack->base \ + + (thr)->stack->size \ - 0x4) & ~0xf; \ { \ unsigned int *pbacklink = \ diff --git a/lib/libpthread/arch/sparc/uthread_machdep.h b/lib/libpthread/arch/sparc/uthread_machdep.h index c922b49fd0c..46ffd6dc92c 100644 --- a/lib/libpthread/arch/sparc/uthread_machdep.h +++ b/lib/libpthread/arch/sparc/uthread_machdep.h @@ -1,7 +1,7 @@ /* * OpenBSD/sparc machine-dependent thread macros * - * $OpenBSD: uthread_machdep.h,v 1.2 1999/01/17 23:49:49 d Exp $ + * $OpenBSD: uthread_machdep.h,v 1.3 1999/11/25 07:01:29 d Exp $ */ #include <sys/signal.h> @@ -9,13 +9,13 @@ /* save the floating point state of a thread */ #define _thread_machdep_save_float_state(thr) \ { \ - /* XXX tdb */ \ + /* XXX tdb */ \ } /* restore the floating point state of a thread */ #define _thread_machdep_restore_float_state(thr) \ { \ - /* XXX tdb */ \ + /* XXX tdb */ \ } /* initialise the jmpbuf stack frame so it continues from entry */ @@ -25,19 +25,13 @@ /* entry */ \ (thr)->saved_jmp_buf[1] = (long) entry; \ /* stack */ \ - (thr)->saved_jmp_buf[0] = (long) (thr)->stack \ - + (pattr)->stacksize_attr \ + (thr)->saved_jmp_buf[0] = (long) (thr)->stack->base \ + + (thr)->stack->size \ - sizeof(double); \ } -/* - * XXX high chance of longjmp botch (see libc/arch/sparc/gen/_setjmp.S) - * because it uses the frame pointer to pop off frames.. we don't want - * that.. what to do? fudge %fp? do our own setjmp? - */ -#define _thread_machdep_longjmp(a,v) _longjmp(a,v) -#define _thread_machdep_setjmp(a) _setjmp(a) - +#define _thread_machdep_longjmp(a,v) _longjmp(a,v) +#define _thread_machdep_setjmp(a) _setjmp(a) typedef jmp_buf _machdep_jmp_buf; struct _machdep_struct { diff --git a/lib/libpthread/include/pthread.h b/lib/libpthread/include/pthread.h index 108f4d2de41..d94bbe8173f 100644 --- a/lib/libpthread/include/pthread.h +++ b/lib/libpthread/include/pthread.h @@ -30,13 +30,19 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: pthread.h,v 1.8 1999/06/15 00:10:37 d Exp $ + * $OpenBSD: pthread.h,v 1.9 1999/11/25 07:01:29 d Exp $ * + * $FreeBSD: pthread.h,v 1.13 1999/07/31 08:36:07 rse Exp $ */ #ifndef _PTHREAD_H_ #define _PTHREAD_H_ #ifdef _POSIX_THREADS +#ifdef notyet +#warning -pthread option no longer needed - upgrade gcc +#endif +#undef _POSIX_THREADS +#endif /* * Header files. @@ -62,7 +68,7 @@ * Note that those commented out are not currently supported by the * implementation. */ - +#define _POSIX_THREADS #define _POSIX_THREAD_ATTR_STACKADDR #define _POSIX_THREAD_ATTR_STACKSIZE #define _POSIX_THREAD_PRIORITY_SCHEDULING @@ -113,7 +119,6 @@ struct pthread_mutex_attr; struct pthread_once; struct pthread_rwlock; struct pthread_rwlockattr; -struct sched_param; /* * Primitive system data type definitions required by P1003.1c. @@ -209,7 +214,6 @@ int pthread_attr_init __P((pthread_attr_t *)); int pthread_attr_setstacksize __P((pthread_attr_t *, size_t)); int pthread_attr_setstackaddr __P((pthread_attr_t *, void *)); int pthread_attr_setdetachstate __P((pthread_attr_t *, int)); -int pthread_cancel __P((pthread_t)); void pthread_cleanup_pop __P((int execute)); void pthread_cleanup_push __P((void (*routine) (void *), void *routine_arg)); @@ -252,7 +256,7 @@ int pthread_mutex_lock __P((pthread_mutex_t *)); int pthread_mutex_trylock __P((pthread_mutex_t *)); int pthread_mutex_unlock __P((pthread_mutex_t *)); int pthread_once __P((pthread_once_t *, - void (*init_routine) (void))); + void (*) (void))); int pthread_rwlock_destroy __P((pthread_rwlock_t *)); int pthread_rwlock_init __P((pthread_rwlock_t *, const pthread_rwlockattr_t *)); @@ -268,12 +272,13 @@ int pthread_rwlockattr_setpshared __P((pthread_rwlockattr_t *, int *)); int pthread_rwlockattr_destroy __P((pthread_rwlockattr_t *)); pthread_t pthread_self __P((void)); -int pthread_setcancelstate __P((int, int *)); -int pthread_setcanceltype __P((int, int *)); int pthread_setspecific __P((pthread_key_t, const void *)); int pthread_sigmask __P((int, const sigset_t *, sigset_t *)); -void pthread_testcancel __P((void)); +int pthread_cancel __P((pthread_t)); +int pthread_setcancelstate __P((int, int *)); +int pthread_setcanceltype __P((int, int *)); +void pthread_testcancel __P((void)); int pthread_getprio __P((pthread_t)); int pthread_setprio __P((pthread_t, int)); @@ -326,15 +331,13 @@ int pthread_attr_setcleanup __P((pthread_attr_t *, void (*routine) (void *), void *)); -#if 0 +#ifdef notyet /* - * Single Unix Specification v2 (UNIX98) also wants these: + * Single Unix Specification v2 (UNIX98) defines these: */ - #define PTHREAD_PRIO_INHERIT #define PTHREAD_PRIO_NONE #define PTHREAD_PRIO_PROTECT - int pthread_attr_getguardsize __P((const pthread_attr_t *, size_t *)); int pthread_attr_setguardsize __P((const pthread_attr_t *, @@ -343,12 +346,8 @@ int pthread_getconcurrency __P((void)); int pthread_mutexattr_gettype __P((const pthread_mutexattr_t *, int *)); int pthread_setconcurrency __P((int)); - #endif /* susv2 */ __END_DECLS -#else /* ! _POSIX_THREADS */ -#warning "included <pthread.h> without -pthread compiler option" -#endif /* ! _POSIX_THREADS */ #endif /* _PTHREAD_H_ */ diff --git a/lib/libpthread/include/pthread_np.h b/lib/libpthread/include/pthread_np.h index 6f8b7b7ef44..a6071d9e4d0 100644 --- a/lib/libpthread/include/pthread_np.h +++ b/lib/libpthread/include/pthread_np.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pthread_np.h,v 1.2 1999/05/26 00:17:41 d Exp $ */ +/* $OpenBSD: pthread_np.h,v 1.3 1999/11/25 07:01:29 d Exp $ */ /* * Copyright (c) 1996-98 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -48,11 +48,11 @@ int pthread_multi_np __P((void)); int pthread_resume_np __P((pthread_t)); int pthread_single_np __P((void)); int pthread_suspend_np __P((pthread_t)); -int pthread_mutexattr_getkind_np __P((pthread_mutexattr_t attr)); -int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *attr, int kind)); +int pthread_mutexattr_getkind_np __P((pthread_mutexattr_t)); +int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *, int)); void pthread_set_name_np __P((pthread_t, char *)); -int pthread_switch_add_np (pthread_switch_routine_t routine); -int pthread_switch_delete_np (pthread_switch_routine_t routine); +int pthread_switch_add_np __P((pthread_switch_routine_t)); +int pthread_switch_delete_np __P((pthread_switch_routine_t)); __END_DECLS #endif diff --git a/lib/libpthread/include/sched.h b/lib/libpthread/include/sched.h index 292edf7b2e3..46f8e9703d8 100644 --- a/lib/libpthread/include/sched.h +++ b/lib/libpthread/include/sched.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sched.h,v 1.2 1999/03/10 10:03:52 d Exp $ */ +/* $OpenBSD: sched.h,v 1.3 1999/11/25 07:01:29 d Exp $ */ #ifndef _SCHED_H_ #define _SCHED_H_ @@ -40,6 +40,10 @@ #include <sys/types.h> /* For pid_t */ +#ifndef KERNEL +#include <time.h> /* Per P1003.4 */ +#endif + /* Scheduling policies */ #define SCHED_FIFO 1 @@ -53,8 +57,6 @@ struct sched_param #ifndef KERNEL #include <sys/cdefs.h> -#include <time.h> /* Per P1003.4 */ -#include <sys/time.h> __BEGIN_DECLS int sched_setparam __P((pid_t, const struct sched_param *)); diff --git a/lib/libpthread/include/spinlock.h b/lib/libpthread/include/spinlock.h index 4da4a9ec500..772331be377 100644 --- a/lib/libpthread/include/spinlock.h +++ b/lib/libpthread/include/spinlock.h @@ -29,8 +29,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: spinlock.h,v 1.3 1999/01/18 00:03:34 d Exp $ - * $OpenBSD: spinlock.h,v 1.3 1999/01/18 00:03:34 d Exp $ + * $Id: spinlock.h,v 1.4 1999/11/25 07:01:29 d Exp $ + * $OpenBSD: spinlock.h,v 1.4 1999/11/25 07:01:29 d Exp $ * * Lock definitions used in both libc and libpthread. * @@ -61,6 +61,8 @@ typedef struct { #define _SPINLOCK(_lck) _spinlock(_lck) #endif +#define _SPINLOCK_INIT(_lck) _SPINUNLOCK(_lck) + /* * Thread function prototype definitions: */ diff --git a/lib/libpthread/sys/Makefile.inc b/lib/libpthread/sys/Makefile.inc index 2c4ee0df2fd..79b6afe2a4d 100644 --- a/lib/libpthread/sys/Makefile.inc +++ b/lib/libpthread/sys/Makefile.inc @@ -1,17 +1,23 @@ -# $Id: Makefile.inc,v 1.3 1999/01/06 05:36:18 d Exp $ -# $OpenBSD: Makefile.inc,v 1.3 1999/01/06 05:36:18 d Exp $ +# $Id: Makefile.inc,v 1.4 1999/11/25 07:01:29 d Exp $ +# $OpenBSD: Makefile.inc,v 1.4 1999/11/25 07:01:29 d Exp $ .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} -SRCS+= uthread_error.c _atomic_lock.c slow_atomic_lock.c +SRCS+= uthread_error.c _atomic_lock.c slow_atomic_lock.c SRCS+= _sys_aliases.c CLEANFILES += _sys_aliases.c _sys_aliases.c: ${.CURDIR}/Makefile ${LIBCSRCDIR}/sys/Makefile.inc - (echo '#include <sys/cdefs.h>'; \ - for fn in ${ASM:R} ${PSEUDO:R} ""; do \ + echo '#include <sys/cdefs.h>' > ${.TARGET} +.if ${MACHINE} == "alpha" + # This kludge will disappear when we shift to -lpthread + echo '#define __indr_reference(old,new)' \ + '__asm__(".globl "#new";"#new": jmp $$31,"#old)' > ${.TARGET} + +.endif + for fn in ${ASM:R} ${PSEUDO:R} ""; do \ case $$fn in ${HIDDEN_SYSCALLS:.o=|}"") : stays hidden ;; \ *) echo "__indr_reference(_thread_sys_$$fn,$$fn);";; \ esac; \ - done ) > ${.TARGET} + done >> ${.TARGET} diff --git a/lib/libpthread/sys/uthread_error.c b/lib/libpthread/sys/uthread_error.c index 545dfb06652..08740ed92ff 100644 --- a/lib/libpthread/sys/uthread_error.c +++ b/lib/libpthread/sys/uthread_error.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_error.c,v 1.2 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu @@ -31,6 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_error.c,v 1.2 1999/08/05 12:14:13 deischen Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libpthread/uthread/Makefile.inc b/lib/libpthread/uthread/Makefile.inc index 56a6b0046ba..00022b16eb6 100644 --- a/lib/libpthread/uthread/Makefile.inc +++ b/lib/libpthread/uthread/Makefile.inc @@ -1,5 +1,5 @@ -# $Id: Makefile.inc,v 1.8 1999/06/15 00:07:39 d Exp $ -# $OpenBSD: Makefile.inc,v 1.8 1999/06/15 00:07:39 d Exp $ +# $OpenBSD: Makefile.inc,v 1.9 1999/11/25 07:01:30 d Exp $ +# $FreeBSD: Makefile.inc,v 1.19 1999/08/28 00:03:19 peter Exp $ # uthread sources .PATH: ${.CURDIR}/uthread @@ -15,7 +15,6 @@ SRCS+= \ uthread_attr_getschedparam.c \ uthread_attr_getschedpolicy.c \ uthread_attr_getscope.c \ - uthread_attr_setstackaddr.c \ uthread_attr_getstackaddr.c \ uthread_attr_getstacksize.c \ uthread_attr_setcreatesuspend_np.c \ @@ -28,7 +27,6 @@ SRCS+= \ uthread_attr_setstacksize.c \ uthread_autoinit.c \ uthread_bind.c \ - uthread_fchflags.c \ uthread_cancel.c \ uthread_clean.c \ uthread_close.c \ @@ -63,7 +61,7 @@ SRCS+= \ uthread_getschedparam.c \ uthread_getsockname.c \ uthread_getsockopt.c \ - uthread_info.c \ + uthread_info_openbsd.c \ uthread_init.c \ uthread_ioctl.c \ uthread_join.c \ @@ -82,9 +80,8 @@ SRCS+= \ uthread_once.c \ uthread_open.c \ uthread_pipe.c \ - uthread_priority_queue.c \ uthread_poll.c \ - uthread_queue.c \ + uthread_priority_queue.c \ uthread_read.c \ uthread_readv.c \ uthread_recvfrom.c \ @@ -116,6 +113,7 @@ SRCS+= \ uthread_socketpair.c \ uthread_spec.c \ uthread_spinlock.c \ + uthread_stack.c \ uthread_suspend_np.c \ uthread_switch_np.c \ uthread_vfork.c \ diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h index 69a36e13477..f49d0eb257e 100644 --- a/lib/libpthread/uthread/pthread_private.h +++ b/lib/libpthread/uthread/pthread_private.h @@ -1,3 +1,4 @@ +/* $OpenBSD: pthread_private.h,v 1.18 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -31,15 +32,12 @@ * * Private thread definitions for the uthread kernel. * - * $OpenBSD: pthread_private.h,v 1.17 1999/09/08 08:21:47 espie Exp $ - * + * $FreeBSD: pthread_private.h,v 1.27 1999/09/29 15:18:38 marcel Exp $ */ #ifndef _PTHREAD_PRIVATE_H #define _PTHREAD_PRIVATE_H -#include <paths.h> - /* * Include files. */ @@ -51,9 +49,7 @@ #include <sched.h> #include <spinlock.h> #include <pthread_np.h> -#ifndef _NO_UTHREAD_MACHDEP #include "uthread_machdep.h" -#endif /* * Kernel fatal error handler macro. @@ -66,33 +62,88 @@ /* - * Priority queue manipulation macros: + * Priority queue manipulation macros (using pqe link): */ #define PTHREAD_PRIOQ_INSERT_HEAD(thrd) _pq_insert_head(&_readyq,thrd) #define PTHREAD_PRIOQ_INSERT_TAIL(thrd) _pq_insert_tail(&_readyq,thrd) #define PTHREAD_PRIOQ_REMOVE(thrd) _pq_remove(&_readyq,thrd) -#define PTHREAD_PRIOQ_FIRST _pq_first(&_readyq) +#define PTHREAD_PRIOQ_FIRST() _pq_first(&_readyq) /* - * Waiting queue manipulation macros: + * Waiting queue manipulation macros (using pqe link): */ -#define PTHREAD_WAITQ_INSERT(thrd) TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe) +#if defined(_PTHREADS_INVARIANTS) +#define PTHREAD_WAITQ_REMOVE(thrd) _waitq_remove(thrd) +#define PTHREAD_WAITQ_INSERT(thrd) _waitq_insert(thrd) +#define PTHREAD_WAITQ_CLEARACTIVE() _waitq_clearactive() +#define PTHREAD_WAITQ_SETACTIVE() _waitq_setactive() +#else #define PTHREAD_WAITQ_REMOVE(thrd) TAILQ_REMOVE(&_waitingq,thrd,pqe) +#define PTHREAD_WAITQ_INSERT(thrd) do { \ + if ((thrd)->wakeup_time.tv_sec == -1) \ + TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe); \ + else { \ + pthread_t tid = TAILQ_FIRST(&_waitingq); \ + while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) && \ + ((tid->wakeup_time.tv_sec < (thrd)->wakeup_time.tv_sec) || \ + ((tid->wakeup_time.tv_sec == (thrd)->wakeup_time.tv_sec) && \ + (tid->wakeup_time.tv_nsec <= (thrd)->wakeup_time.tv_nsec)))) \ + tid = TAILQ_NEXT(tid, pqe); \ + if (tid == NULL) \ + TAILQ_INSERT_TAIL(&_waitingq,thrd,pqe); \ + else \ + TAILQ_INSERT_BEFORE(tid,thrd,pqe); \ + } \ +} while (0) +#define PTHREAD_WAITQ_CLEARACTIVE() +#define PTHREAD_WAITQ_SETACTIVE() +#endif + +/* + * Work queue manipulation macros (using qe link): + */ +#define PTHREAD_WORKQ_INSERT(thrd) do { \ + TAILQ_INSERT_TAIL(&_workq,thrd,qe); \ + (thrd)->flags |= PTHREAD_FLAGS_IN_WORKQ; \ +} while (0) +#define PTHREAD_WORKQ_REMOVE(thrd) do { \ + TAILQ_REMOVE(&_workq,thrd,qe); \ + (thrd)->flags &= ~PTHREAD_FLAGS_IN_WORKQ; \ +} while (0) + /* * State change macro without scheduling queue change: */ -#define PTHREAD_SET_STATE(thrd, newstate) { \ +#define PTHREAD_SET_STATE(thrd, newstate) do { \ (thrd)->state = newstate; \ (thrd)->fname = __FILE__; \ (thrd)->lineno = __LINE__; \ -} +} while (0) /* * State change macro with scheduling queue change - This must be * called with preemption deferred (see thread_kern_sched_[un]defer). */ -#define PTHREAD_NEW_STATE(thrd, newstate) { \ +#if defined(_PTHREADS_INVARIANTS) +#define PTHREAD_NEW_STATE(thrd, newstate) do { \ + if (_thread_kern_new_state != 0) \ + PANIC("Recursive PTHREAD_NEW_STATE"); \ + _thread_kern_new_state = 1; \ + if ((thrd)->state != newstate) { \ + if ((thrd)->state == PS_RUNNING) { \ + PTHREAD_PRIOQ_REMOVE(thrd); \ + PTHREAD_WAITQ_INSERT(thrd); \ + } else if (newstate == PS_RUNNING) { \ + PTHREAD_WAITQ_REMOVE(thrd); \ + PTHREAD_PRIOQ_INSERT_TAIL(thrd); \ + } \ + } \ + _thread_kern_new_state = 0; \ + PTHREAD_SET_STATE(thrd, newstate); \ +} while (0) +#else +#define PTHREAD_NEW_STATE(thrd, newstate) do { \ if ((thrd)->state != newstate) { \ if ((thrd)->state == PS_RUNNING) { \ PTHREAD_PRIOQ_REMOVE(thrd); \ @@ -103,7 +154,8 @@ } \ } \ PTHREAD_SET_STATE(thrd, newstate); \ -} +} while (0) +#endif /* * Define the signals to be used for scheduling. @@ -117,15 +169,6 @@ #endif /* - * Queue definitions. - */ -struct pthread_queue { - struct pthread *q_next; - struct pthread *q_last; - void *q_data; -}; - -/* * Priority queues. * * XXX It'd be nice if these were contained in uthread_priority_queue.[ch]. @@ -145,14 +188,9 @@ typedef struct pq_queue { /* - * Static queue initialization values. - */ -#define PTHREAD_QUEUE_INITIALIZER { NULL, NULL, NULL } - -/* * TailQ initialization values. */ -#define TAILQ_INITIALIZER { NULL, NULL } +#define TAILQ_INITIALIZER { NULL, NULL } /* * Mutex definitions. @@ -223,7 +261,7 @@ struct pthread_mutex_attr { */ enum pthread_cond_type { COND_TYPE_FAST, - COND_TYPE_MAX +#define COND_TYPE_MAX ((int)COND_TYPE_FAST + 1) }; struct pthread_cond { @@ -255,8 +293,8 @@ struct pthread_cond_attr { * Static cond initialization values. */ #define PTHREAD_COND_STATIC_INITIALIZER \ - { COND_TYPE_FAST, PTHREAD_QUEUE_INITIALIZER, NULL, NULL, \ - 0, _SPINLOCK_INITIALIZER } + { COND_TYPE_FAST, TAILQ_INITIALIZER, NULL, NULL, \ + 0, _SPINLOCK_INITIALIZER } /* * Cleanup definitions. @@ -290,6 +328,13 @@ struct pthread_attr { * Miscellaneous definitions. */ #define PTHREAD_STACK_DEFAULT 65536 +/* + * Maximum size of initial thread's stack. This perhaps deserves to be larger + * than the stacks of other threads, since many applications are likely to run + * almost entirely on this stack. + */ +#define PTHREAD_STACK_INITIAL 0x100000 +/* Address immediately beyond the beginning of the initial thread stack. */ #define PTHREAD_DEFAULT_PRIORITY 64 #define PTHREAD_MAX_PRIORITY 126 #define PTHREAD_MIN_PRIORITY 0 @@ -301,12 +346,6 @@ struct pthread_attr { #define CLOCK_RES_NSEC 10000000 /* - * Number of microseconds between incremental priority updates for - * threads that are ready to run, but denied being run. - */ -#define INC_PRIO_USEC 500000 - -/* * Time slice period in microseconds. */ #define TIMESLICE_USEC 100000 @@ -343,6 +382,7 @@ enum pthread_state { PS_FDR_WAIT, PS_FDW_WAIT, PS_FILE_WAIT, + PS_POLL_WAIT, PS_SELECT_WAIT, PS_SLEEP_WAIT, PS_WAIT_WAIT, @@ -352,8 +392,8 @@ enum pthread_state { PS_JOIN, PS_SUSPENDED, PS_DEAD, - PS_DEADLOCK, - PS_STATE_MAX + PS_DEADLOCK +#define PS_STATE_MAX ((int)PS_DEADLOCK + 1) }; @@ -375,8 +415,8 @@ struct fd_table_entry { * state of the lock on the file descriptor. */ spinlock_t lock; - struct pthread_queue r_queue; /* Read queue. */ - struct pthread_queue w_queue; /* Write queue. */ + TAILQ_HEAD(, pthread) r_queue; /* Read queue. */ + TAILQ_HEAD(, pthread) w_queue; /* Write queue. */ struct pthread *r_owner; /* Ptr to thread owning read lock. */ struct pthread *w_owner; /* Ptr to thread owning write lock. */ const char *r_fname; /* Ptr to read lock source file name */ @@ -388,11 +428,9 @@ struct fd_table_entry { int flags; /* Flags used in open. */ }; -struct pthread_select_data { +struct pthread_poll_data { int nfds; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; + struct pollfd *fds; }; union pthread_wait_data { @@ -404,10 +442,21 @@ union pthread_wait_data { short branch; /* Line number, for debugging. */ const char *fname; /* Source file name for debugging.*/ } fd; - struct pthread_select_data * select_data; + struct pthread_poll_data * poll_data; spinlock_t *spinlock; }; +/* Spare thread stack. */ +struct stack { + SLIST_ENTRY(stack) qe; /* Queue entry for this stack. */ + void *base; /* Bottom of useful stack */ + size_t size; /* Size of useful stack */ + void *redzone; /* Red zone location */ + void *storage; /* allocated storage */ +}; + +typedef TAILQ_ENTRY(pthread) pthread_entry_t; + /* * Thread structure. */ @@ -425,15 +474,11 @@ struct pthread { */ spinlock_t lock; - /* - * Pointer to the next thread in the thread linked list. - */ - struct pthread *nxt; + /* Queue entry for list of all threads: */ + pthread_entry_t tle; - /* - * Pointer to the next thread in the dead thread linked list. - */ - struct pthread *nxt_dead; + /* Queue entry for list of dead threads: */ + pthread_entry_t dle; /* * Thread start routine, argument, stack pointer and thread @@ -441,7 +486,7 @@ struct pthread { */ void *(*start_routine)(void *); void *arg; - void *stack; + struct stack *stack; struct pthread_attr attr; /* @@ -450,6 +495,17 @@ struct pthread { */ struct sigcontext saved_sigcontext; + /* + * Saved jump buffer used in call to longjmp by _thread_kern_sched + * if sig_saved is FALSE. + */ + _machdep_jmp_buf saved_jmp_buf; + + /* + * Further machine-dependent context, valid if sig_saved is FALSE. + */ + struct _machdep_struct _machdep; + /* * TRUE if the last state saved was a signal context. FALSE if the * last state saved was a jump buffer. @@ -484,12 +540,6 @@ struct pthread { long slice_usec; /* - * Cumulative times spent in thread - */ - struct timeval ru_utime; - struct timeval ru_stime; - - /* * Incremental priority accumulated by thread while it is ready to * run but is denied being run. */ @@ -510,36 +560,41 @@ struct pthread { */ int error; - /* Join queue for waiting threads: */ - struct pthread_queue join_queue; + /* Join queue head and link for waiting threads: */ + TAILQ_HEAD(join_head, pthread) join_queue; /* - * The current thread can belong to only one scheduling queue - * at a time (ready or waiting queue). It can also belong to - * a queue of threads waiting on mutexes or condition variables. - * Use pqe for the scheduling queue link (both ready and waiting), - * and qe for other links (mutexes and condition variables). + * The current thread can belong to only one scheduling queue at + * a time (ready or waiting queue). It can also belong to (only) + * one of: * - * Pointer to queue (if any) on which the current thread is waiting. + * o A queue of threads waiting for a mutex + * o A queue of threads waiting for a condition variable + * o A queue of threads waiting for another thread to terminate + * (the join queue above) + * o A queue of threads waiting for a file descriptor lock + * o A queue of threads needing work done by the kernel thread + * (waiting for a spinlock or file I/O) * - * XXX The queuing should be changed to use the TAILQ entry below. - * XXX For the time being, it's hybrid. + * Use pqe for the scheduling queue link (both ready and waiting), + * and qe for other links. */ - struct pthread_queue *queue; - - /* Pointer to next element in queue. */ - struct pthread *qnxt; /* Priority queue entry for this thread: */ - TAILQ_ENTRY(pthread) pqe; + pthread_entry_t pqe; /* Queue entry for this thread: */ - TAILQ_ENTRY(pthread) qe; + pthread_entry_t qe; /* Wait data. */ union pthread_wait_data data; /* + * Allocated for converting select into poll. + */ + struct pthread_poll_data poll_data; + + /* * Set to TRUE if a blocking operation was * interrupted by a signal: */ @@ -549,25 +604,28 @@ struct pthread { int signo; /* - * Set to non-zero when this thread has deferred thread - * scheduling. We allow for recursive deferral. + * Set to non-zero when this thread has deferred signals. + * We allow for recursive deferral. */ - int sched_defer_count; + int sig_defer_count; /* * Set to TRUE if this thread should yield after undeferring - * thread scheduling. + * signals. */ - int yield_on_sched_undefer; + int yield_on_sig_undefer; /* Miscellaneous data. */ int flags; #define PTHREAD_FLAGS_PRIVATE 0x0001 #define PTHREAD_EXITING 0x0002 -#define PTHREAD_FLAGS_QUEUED 0x0004 /* in queue (qe is used) */ -#define PTHREAD_FLAGS_TRACE 0x0008 -#define PTHREAD_CANCELLING 0x0010 /* thread has been cancelled */ -#define PTHREAD_AT_CANCEL_POINT 0x0020 /* thread at cancel point */ +#define PTHREAD_FLAGS_IN_CONDQ 0x0004 /* in condition queue using qe link*/ +#define PTHREAD_FLAGS_IN_WORKQ 0x0008 /* in work queue using qe link */ +#define PTHREAD_FLAGS_IN_WAITQ 0x0010 /* in waiting queue using pqe link*/ +#define PTHREAD_FLAGS_IN_PRIOQ 0x0020 /* in priority queue using pqe link*/ +#define PTHREAD_FLAGS_TRACE 0x0040 /* for debugging purposes */ +#define PTHREAD_FLAGS_CANCELED 0x1000 /* thread has been cancelled */ +#define PTHREAD_FLAGS_CANCELPT 0x2000 /* thread at cancel point */ /* * Base priority is the user setable and retrievable priority @@ -590,7 +648,7 @@ struct pthread { /* * Active priority is always the maximum of the threads base * priority and inherited priority. When there is a change - * in either the real or inherited priority, the active + * in either the base or inherited priority, the active * priority must be recalculated. */ char active_priority; @@ -611,17 +669,6 @@ struct pthread { struct pthread_cleanup *cleanup; const char *fname; /* Ptr to source file name */ int lineno; /* Source line number. */ - - /* - * Saved jump buffer used in call to longjmp by _thread_kern_sched - * if sig_saved is FALSE. - */ - _machdep_jmp_buf saved_jmp_buf; - -#ifndef _UTHREAD_MACHDEP - /* Machine dependent information */ - struct _machdep_struct _machdep; -#endif }; /* @@ -629,14 +676,13 @@ struct pthread { */ /* Kernel thread structure used when there are no running threads: */ -extern struct pthread volatile _thread_kern_thread; -extern struct pthread * volatile _thread_kern_threadp; +extern struct pthread _thread_kern_thread; /* Ptr to the thread structure for the running thread: */ extern struct pthread * volatile _thread_run; /* Ptr to the thread structure for the last user thread to run: */ -extern struct pthread * volatile _last_user_thread; +extern struct pthread * volatile _last_user_thread; /* * Ptr to the thread running in single-threaded mode or NULL if @@ -644,22 +690,23 @@ extern struct pthread * volatile _last_user_thread; */ extern struct pthread * volatile _thread_single; -/* Ptr to the first thread in the thread linked list: */ -extern struct pthread * volatile _thread_link_list; +/* List of all threads: */ +typedef TAILQ_HEAD(, pthread) _thread_list_t; +extern _thread_list_t _thread_list; /* * Array of kernel pipe file descriptors that are used to ensure that * no signals are missed in calls to _select. */ -extern int _thread_kern_pipe[2]; -extern int _thread_kern_in_select; +extern int _thread_kern_pipe[2]; +extern int volatile _queue_signals; extern int _thread_kern_in_sched; /* Last time that an incremental priority update was performed: */ extern struct timeval kern_inc_prio_time; /* Dead threads: */ -extern struct pthread * volatile _thread_dead; +extern _thread_list_t _dead_list; /* Initial thread: */ extern struct pthread *_thread_initial; @@ -682,12 +729,18 @@ extern int _pthread_stdio_flags[3]; /* File table information: */ extern struct fd_table_entry **_thread_fd_table; + +/* Table for polling file descriptors: */ +extern struct pollfd *_thread_pfd_table; + extern const int dtablecount; -extern int _thread_dtablesize; +extern int _thread_dtablesize; /* Descriptor table size. */ + +extern int _clock_res_nsec; /* Clock resolution in nsec. */ /* Garbage collector mutex and condition variable. */ -extern pthread_mutex_t _gc_mutex; -extern pthread_cond_t _gc_cond; +extern pthread_mutex_t _gc_mutex; +extern pthread_cond_t _gc_cond; /* * Array of signal actions for this process. @@ -698,19 +751,32 @@ extern struct sigaction _thread_sigact[NSIG]; * Scheduling queues: */ extern pq_queue_t _readyq; -typedef TAILQ_HEAD(, pthread) _waitingq_t; -extern _waitingq_t _waitingq; +extern _thread_list_t _waitingq; + +/* + * Work queue: + */ +extern _thread_list_t _workq; -/* Indicates that the waitingq now has threads ready to run. */ -extern volatile int _waitingq_check_reqd; +/* Tracks the number of threads blocked while waiting for a spinlock. */ +extern volatile int _spinblock_count; + +/* Indicates that the signal queue needs to be checked. */ +extern volatile int _sigq_check_reqd; /* Thread switch hook. */ extern pthread_switch_routine_t _sched_switch_hook; /* - * Where SIGINFO writes thread states when /dev/tty cannot be opened + * Spare stack queue. Stacks of default size are cached in order to reduce + * thread creation time. Spare stacks are used in LIFO order to increase cache + * locality. */ -#define INFO_DUMP_FILE "/tmp/uthread.dump" +typedef SLIST_HEAD(, stack) _stack_list_t; +extern _stack_list_t _stackq; + +/* Used for _PTHREADS_INVARIANTS checking. */ +extern int _thread_kern_new_state; #ifdef _LOCK_DEBUG #define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock_debug(_fd, _type, \ @@ -722,6 +788,8 @@ extern pthread_switch_routine_t _sched_switch_hook; #define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type) #endif +extern int __isthreaded; + /* * Function prototype definitions. */ @@ -733,49 +801,52 @@ int _thread_fd_lock(int, int, struct timespec *); int _thread_fd_lock_debug(int, int, struct timespec *,const char *fname,int lineno); void _dispatch_signals(void); void _thread_signal(pthread_t, int); -void _lock_thread(void); -void _lock_thread_list(void); -void _unlock_thread(void); -void _unlock_thread_list(void); int _mutex_cv_lock(pthread_mutex_t *); int _mutex_cv_unlock(pthread_mutex_t *); +int _mutex_reinit(pthread_mutex_t *); void _mutex_notify_priochange(struct pthread *); -int _pq_init(struct pq_queue *pq, int, int); +int _cond_reinit(pthread_cond_t *); +int _pq_alloc(struct pq_queue *, int, int); +int _pq_init(struct pq_queue *); void _pq_remove(struct pq_queue *pq, struct pthread *); void _pq_insert_head(struct pq_queue *pq, struct pthread *); void _pq_insert_tail(struct pq_queue *pq, struct pthread *); struct pthread *_pq_first(struct pq_queue *pq); -void _thread_exit(const char *, int, const char *) - __attribute__((noreturn)); +#if defined(_PTHREADS_INVARIANTS) +void _waitq_insert(pthread_t pthread); +void _waitq_remove(pthread_t pthread); +void _waitq_setactive(void); +void _waitq_clearactive(void); +#endif +__dead void _thread_exit(const char *, int, const char *) __attribute__((noreturn)); void _thread_fd_unlock(int, int); -void _thread_fd_unlock_debug(int, int, char *, int); +void _thread_fd_unlock_debug(int, int, const char *, int); void *_thread_cleanup(pthread_t); void _thread_cleanupspecific(void); void _thread_dump_info(void); void _thread_init(void); void _thread_kern_sched(struct sigcontext *); -void _thread_kern_sched_state(enum pthread_state, const char *, int); +void _thread_kern_sched_state(enum pthread_state,const char *fname,int lineno); void _thread_kern_sched_state_unlock(enum pthread_state state, spinlock_t *lock, char *fname, int lineno); void _thread_kern_set_timeout(struct timespec *); -void _thread_kern_sched_defer(void); -void _thread_kern_sched_undefer(void); +void _thread_kern_sig_defer(void); +void _thread_kern_sig_undefer(void); void _thread_sig_handler(int, int, struct sigcontext *); +void _thread_sig_handle(int, struct sigcontext *); +void _thread_sig_init(void); void _thread_start(void); void _thread_start_sig_handler(void); void _thread_seterrno(pthread_t,int); -void _thread_queue_init(struct pthread_queue *); -void _thread_queue_enq(struct pthread_queue *, struct pthread *); -int _thread_queue_remove(struct pthread_queue *, struct pthread *); int _thread_fd_table_init(int fd); -struct pthread *_thread_queue_get(struct pthread_queue *); -struct pthread *_thread_queue_deq(struct pthread_queue *); pthread_addr_t _thread_gc(pthread_addr_t); void _thread_enter_cancellation_point(void); void _thread_leave_cancellation_point(void); void _thread_cancellation_point(void); int _thread_slow_atomic_lock(volatile _spinlock_lock_t *); int _thread_slow_atomic_is_locked(volatile _spinlock_lock_t *); +struct stack * _thread_stack_alloc(void *, size_t); +void _thread_stack_free(struct stack *); /* #include <signal.h> */ #ifdef _USER_SIGNAL_H @@ -900,7 +971,7 @@ int _thread_sys_fchdir(int); int _thread_sys_fchown(int, uid_t, gid_t); int _thread_sys_fsync(int); int _thread_sys_ftruncate(int, off_t); -long _thread_sys_fpathconf(int, int); +long _thread_sys_fpathconf(int, int); int _thread_sys_pause(void); int _thread_sys_pipe(int *); int _thread_sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); @@ -909,8 +980,7 @@ pid_t _thread_sys_fork(void); pid_t _thread_sys_tcgetpgrp(int); ssize_t _thread_sys_read(int, void *, size_t); ssize_t _thread_sys_write(int, const void *, size_t); -void _thread_sys__exit(int) - __attribute__((noreturn)); +__dead void _thread_sys__exit(int) __attribute__((noreturn)); #endif /* #include <fcntl.h> */ @@ -948,16 +1018,16 @@ ssize_t _thread_sys_writev(int, const struct iovec *, int); #endif /* #include <sys/wait.h> */ -#ifdef _SYS_WAIT_H_ +#ifdef _SYS_WAIT_H_ pid_t _thread_sys_wait(int *); pid_t _thread_sys_waitpid(pid_t, int *, int); pid_t _thread_sys_wait3(int *, int, struct rusage *); pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *); #endif -/* #include <sys/poll.h> */ +/* #include <poll.h> */ #ifdef _SYS_POLL_H_ -int _thread_sys_poll(struct pollfd[], int, int); +int _thread_sys_poll(struct pollfd *, unsigned, int); #endif /* #include <sys/mman.h> */ diff --git a/lib/libpthread/uthread/uthread_accept.c b/lib/libpthread/uthread/uthread_accept.c index 95f8c10b56c..db8d078c444 100644 --- a/lib/libpthread/uthread/uthread_accept.c +++ b/lib/libpthread/uthread/uthread_accept.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_accept.c,v 1.4 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_accept.c,v 1.3 1999/02/16 16:39:59 deraadt Exp $ + * $FreeBSD: uthread_accept.c,v 1.9 1999/08/28 00:03:20 peter Exp $ */ #include <errno.h> #include <unistd.h> diff --git a/lib/libpthread/uthread/uthread_attr_destroy.c b/lib/libpthread/uthread/uthread_attr_destroy.c index 51848d5d438..feb0c8309f0 100644 --- a/lib/libpthread/uthread/uthread_attr_destroy.c +++ b/lib/libpthread/uthread/uthread_attr_destroy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_destroy.c,v 1.3 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_destroy.c,v 1.2 1999/01/10 23:05:18 d Exp $ + * $FreeBSD: uthread_attr_destroy.c,v 1.4 1999/08/28 00:03:20 peter Exp $ */ #include <stdlib.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_attr_getdetachstate.c b/lib/libpthread/uthread/uthread_attr_getdetachstate.c index 52ebdfb89c1..f0326139902 100644 --- a/lib/libpthread/uthread/uthread_attr_getdetachstate.c +++ b/lib/libpthread/uthread/uthread_attr_getdetachstate.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_getdetachstate.c,v 1.3 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_getdetachstate.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_getdetachstate.c,v 1.3 1999/08/28 00:03:20 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_getinheritsched.c b/lib/libpthread/uthread/uthread_attr_getinheritsched.c index 54294c2e74b..da160586615 100644 --- a/lib/libpthread/uthread/uthread_attr_getinheritsched.c +++ b/lib/libpthread/uthread/uthread_attr_getinheritsched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getinheritsched.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getinheritsched.c,v 1.2 1999/11/25 07:01:30 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getinheritsched.c,v 1.3 1999/08/28 00:03:21 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_getschedparam.c b/lib/libpthread/uthread/uthread_attr_getschedparam.c index 1a51d23b069..321d2b646b1 100644 --- a/lib/libpthread/uthread/uthread_attr_getschedparam.c +++ b/lib/libpthread/uthread/uthread_attr_getschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getschedparam.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getschedparam.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getschedparam.c,v 1.3 1999/08/28 00:03:21 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_getschedpolicy.c b/lib/libpthread/uthread/uthread_attr_getschedpolicy.c index 54977df53a0..5be8dcba3bf 100644 --- a/lib/libpthread/uthread/uthread_attr_getschedpolicy.c +++ b/lib/libpthread/uthread/uthread_attr_getschedpolicy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getschedpolicy.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getschedpolicy.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getschedpolicy.c,v 1.3 1999/08/28 00:03:21 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_getscope.c b/lib/libpthread/uthread/uthread_attr_getscope.c index 5dd4772ae46..68bfb0d6654 100644 --- a/lib/libpthread/uthread/uthread_attr_getscope.c +++ b/lib/libpthread/uthread/uthread_attr_getscope.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_getscope.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_getscope.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_getscope.c,v 1.3 1999/08/28 00:03:22 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_getstackaddr.c b/lib/libpthread/uthread/uthread_attr_getstackaddr.c index 0e0cb724b33..1a99e1db8a8 100644 --- a/lib/libpthread/uthread/uthread_attr_getstackaddr.c +++ b/lib/libpthread/uthread/uthread_attr_getstackaddr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_getstackaddr.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_getstackaddr.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_getstackaddr.c,v 1.3 1999/08/28 00:03:22 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_getstacksize.c b/lib/libpthread/uthread/uthread_attr_getstacksize.c index c62ca413e62..f8d2f0b054c 100644 --- a/lib/libpthread/uthread/uthread_attr_getstacksize.c +++ b/lib/libpthread/uthread/uthread_attr_getstacksize.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_getstacksize.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_getstacksize.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_getstacksize.c,v 1.3 1999/08/28 00:03:22 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_init.c b/lib/libpthread/uthread/uthread_attr_init.c index 04cca9e6cb8..2842ef38a6d 100644 --- a/lib/libpthread/uthread/uthread_attr_init.c +++ b/lib/libpthread/uthread/uthread_attr_init.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_init.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_init.c,v 1.2 1999/01/06 05:29:21 d Exp $ + * $FreeBSD: uthread_attr_init.c,v 1.4 1999/08/28 00:03:23 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libpthread/uthread/uthread_attr_setcreatesuspend_np.c b/lib/libpthread/uthread/uthread_attr_setcreatesuspend_np.c index 56c762c32f4..64c30da907e 100644 --- a/lib/libpthread/uthread/uthread_attr_setcreatesuspend_np.c +++ b/lib/libpthread/uthread/uthread_attr_setcreatesuspend_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setcreatesuspend_np.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setcreatesuspend_np.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setcreatesuspend_np.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setdetachstate.c b/lib/libpthread/uthread/uthread_attr_setdetachstate.c index 5f86679e299..1c9e413d85a 100644 --- a/lib/libpthread/uthread/uthread_attr_setdetachstate.c +++ b/lib/libpthread/uthread/uthread_attr_setdetachstate.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setdetachstate.c,v 1.3 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setdetachstate.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setdetachstate.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setinheritsched.c b/lib/libpthread/uthread/uthread_attr_setinheritsched.c index 0e0e015558a..61e0f2f6144 100644 --- a/lib/libpthread/uthread/uthread_attr_setinheritsched.c +++ b/lib/libpthread/uthread/uthread_attr_setinheritsched.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setinheritsched.c,v 1.1 1999/05/26 00:18:22 d Exp $ */ +/* $OpenBSD: uthread_attr_setinheritsched.c,v 1.2 1999/11/25 07:01:31 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setinheritsched.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setprio.c b/lib/libpthread/uthread/uthread_attr_setprio.c index 4a548b3a201..f36e07208c6 100644 --- a/lib/libpthread/uthread/uthread_attr_setprio.c +++ b/lib/libpthread/uthread/uthread_attr_setprio.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setprio.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setprio.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setprio.c,v 1.3 1999/08/28 00:03:24 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setschedparam.c b/lib/libpthread/uthread/uthread_attr_setschedparam.c index 2ff67680fe8..216e1992c8b 100644 --- a/lib/libpthread/uthread/uthread_attr_setschedparam.c +++ b/lib/libpthread/uthread/uthread_attr_setschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setschedparam.c,v 1.1 1999/05/26 00:18:23 d Exp $ */ +/* $OpenBSD: uthread_attr_setschedparam.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setschedparam.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setschedpolicy.c b/lib/libpthread/uthread/uthread_attr_setschedpolicy.c index 2b47a9d9339..f5090d987a9 100644 --- a/lib/libpthread/uthread/uthread_attr_setschedpolicy.c +++ b/lib/libpthread/uthread/uthread_attr_setschedpolicy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setschedpolicy.c,v 1.1 1999/05/26 00:18:23 d Exp $ */ +/* $OpenBSD: uthread_attr_setschedpolicy.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setschedpolicy.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setscope.c b/lib/libpthread/uthread/uthread_attr_setscope.c index 26fdaf6f32c..e40b73afcb8 100644 --- a/lib/libpthread/uthread/uthread_attr_setscope.c +++ b/lib/libpthread/uthread/uthread_attr_setscope.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_attr_setscope.c,v 1.1 1999/05/26 00:18:23 d Exp $ */ +/* $OpenBSD: uthread_attr_setscope.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_attr_setscope.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setstackaddr.c b/lib/libpthread/uthread/uthread_attr_setstackaddr.c index ccef1189723..2dcdd79eee1 100644 --- a/lib/libpthread/uthread/uthread_attr_setstackaddr.c +++ b/lib/libpthread/uthread/uthread_attr_setstackaddr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setstackaddr.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setstackaddr.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setstackaddr.c,v 1.3 1999/08/28 00:03:25 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_attr_setstacksize.c b/lib/libpthread/uthread/uthread_attr_setstacksize.c index ee73ae39a9a..6b1792d02dc 100644 --- a/lib/libpthread/uthread/uthread_attr_setstacksize.c +++ b/lib/libpthread/uthread/uthread_attr_setstacksize.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_attr_setstacksize.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_attr_setstacksize.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_attr_setstacksize.c,v 1.4 1999/08/28 00:03:26 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_autoinit.c b/lib/libpthread/uthread/uthread_autoinit.c index 85aae18b063..850aec29f09 100644 --- a/lib/libpthread/uthread/uthread_autoinit.c +++ b/lib/libpthread/uthread/uthread_autoinit.c @@ -1,7 +1,7 @@ /* * David Leonard, 1998. Public Domain. <david.leonard@csee.uq.edu.au> * - * $OpenBSD: uthread_autoinit.c,v 1.6 1999/03/10 10:05:39 d Exp $ + * $OpenBSD: uthread_autoinit.c,v 1.7 1999/11/25 07:01:32 d Exp $ */ #include <stdio.h> @@ -49,7 +49,7 @@ _thread_dot_init() * found in the .dynamic section into the _INIT field. This then gets * automatically run by GNU ELF's ld.so. */ -#ifdef pmax +#ifdef __mips__ extern int _init() __attribute__((constructor,section (".dynamic"))); int _init() @@ -58,7 +58,7 @@ _init() _thread_init(); return 0; } -#endif /* mips */ +#endif /* __mips__ */ /* * A GNU C installation may know how to automatically run @@ -68,7 +68,7 @@ _init() * the collect2 stage of linkage will inform __main (from libgcc.a) * to call it. */ -#ifdef __GNUC__ +#if defined(__GNUC__) /* && defined(notyet) /* internal compiler error??? */ void _thread_init_constructor __P((void)) __attribute__((constructor)); void _thread_init_constructor() @@ -80,6 +80,6 @@ _thread_init_constructor() /* * Dummy symbol referenced by uthread_init.o so this compilation unit - * is always loaded. + * is always loaded from archives. */ int _thread_autoinit_dummy_decl = 0; diff --git a/lib/libpthread/uthread/uthread_bind.c b/lib/libpthread/uthread/uthread_bind.c index 644b31a0197..fca26b55558 100644 --- a/lib/libpthread/uthread/uthread_bind.c +++ b/lib/libpthread/uthread/uthread_bind.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_bind.c,v 1.4 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_bind.c,v 1.3 1999/02/16 16:39:59 deraadt Exp $ + * $FreeBSD: uthread_bind.c,v 1.5 1999/08/28 00:03:26 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libpthread/uthread/uthread_cancel.c b/lib/libpthread/uthread/uthread_cancel.c index f3a205d1e9e..e43e03bf00b 100644 --- a/lib/libpthread/uthread/uthread_cancel.c +++ b/lib/libpthread/uthread/uthread_cancel.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_cancel.c,v 1.2 1999/11/25 07:01:32 d Exp $ */ /* * David Leonard <d@openbsd.org>, 1999. Public domain. */ @@ -12,35 +13,33 @@ pthread_cancel(pthread) int ret; if ((ret = _find_thread(pthread))) { - } else if (pthread->state == PS_DEAD) - ret = 0; - else { - /* Set the threads's I've-been-cancelled flag: */ - pthread->flags |= PTHREAD_CANCELLING; + } else if ((pthread->flags & PTHREAD_FLAGS_CANCELED) == 0) { + /* Set the thread's I've-been-cancelled flag: */ + pthread->flags |= PTHREAD_FLAGS_CANCELED; /* Check if we need to kick it back into the run queue: */ if ((pthread->cancelstate == PTHREAD_CANCEL_ENABLE) && ((pthread->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) || - (pthread->flags & PTHREAD_AT_CANCEL_POINT))) + (pthread->flags & PTHREAD_FLAGS_CANCELPT))) switch (pthread->state) { - case PS_RUNNING: - /* No need to resume: */ - break; case PS_WAIT_WAIT: case PS_FDR_WAIT: case PS_FDW_WAIT: case PS_SLEEP_WAIT: case PS_SELECT_WAIT: + case PS_POLL_WAIT: case PS_SIGSUSPEND: /* Interrupt and resume: */ pthread->interrupted = 1; + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); PTHREAD_NEW_STATE(pthread,PS_RUNNING); break; case PS_MUTEX_WAIT: case PS_COND_WAIT: + case PS_SIGWAIT: case PS_FDLR_WAIT: case PS_FDLW_WAIT: case PS_FILE_WAIT: - case PS_SIGWAIT: case PS_JOIN: case PS_SUSPENDED: case PS_SIGTHREAD: @@ -48,8 +47,10 @@ pthread_cancel(pthread) /* XXX may be incorrect */ PTHREAD_NEW_STATE(pthread,PS_RUNNING); break; + case PS_RUNNING: + case PS_DEADLOCK: + case PS_SPINBLOCK: case PS_DEAD: - case PS_STATE_MAX: /* Ignore */ break; } @@ -134,14 +135,14 @@ _thread_enter_cancellation_point() /* Look for a cancellation before we block: */ _thread_cancellation_point(); - _thread_run->flags |= PTHREAD_AT_CANCEL_POINT; + _thread_run->flags |= PTHREAD_FLAGS_CANCELPT; } void _thread_leave_cancellation_point() { - _thread_run->flags &=~ PTHREAD_AT_CANCEL_POINT; + _thread_run->flags &=~ PTHREAD_FLAGS_CANCELPT; /* Look for a cancellation after we unblock: */ _thread_cancellation_point(); } @@ -155,9 +156,9 @@ _thread_cancellation_point() { if ((_thread_run->cancelstate == PTHREAD_CANCEL_ENABLE) && - ((_thread_run->flags & (PTHREAD_CANCELLING|PTHREAD_EXITING)) == - PTHREAD_CANCELLING)) { - _thread_run->flags &=~ PTHREAD_CANCELLING; + ((_thread_run->flags & (PTHREAD_FLAGS_CANCELED|PTHREAD_EXITING)) == + PTHREAD_FLAGS_CANCELED)) { + _thread_run->flags &=~ PTHREAD_FLAGS_CANCELED; pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } diff --git a/lib/libpthread/uthread/uthread_clean.c b/lib/libpthread/uthread/uthread_clean.c index c13519b0def..0fc9a272f7f 100644 --- a/lib/libpthread/uthread/uthread_clean.c +++ b/lib/libpthread/uthread/uthread_clean.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_clean.c,v 1.3 1999/11/25 07:01:32 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_clean.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_clean.c,v 1.4 1999/08/28 00:03:26 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_close.c b/lib/libpthread/uthread/uthread_close.c index 6cfde5ca48e..a3dff060aec 100644 --- a/lib/libpthread/uthread/uthread_close.c +++ b/lib/libpthread/uthread/uthread_close.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_close.c,v 1.6 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_close.c,v 1.5 1999/06/09 07:16:16 d Exp $ + * $FreeBSD: uthread_close.c,v 1.7 1999/08/28 00:03:26 peter Exp $ */ +#include <errno.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> @@ -44,16 +46,26 @@ close(int fd) { int flags; int ret; + int status; struct stat sb; + struct fd_table_entry *entry; /* This is a cancelation point: */ _thread_enter_cancellation_point(); - /* Lock the file descriptor while the file is closed: */ - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { - /* Get file descriptor status. */ - _thread_sys_fstat(fd, &sb); - + if ((fd == _thread_kern_pipe[0]) || (fd == _thread_kern_pipe[1])) { + /* + * Don't allow silly programs to close the kernel pipe. + */ + errno = EBADF; + ret = -1; + } + /* + * Lock the file descriptor while the file is closed and get + * the file descriptor status: + */ + else if (((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) && + ((ret = _thread_sys_fstat(fd, &sb)) == 0)) { /* * Check if the file should be left as blocking. * @@ -81,11 +93,14 @@ close(int fd) _thread_sys_fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); } + /* XXX: Assumes well behaved threads. */ + /* XXX: Defer real close to avoid race condition */ + entry = _thread_fd_table[fd]; + _thread_fd_table[fd] = NULL; + free(entry); + /* Close the file descriptor: */ ret = _thread_sys_close(fd); - - free(_thread_fd_table[fd]); - _thread_fd_table[fd] = NULL; } /* No longer in a cancellation point: */ diff --git a/lib/libpthread/uthread/uthread_cond.c b/lib/libpthread/uthread/uthread_cond.c index aef5daac188..aed1adc7662 100644 --- a/lib/libpthread/uthread/uthread_cond.c +++ b/lib/libpthread/uthread/uthread_cond.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_cond.c,v 1.7 1999/06/09 07:06:54 d Exp $ */ +/* $OpenBSD: uthread_cond.c,v 1.8 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_cond.c,v 1.18 1999/08/30 00:02:07 deischen Exp $ */ #include <stdlib.h> #include <errno.h> @@ -45,6 +46,28 @@ static inline pthread_t cond_queue_deq(pthread_cond_t); static inline void cond_queue_remove(pthread_cond_t, pthread_t); static inline void cond_queue_enq(pthread_cond_t, pthread_t); +/* Reinitialize a condition variable to defaults. */ +int +_cond_reinit(pthread_cond_t * cond) +{ + int ret = 0; + + if (cond == NULL) + ret = EINVAL; + else if (*cond == NULL) + ret = pthread_cond_init(cond, NULL); + else { + /* + * Initialize the condition variable structure: + */ + TAILQ_INIT(&(*cond)->c_queue); + (*cond)->c_flags = COND_FLAGS_INITED; + (*cond)->c_type = COND_TYPE_FAST; + (*cond)->c_mutex = NULL; + memset(&(*cond)->lock, 0, sizeof((*cond)->lock)); + } + return (ret); +} int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr) @@ -96,7 +119,7 @@ pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t * cond_attr) pcond->c_flags |= COND_FLAGS_INITED; pcond->c_type = type; pcond->c_mutex = NULL; - _SPINUNLOCK(&pcond->lock); + _SPINLOCK_INIT(&pcond->lock); *cond = pcond; } } @@ -136,6 +159,7 @@ int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) { int rval = 0; + int status; /* This is a cancellation point: */ _thread_enter_cancellation_point(); @@ -149,6 +173,9 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) */ else if (*cond != NULL || (rval = pthread_cond_init(cond,NULL)) == 0) { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + /* * If the condvar was statically allocated, properly * initialize the tail queue. @@ -158,9 +185,6 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex) (*cond)->c_flags |= COND_FLAGS_INITED; } - /* Lock the condition variable structure: */ - _SPINLOCK(&(*cond)->lock); - /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ @@ -242,11 +266,16 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec * abstime) { int rval = 0; + int status; /* This is a cancellation point: */ _thread_enter_cancellation_point(); - if (cond == NULL) + if (cond == NULL || abstime == NULL) + rval = EINVAL; + + else if (abstime->tv_sec < 0 || + abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) rval = EINVAL; /* @@ -255,6 +284,9 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, */ else if (*cond != NULL || (rval = pthread_cond_init(cond,NULL)) == 0) { + /* Lock the condition variable structure: */ + _SPINLOCK(&(*cond)->lock); + /* * If the condvar was statically allocated, properly * initialize the tail queue. @@ -264,10 +296,6 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, (*cond)->c_flags |= COND_FLAGS_INITED; } - - /* Lock the condition variable structure: */ - _SPINLOCK(&(*cond)->lock); - /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ @@ -367,6 +395,7 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, rval = EINVAL; break; } + } /* No longer in a cancellation point: */ @@ -385,6 +414,12 @@ pthread_cond_signal(pthread_cond_t * cond) if (cond == NULL || *cond == NULL) rval = EINVAL; else { + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); + /* Lock the condition variable structure: */ _SPINLOCK(&(*cond)->lock); @@ -419,6 +454,12 @@ pthread_cond_signal(pthread_cond_t * cond) /* Unlock the condition variable structure: */ _SPINUNLOCK(&(*cond)->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -435,14 +476,10 @@ pthread_cond_broadcast(pthread_cond_t * cond) rval = EINVAL; else { /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. In addition, we must assure - * that all threads currently waiting on the condition - * variable are signaled and are not timedout by a - * scheduling signal that causes a preemption. + * Defer signals to protect the scheduling queues + * from access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Lock the condition variable structure: */ _SPINLOCK(&(*cond)->lock); @@ -478,9 +515,11 @@ pthread_cond_broadcast(pthread_cond_t * cond) /* Unlock the condition variable structure: */ _SPINUNLOCK(&(*cond)->lock); - /* Reenable preemption and yield if necessary. + /* + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -498,7 +537,7 @@ cond_queue_deq(pthread_cond_t cond) if ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { TAILQ_REMOVE(&cond->c_queue, pthread, qe); - pthread->flags &= ~PTHREAD_FLAGS_QUEUED; + pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; } return(pthread); @@ -517,9 +556,9 @@ cond_queue_remove(pthread_cond_t cond, pthread_t pthread) * guard against removing the thread from the queue if * it isn't in the queue. */ - if (pthread->flags & PTHREAD_FLAGS_QUEUED) { + if (pthread->flags & PTHREAD_FLAGS_IN_CONDQ) { TAILQ_REMOVE(&cond->c_queue, pthread, qe); - pthread->flags &= ~PTHREAD_FLAGS_QUEUED; + pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ; } } @@ -545,6 +584,6 @@ cond_queue_enq(pthread_cond_t cond, pthread_t pthread) tid = TAILQ_NEXT(tid, qe); TAILQ_INSERT_BEFORE(tid, pthread, qe); } - pthread->flags |= PTHREAD_FLAGS_QUEUED; + pthread->flags |= PTHREAD_FLAGS_IN_CONDQ; } #endif diff --git a/lib/libpthread/uthread/uthread_condattr_destroy.c b/lib/libpthread/uthread/uthread_condattr_destroy.c index 7e6aa2dc124..62e5a4495a8 100644 --- a/lib/libpthread/uthread/uthread_condattr_destroy.c +++ b/lib/libpthread/uthread/uthread_condattr_destroy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_condattr_destroy.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_condattr_destroy.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_condattr_destroy.c,v 1.4 1999/08/28 00:03:27 peter Exp $ */ #include <stdlib.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_condattr_init.c b/lib/libpthread/uthread/uthread_condattr_init.c index 0231bc78f7b..298989ccef4 100644 --- a/lib/libpthread/uthread/uthread_condattr_init.c +++ b/lib/libpthread/uthread/uthread_condattr_init.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_condattr_init.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_condattr_init.c,v 1.2 1999/01/06 05:29:22 d Exp $ + * $FreeBSD: uthread_condattr_init.c,v 1.4 1999/08/28 00:03:27 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libpthread/uthread/uthread_connect.c b/lib/libpthread/uthread/uthread_connect.c index 59fc0724f47..a6a2f367189 100644 --- a/lib/libpthread/uthread/uthread_connect.c +++ b/lib/libpthread/uthread/uthread_connect.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_connect.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_connect.c,v 1.2 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_connect.c,v 1.6 1999/08/28 00:03:28 peter Exp $ */ #include <errno.h> #include <sys/types.h> @@ -43,8 +44,7 @@ int connect(int fd, const struct sockaddr * name, socklen_t namelen) { struct sockaddr tmpname; - int errnolen, ret; - socklen_t tmpnamelen; + int errnolen, ret, tmpnamelen; if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) == 0) { if ((ret = _thread_sys_connect(fd, name, namelen)) < 0) { diff --git a/lib/libpthread/uthread/uthread_create.c b/lib/libpthread/uthread/uthread_create.c index 002f563d14a..67811b2d583 100644 --- a/lib/libpthread/uthread/uthread_create.c +++ b/lib/libpthread/uthread/uthread_create.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_create.c,v 1.11 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_create.c,v 1.10 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_create.c,v 1.19 1999/08/28 00:03:28 peter Exp $ */ #include <errno.h> #include <stdlib.h> @@ -37,22 +38,25 @@ #include <fcntl.h> #include <unistd.h> #include <sys/time.h> +#include <sys/types.h> +#include <sys/mman.h> #ifdef _THREAD_SAFE #include <machine/reg.h> #include <pthread.h> #include "pthread_private.h" -#include "thread_private.h" int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void *(*start_routine) (void *), void *arg) { int f_gc = 0; + int i; int ret = 0; + int status; pthread_t gc_thread; pthread_t new_thread; pthread_attr_t pattr; - void *stack; + struct stack *stack; /* * Locking functions in libc are required when there are @@ -72,31 +76,24 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, } else { pattr = *attr; } - /* Check if a stack was specified in the thread attributes: */ - if ((stack = pattr->stackaddr_attr) != NULL) { - } - /* Allocate memory for the stack: */ - else if ((stack = (void *) malloc(pattr->stacksize_attr)) == NULL) { - /* Insufficient memory to create a thread: */ + /* Create a stack from the specified attributes: */ + if ((stack = _thread_stack_alloc(pattr->stackaddr_attr, + pattr->stacksize_attr)) == NULL) { ret = EAGAIN; free(new_thread); } + /* Check for errors: */ if (ret != 0) { } else { /* Initialise the thread structure: */ memset(new_thread, 0, sizeof(struct pthread)); + _SPINLOCK_INIT(&new_thread->lock); new_thread->slice_usec = -1; new_thread->sig_saved = 0; new_thread->stack = stack; new_thread->start_routine = start_routine; new_thread->arg = arg; -#ifdef _THREAD_RUSAGE - timerclear(&new_thread->ru_utime); - timerclear(&new_thread->ru_stime); -#endif - _SPINUNLOCK(&new_thread->lock); - new_thread->cancelstate = PTHREAD_CANCEL_ENABLE; new_thread->canceltype = PTHREAD_CANCEL_DEFERRED; @@ -106,12 +103,6 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, */ new_thread->magic = PTHREAD_MAGIC; - if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { - PTHREAD_NEW_STATE(new_thread,PS_SUSPENDED); - } else { - PTHREAD_NEW_STATE(new_thread,PS_RUNNING); - } - /* Initialise the thread for signals: */ new_thread->sigmask = _thread_run->sigmask; @@ -123,8 +114,8 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, * returned from a longjmp() to the beginning of * _thread_start(). */ - - _thread_machdep_thread_create(new_thread, _thread_start, pattr); + _thread_machdep_thread_create(new_thread, _thread_start, + pattr); /* Copy the thread attributes: */ memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr)); @@ -135,22 +126,26 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, */ if (new_thread->attr.flags & PTHREAD_INHERIT_SCHED) { /* Copy the scheduling attributes: */ - new_thread->base_priority = _thread_run->base_priority; - new_thread->attr.prio = _thread_run->base_priority; - new_thread->attr.sched_policy = _thread_run->attr.sched_policy; + new_thread->base_priority + = _thread_run->base_priority; + new_thread->attr.prio + = _thread_run->base_priority; + new_thread->attr.sched_policy + = _thread_run->attr.sched_policy; } else { /* * Use just the thread priority, leaving the * other scheduling attributes as their * default values: */ - new_thread->base_priority = new_thread->attr.prio; + new_thread->base_priority + = new_thread->attr.prio; } new_thread->active_priority = new_thread->base_priority; new_thread->inherited_priority = 0; /* Initialise the join queue for the new thread: */ - _thread_queue_init(&(new_thread->join_queue)); + TAILQ_INIT(&(new_thread->join_queue)); /* Initialize the mutex queue: */ TAILQ_INIT(&new_thread->mutexq); @@ -158,32 +153,24 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, /* Initialise hooks in the thread structure: */ new_thread->specific_data = NULL; new_thread->cleanup = NULL; - new_thread->queue = NULL; - new_thread->qnxt = NULL; new_thread->flags = 0; + new_thread->poll_data.nfds = 0; + new_thread->poll_data.fds = NULL; - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues + * from access by the signal handler: + */ + _thread_kern_sig_defer(); /* * Check if the garbage collector thread * needs to be started. */ - f_gc = (_thread_link_list == _thread_initial); + f_gc = (TAILQ_FIRST(&_thread_list) == _thread_initial); /* Add the thread to the linked list of all threads: */ - new_thread->nxt = _thread_link_list; - _thread_link_list = new_thread; - - /* Unlock the thread list: */ - _unlock_thread_list(); - - /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. - */ - _thread_kern_sched_defer(); + TAILQ_INSERT_HEAD(&_thread_list, new_thread, tle); if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) { new_thread->state = PS_SUSPENDED; @@ -194,10 +181,10 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr, } /* - * Reenable preemption and yield if a scheduling - * signal occurred while in the critical region. + * Undefer and handle pending signals, yielding + * if necessary. */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); /* Return a pointer to the thread structure: */ if (thread != NULL) diff --git a/lib/libpthread/uthread/uthread_detach.c b/lib/libpthread/uthread/uthread_detach.c index cb51ff0e43d..181f73b942f 100644 --- a/lib/libpthread/uthread/uthread_detach.c +++ b/lib/libpthread/uthread/uthread_detach.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_detach.c,v 1.5 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_detach.c,v 1.4 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_detach.c,v 1.10 1999/08/28 00:03:28 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -40,6 +41,7 @@ int pthread_detach(pthread_t pthread) { int rval = 0; + int status; pthread_t next_thread; /* Check for invalid calling parameters: */ @@ -53,23 +55,25 @@ pthread_detach(pthread_t pthread) pthread->attr.flags |= PTHREAD_DETACHED; /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Enter a loop to bring all threads off the join queue: */ - while ((next_thread = _thread_queue_deq(&pthread->join_queue)) != NULL) { + while ((next_thread = TAILQ_FIRST(&pthread->join_queue)) != NULL) { + /* Remove the thread from the queue: */ + TAILQ_REMOVE(&pthread->join_queue, next_thread, qe); + /* Make the thread run: */ PTHREAD_NEW_STATE(next_thread,PS_RUNNING); } /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if a + * scheduling signal occurred while in the critical region. */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } else /* Return an error: */ rval = EINVAL; diff --git a/lib/libpthread/uthread/uthread_dup.c b/lib/libpthread/uthread/uthread_dup.c index c24031b8968..8aba9a1dba6 100644 --- a/lib/libpthread/uthread/uthread_dup.c +++ b/lib/libpthread/uthread/uthread_dup.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_dup.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_dup.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_dup.c,v 1.5 1999/08/28 00:03:29 peter Exp $ */ #include <unistd.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_dup2.c b/lib/libpthread/uthread/uthread_dup2.c index 2f34b8f7d32..2dfd9d8c361 100644 --- a/lib/libpthread/uthread/uthread_dup2.c +++ b/lib/libpthread/uthread/uthread_dup2.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_dup2.c,v 1.4 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_dup2.c,v 1.3 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_dup2.c,v 1.6 1999/08/28 00:03:29 peter Exp $ */ #include <errno.h> #include <unistd.h> diff --git a/lib/libpthread/uthread/uthread_equal.c b/lib/libpthread/uthread/uthread_equal.c index 4ec9505d579..54da618366f 100644 --- a/lib/libpthread/uthread/uthread_equal.c +++ b/lib/libpthread/uthread/uthread_equal.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_equal.c,v 1.3 1999/11/25 07:01:33 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_equal.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_equal.c,v 1.3 1999/08/28 00:03:29 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libpthread/uthread/uthread_execve.c b/lib/libpthread/uthread/uthread_execve.c index ba87ccf8d98..b401dd1a145 100644 --- a/lib/libpthread/uthread/uthread_execve.c +++ b/lib/libpthread/uthread/uthread_execve.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_execve.c,v 1.5 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_execve.c,v 1.4 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_execve.c,v 1.8 1999/08/28 00:03:30 peter Exp $ */ #include <errno.h> #include <fcntl.h> @@ -93,6 +94,9 @@ execve(const char *name, char *const * argv, char *const * envp) act.sa_mask = _thread_sigact[i - 1].sa_mask; act.sa_flags = _thread_sigact[i - 1].sa_flags; + /* Ensure the scheduling signal is masked: */ + sigaddset(&act.sa_mask, _SCHED_SIGNAL); + /* Change the signal action for the process: */ _thread_sys_sigaction(i, &act, &oact); } diff --git a/lib/libpthread/uthread/uthread_exit.c b/lib/libpthread/uthread/uthread_exit.c index aba20d5cee2..976ccbbf46d 100644 --- a/lib/libpthread/uthread/uthread_exit.c +++ b/lib/libpthread/uthread/uthread_exit.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_exit.c,v 1.10 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,14 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_exit.c,v 1.9 1999/06/14 23:23:40 d Exp $ + * $FreeBSD: uthread_exit.c,v 1.12 1999/08/30 15:45:42 dt Exp $ */ #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <string.h> -#include <stdio.h> -#include <stdlib.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -77,31 +76,21 @@ void _exit(int status) _thread_sys__exit(status); } -/* - * Append a small number onto the end of a string. - * This avoids the need to use sprintf, which is unsafe sometimes. - */ static void -numlcat(char *s, int num, size_t size) +numlcat(char *s, int l, size_t sz) { - int i; - char digit[7]; + char digit[2]; - if (num<0) { - num = -num; - strlcat(s, "-", size); + /* Inefficient. */ + if (l < 0) { + l = -l; + strlcat(s, "-", sz); } - digit[sizeof digit - 1] = '\0'; - for (i = sizeof digit - 2; i >= 0; i--) { - digit[i] = '0' + (num % 10); - num /= 10; - if (num == 0) - break; - } - if (i<0) - strlcat(s, "inf", size); - else - strlcat(s, &digit[i], size); + if (l >= 10) + numlcat(s, l / 10, sz); + digit[0] = "0123456789"[l % 10]; + digit[1] = '\0'; + strlcat(s, digit, sz); } void @@ -118,30 +107,36 @@ _thread_exit(const char *fname, int lineno, const char *string) strlcat(s, fname, sizeof s); strlcat(s, " (errno = ", sizeof s); numlcat(s, errno, sizeof s); - strlcat(s, ", pid = ", sizeof s); - numlcat(s, _thread_sys_getpid(), sizeof s); strlcat(s, ")\n", sizeof s); /* Write the string to the standard error file descriptor: */ _thread_sys_write(2, s, strlen(s)); - /* Write a dump of the current thread status: */ - _thread_dump_info(); - - /* Try to dump a core file: */ + /* Force this process to exit: */ + /* XXX - Do we want abort to be conditional on _PTHREADS_INVARIANTS? */ +#if defined(_PTHREADS_INVARIANTS) abort(); +#else + _exit(1); +#endif } void pthread_exit(void *status) { + int sig; + long l; pthread_t pthread; /* Check if this thread is already in the process of exiting: */ if ((_thread_run->flags & PTHREAD_EXITING) != 0) { - char msg[128]; - snprintf(msg,sizeof msg,"Thread %p has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!",_thread_run); - PANIC(msg); + PANIC("Thread has called pthread_exit() from a destructor. POSIX 1003.1 1996 s16.2.5.2 does not allow this!"); + } + + /* Free thread-specific poll_data structure, if allocated */ + if (_thread_run->poll_data.fds != NULL) { + free(_thread_run->poll_data.fds); + _thread_run->poll_data.fds = NULL; } /* Flag this thread as exiting: */ @@ -164,22 +159,24 @@ pthread_exit(void *status) } /* - * Guard against preemption by a scheduling signal. A change of - * thread state modifies the waiting and priority queues. + * Defer signals to protect the scheduling queues from access + * by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Check if there are any threads joined to this one: */ - while ((pthread = _thread_queue_deq(&(_thread_run->join_queue))) != NULL) { + while ((pthread = TAILQ_FIRST(&(_thread_run->join_queue))) != NULL) { + /* Remove the thread from the queue: */ + TAILQ_REMOVE(&_thread_run->join_queue, pthread, qe); + /* Wake the joined thread and let it detach this thread: */ PTHREAD_NEW_STATE(pthread,PS_RUNNING); } /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); /* * Lock the garbage collector mutex to ensure that the garbage @@ -189,8 +186,21 @@ pthread_exit(void *status) PANIC("Cannot lock gc mutex"); /* Add this thread to the list of dead threads. */ - _thread_run->nxt_dead = _thread_dead; - _thread_dead = _thread_run; + TAILQ_INSERT_HEAD(&_dead_list, _thread_run, dle); + + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Remove this thread from the thread list: */ + TAILQ_REMOVE(&_thread_list, _thread_run, tle); + + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); /* * Signal the garbage collector thread that there is something diff --git a/lib/libpthread/uthread/uthread_fchmod.c b/lib/libpthread/uthread/uthread_fchmod.c index 454483e410e..652f45c0fd7 100644 --- a/lib/libpthread/uthread/uthread_fchmod.c +++ b/lib/libpthread/uthread/uthread_fchmod.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fchmod.c,v 1.3 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fchmod.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_fchmod.c,v 1.5 1999/08/28 00:03:30 peter Exp $ */ #include <sys/types.h> #include <sys/stat.h> diff --git a/lib/libpthread/uthread/uthread_fchown.c b/lib/libpthread/uthread/uthread_fchown.c index 6b1d4ff1999..ed136ad7ac5 100644 --- a/lib/libpthread/uthread/uthread_fchown.c +++ b/lib/libpthread/uthread/uthread_fchown.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fchown.c,v 1.3 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fchown.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_fchown.c,v 1.5 1999/08/28 00:03:31 peter Exp $ */ #include <sys/types.h> #include <unistd.h> diff --git a/lib/libpthread/uthread/uthread_fcntl.c b/lib/libpthread/uthread/uthread_fcntl.c index c1348a7b27e..7070a564838 100644 --- a/lib/libpthread/uthread/uthread_fcntl.c +++ b/lib/libpthread/uthread/uthread_fcntl.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fcntl.c,v 1.6 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fcntl.c,v 1.5 1999/06/09 07:16:16 d Exp $ + * $FreeBSD: uthread_fcntl.c,v 1.8 1999/08/28 00:03:31 peter Exp $ */ #include <stdarg.h> #include <unistd.h> diff --git a/lib/libpthread/uthread/uthread_fd.c b/lib/libpthread/uthread/uthread_fd.c index 0b51f75b737..39303fc0820 100644 --- a/lib/libpthread/uthread/uthread_fd.c +++ b/lib/libpthread/uthread/uthread_fd.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fd.c,v 1.6 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_fd.c,v 1.10 1999/03/23 05:07:55 jb Exp $ - * $OpenBSD: uthread_fd.c,v 1.5 1999/05/26 00:18:23 d Exp $ + * $FreeBSD: uthread_fd.c,v 1.13 1999/08/28 00:03:31 peter Exp $ * */ #include <errno.h> @@ -80,28 +80,28 @@ _thread_fd_table_init(int fd) ret = -1; } else { /* Initialise the file locks: */ - _SPINUNLOCK(&entry->lock); + _SPINLOCK_INIT(&entry->lock); entry->r_owner = NULL; entry->w_owner = NULL; entry->r_fname = NULL; entry->w_fname = NULL; - entry->r_lineno = 0;; - entry->w_lineno = 0;; - entry->r_lockcount = 0;; - entry->w_lockcount = 0;; + entry->r_lineno = 0; + entry->w_lineno = 0; + entry->r_lockcount = 0; + entry->w_lockcount = 0; /* Initialise the read/write queues: */ - _thread_queue_init(&entry->r_queue); - _thread_queue_init(&entry->w_queue); + TAILQ_INIT(&entry->r_queue); + TAILQ_INIT(&entry->w_queue); /* Get the flags for the file: */ - if (fd >= 3 && (entry->flags = - _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) { + if (((fd >= 3) || (_pthread_stdio_flags[fd] == -1)) && + (entry->flags = _thread_sys_fcntl(fd, F_GETFL, 0)) == -1) { ret = -1; - } + } else { /* Check if a stdio descriptor: */ - if (fd < 3) + if ((fd < 3) && (_pthread_stdio_flags[fd] != -1)) /* * Use the stdio flags read by * _pthread_init() to avoid @@ -170,6 +170,12 @@ _thread_fd_unlock(int fd, int lock_type) */ if ((ret = _thread_fd_table_init(fd)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* * Lock the file descriptor table entry to prevent * other threads for clashing with the current * thread's accesses: @@ -196,8 +202,12 @@ _thread_fd_unlock(int fd, int lock_type) * Get the next thread in the queue for a * read lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->r_owner = _thread_queue_deq(&_thread_fd_table[fd]->r_queue)) == NULL) { + else if ((_thread_fd_table[fd]->r_owner = TAILQ_FIRST(&_thread_fd_table[fd]->r_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->r_queue, + _thread_fd_table[fd]->r_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -234,8 +244,12 @@ _thread_fd_unlock(int fd, int lock_type) * Get the next thread in the queue for a * write lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->w_owner = _thread_queue_deq(&_thread_fd_table[fd]->w_queue)) == NULL) { + else if ((_thread_fd_table[fd]->w_owner = TAILQ_FIRST(&_thread_fd_table[fd]->w_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->w_queue, + _thread_fd_table[fd]->w_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -255,6 +269,12 @@ _thread_fd_unlock(int fd, int lock_type) /* Unlock the file descriptor table entry: */ _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); } /* Nothing to return. */ @@ -296,7 +316,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout) * queue of threads waiting for a * read lock on this file descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->r_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->r_queue, _thread_run, qe); /* * Save the file descriptor details @@ -369,7 +389,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout) * write lock on this file * descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->w_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->w_queue, _thread_run, qe); /* * Save the file descriptor details @@ -431,7 +451,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout) } void -_thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) +_thread_fd_unlock_debug(int fd, int lock_type, const char *fname, int lineno) { int ret; @@ -441,6 +461,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) */ if ((ret = _thread_fd_table_init(fd)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* * Lock the file descriptor table entry to prevent * other threads for clashing with the current * thread's accesses: @@ -467,8 +493,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) * Get the next thread in the queue for a * read lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->r_owner = _thread_queue_deq(&_thread_fd_table[fd]->r_queue)) == NULL) { + else if ((_thread_fd_table[fd]->r_owner = TAILQ_FIRST(&_thread_fd_table[fd]->r_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->r_queue, + _thread_fd_table[fd]->r_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -505,8 +535,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) * Get the next thread in the queue for a * write lock on this file descriptor: */ - else if ((_thread_fd_table[fd]->w_owner = _thread_queue_deq(&_thread_fd_table[fd]->w_queue)) == NULL) { + else if ((_thread_fd_table[fd]->w_owner = TAILQ_FIRST(&_thread_fd_table[fd]->w_queue)) == NULL) { } else { + /* Remove this thread from the queue: */ + TAILQ_REMOVE(&_thread_fd_table[fd]->w_queue, + _thread_fd_table[fd]->w_owner, qe); + /* * Set the state of the new owner of * the thread to running: @@ -526,6 +560,12 @@ _thread_fd_unlock_debug(int fd, int lock_type, char *fname, int lineno) /* Unlock the file descriptor table entry: */ _SPINUNLOCK(&_thread_fd_table[fd]->lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary. + */ + _thread_kern_sig_undefer(); } /* Nothing to return. */ @@ -568,7 +608,7 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, * queue of threads waiting for a * read lock on this file descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->r_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->r_queue, _thread_run, qe); /* * Save the file descriptor details @@ -650,7 +690,7 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout, * write lock on this file * descriptor: */ - _thread_queue_enq(&_thread_fd_table[fd]->w_queue, _thread_run); + TAILQ_INSERT_TAIL(&_thread_fd_table[fd]->w_queue, _thread_run, qe); /* * Save the file descriptor details diff --git a/lib/libpthread/uthread/uthread_file.c b/lib/libpthread/uthread/uthread_file.c index a4b5f922fd7..e1c234fc3d4 100644 --- a/lib/libpthread/uthread/uthread_file.c +++ b/lib/libpthread/uthread/uthread_file.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_file.c,v 1.4 1999/11/25 07:01:34 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_file.c,v 1.6 1998/09/09 16:50:33 dt Exp $ - * $OpenBSD: uthread_file.c,v 1.3 1998/12/23 22:44:39 d Exp $ + * $FreeBSD: uthread_file.c,v 1.9 1999/08/28 00:03:32 peter Exp $ * * POSIX stdio FILE locking functions. These assume that the locking * is only required at FILE structure level, not at file descriptor @@ -46,6 +46,13 @@ #include "pthread_private.h" /* + * Weak symbols for externally visible functions in this file: + */ +#pragma weak flockfile=_flockfile +#pragma weak ftrylockfile=_ftrylockfile +#pragma weak funlockfile=_funlockfile + +/* * The FILE lock structure. The FILE *fp is locked if the owner is * not NULL. If not locked, the file lock structure can be * reassigned to a different file by setting fp. @@ -237,14 +244,14 @@ _flockfile_debug(FILE * fp, const char *fname, int lineno) } void -flockfile(FILE * fp) +_flockfile(FILE * fp) { _flockfile_debug(fp, "?", 1); return; } int -ftrylockfile(FILE * fp) +_ftrylockfile(FILE * fp) { int ret = -1; int idx = file_idx(fp); @@ -255,15 +262,6 @@ ftrylockfile(FILE * fp) /* Lock the hash table: */ _SPINLOCK(&hash_lock); - /* Check if the static array has not been initialised: */ - if (!init_done) { - /* Initialise the global array: */ - memset(flh,0,sizeof(flh)); - - /* Flag the initialisation as complete: */ - init_done = 1; - } - /* Get a pointer to any existing lock for the file: */ if ((p = find_lock(idx, fp)) == NULL) { /* @@ -305,13 +303,20 @@ ftrylockfile(FILE * fp) } void -funlockfile(FILE * fp) +_funlockfile(FILE * fp) { + int status; int idx = file_idx(fp); struct file_lock *p; /* Check if this is a real file: */ if (fp->_file >= 0) { + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + /* Lock the hash table: */ _SPINLOCK(&hash_lock); @@ -319,7 +324,7 @@ funlockfile(FILE * fp) * Get a pointer to the lock for the file and check that * the running thread is the one with the lock: */ - if (init_done && (p = find_lock(idx, fp)) != NULL && + if ((p = find_lock(idx, fp)) != NULL && p->owner == _thread_run) { /* * Check if this thread has locked the FILE @@ -358,6 +363,12 @@ funlockfile(FILE * fp) /* Unlock the hash table: */ _SPINUNLOCK(&hash_lock); + + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); } return; } diff --git a/lib/libpthread/uthread/uthread_find_thread.c b/lib/libpthread/uthread/uthread_find_thread.c index 21a37e679c7..42b561524b9 100644 --- a/lib/libpthread/uthread/uthread_find_thread.c +++ b/lib/libpthread/uthread/uthread_find_thread.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_find_thread.c,v 1.4 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_find_thread.c,v 1.3 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_find_thread.c,v 1.5 1999/08/28 00:03:32 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -47,20 +48,20 @@ _find_thread(pthread_t pthread) /* Invalid thread: */ return(EINVAL); - /* Lock the thread list: */ - _lock_thread_list(); - - /* Point to the first thread in the list: */ - pthread1 = _thread_link_list; + /* + * Defer signals to protect the thread list from access + * by the signal handler: + */ + _thread_kern_sig_defer(); - /* Search for the thread to join to: */ - while (pthread1 != NULL && pthread1 != pthread) { - /* Point to the next thread: */ - pthread1 = pthread1->nxt; + /* Search for the specified thread: */ + TAILQ_FOREACH(pthread1, &_thread_list, tle) { + if (pthread == pthread1) + break; } - /* Unlock the thread list: */ - _unlock_thread_list(); + /* Undefer and handle pending signals, yielding if necessary: */ + _thread_kern_sig_undefer(); /* Return zero if the thread exists: */ return ((pthread1 != NULL) ? 0:ESRCH); @@ -84,13 +85,10 @@ _find_dead_thread(pthread_t pthread) if (pthread_mutex_lock(&_gc_mutex) != 0) PANIC("Cannot lock gc mutex"); - /* Point to the first thread in the list: */ - pthread1 = _thread_dead; - - /* Search for the thread to join to: */ - while (pthread1 != NULL && pthread1 != pthread) { - /* Point to the next thread: */ - pthread1 = pthread1->nxt_dead; + /* Search for the specified thread: */ + TAILQ_FOREACH(pthread1, &_dead_list, dle) { + if (pthread1 == pthread) + break; } /* Unlock the garbage collector mutex: */ diff --git a/lib/libpthread/uthread/uthread_flock.c b/lib/libpthread/uthread/uthread_flock.c index e228762f43c..fed679bd80b 100644 --- a/lib/libpthread/uthread/uthread_flock.c +++ b/lib/libpthread/uthread/uthread_flock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_flock.c,v 1.3 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_flock.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_flock.c,v 1.5 1999/08/28 00:03:32 peter Exp $ */ #include <sys/file.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_fork.c b/lib/libpthread/uthread/uthread_fork.c index ed1566915bd..0e9aef59a20 100644 --- a/lib/libpthread/uthread/uthread_fork.c +++ b/lib/libpthread/uthread/uthread_fork.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fork.c,v 1.7 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,13 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fork.c,v 1.6 1999/06/15 00:07:39 d Exp $ + * $FreeBSD: uthread_fork.c,v 1.14 1999/09/29 15:18:38 marcel Exp $ */ #include <errno.h> #include <string.h> #include <unistd.h> #include <fcntl.h> -#include <stdlib.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -46,10 +46,13 @@ fork(void) int i, flags; pid_t ret; pthread_t pthread; - pthread_t pthread_next; + pthread_t pthread_save; - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues from access + * by the signal handler: + */ + _thread_kern_sig_defer(); /* Fork a new process: */ if ((ret = _thread_sys_fork()) != 0) { @@ -60,7 +63,7 @@ fork(void) _thread_sys_close(_thread_kern_pipe[1]); /* Reset signals pending for the running thread: */ - _thread_run->sigpend = 0; + sigemptyset(&_thread_run->sigpend); /* * Create a pipe that is written to by the signal handler to @@ -90,45 +93,74 @@ fork(void) else if (_thread_sys_fcntl(_thread_kern_pipe[1], F_SETFL, flags | O_NONBLOCK) == -1) { /* Abort this application: */ abort(); + } + /* Reinitialize the GC mutex: */ + else if (_mutex_reinit(&_gc_mutex) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC mutex for forked process"); + } + /* Reinitialize the GC condition variable: */ + else if (_cond_reinit(&_gc_cond) != 0) { + /* Abort this application: */ + PANIC("Cannot initialize GC condvar for forked process"); + } /* Initialize the ready queue: */ - } else if (_pq_init(&_readyq, PTHREAD_MIN_PRIORITY, - PTHREAD_MAX_PRIORITY) != 0) { + else if (_pq_init(&_readyq) != 0) { /* Abort this application: */ - PANIC("Cannot allocate priority ready queue."); + PANIC("Cannot initialize priority ready queue."); } else { - /* Point to the first thread in the list: */ - pthread = _thread_link_list; - /* * Enter a loop to remove all threads other than * the running thread from the thread list: */ + pthread = TAILQ_FIRST(&_thread_list); while (pthread != NULL) { - pthread_next = pthread->nxt; - if (pthread == _thread_run) { - _thread_link_list = pthread; - pthread->nxt = NULL; - } else { - if (pthread->attr.stackaddr_attr == - NULL && pthread->stack != NULL) - /* - * Free the stack of the - * dead thread: - */ - free(pthread->stack); - - if (pthread->specific_data != NULL) - free(pthread->specific_data); - - free(pthread); - } + /* Save the thread to be freed: */ + pthread_save = pthread; + + /* + * Advance to the next thread before + * destroying the current thread: + */ + pthread = TAILQ_NEXT(pthread, dle); + + /* Make sure this isn't the running thread: */ + if (pthread_save != _thread_run) { + /* Remove this thread from the list: */ + TAILQ_REMOVE(&_thread_list, + pthread_save, tle); - /* Point to the next thread: */ - pthread = pthread_next; + if(pthread_save->stack != NULL) + _thread_stack_free(pthread_save->stack); + + if (pthread_save->specific_data != NULL) + free(pthread_save->specific_data); + + if (pthread_save->poll_data.fds != NULL) + free(pthread_save->poll_data.fds); + + free(pthread_save); + } } - /* Re-init the waiting queues. */ + /* Re-init the dead thread list: */ + TAILQ_INIT(&_dead_list); + + /* Re-init the waiting and work queues. */ TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); + + /* Re-init the threads mutex queue: */ + TAILQ_INIT(&_thread_run->mutexq); + + /* No spinlocks yet: */ + _spinblock_count = 0; + + /* Don't queue signals yet: */ + _queue_signals = 0; + + /* Initialize signal handling: */ + _thread_sig_init(); /* Initialize the scheduling switch hook routine: */ _sched_switch_hook = NULL; @@ -137,7 +169,7 @@ fork(void) for (i = 0; i < _thread_dtablesize; i++) { if (_thread_fd_table[i] != NULL) { /* Initialise the file locks: */ - _SPINUNLOCK(&_thread_fd_table[i]->lock); + _SPINLOCK_INIT(&_thread_fd_table[i]->lock); _thread_fd_table[i]->r_owner = NULL; _thread_fd_table[i]->w_owner = NULL; _thread_fd_table[i]->r_fname = NULL; @@ -148,15 +180,17 @@ fork(void) _thread_fd_table[i]->w_lockcount = 0;; /* Initialise the read/write queues: */ - _thread_queue_init(&_thread_fd_table[i]->r_queue); - _thread_queue_init(&_thread_fd_table[i]->w_queue); + TAILQ_INIT(&_thread_fd_table[i]->r_queue); + TAILQ_INIT(&_thread_fd_table[i]->w_queue); } } } } - /* Unock the thread list: */ - _unlock_thread_list(); + /* + * Undefer and handle pending signals, yielding if necessary: + */ + _thread_kern_sig_undefer(); /* Return the process ID: */ return (ret); diff --git a/lib/libpthread/uthread/uthread_fstat.c b/lib/libpthread/uthread/uthread_fstat.c index c1e195f0c69..29b65b5aac6 100644 --- a/lib/libpthread/uthread/uthread_fstat.c +++ b/lib/libpthread/uthread/uthread_fstat.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fstat.c,v 1.3 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fstat.c,v 1.2 1999/01/06 05:29:23 d Exp $ + * $FreeBSD: uthread_fstat.c,v 1.5 1999/08/28 00:03:33 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_fstatfs.c b/lib/libpthread/uthread/uthread_fstatfs.c index cbd590f008a..ba809a5bef4 100644 --- a/lib/libpthread/uthread/uthread_fstatfs.c +++ b/lib/libpthread/uthread/uthread_fstatfs.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fstatfs.c,v 1.3 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fstatfs.c,v 1.2 1999/01/10 23:10:25 d Exp $ + * $FreeBSD: uthread_fstatfs.c,v 1.5 1999/08/28 00:03:33 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_fsync.c b/lib/libpthread/uthread/uthread_fsync.c index 2136d62afe7..cc5cb5046e1 100644 --- a/lib/libpthread/uthread/uthread_fsync.c +++ b/lib/libpthread/uthread/uthread_fsync.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_fsync.c,v 1.5 1999/11/25 07:01:35 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_fsync.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_fsync.c,v 1.5 1999/08/28 00:03:33 peter Exp $ */ #include <unistd.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_gc.c b/lib/libpthread/uthread/uthread_gc.c index 1a2790c74bd..d97b602687c 100644 --- a/lib/libpthread/uthread/uthread_gc.c +++ b/lib/libpthread/uthread/uthread_gc.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_gc.c,v 1.6 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_gc.c,v 1.2 1998/09/30 19:17:51 dt Exp $ - * $OpenBSD: uthread_gc.c,v 1.5 1999/05/26 00:18:24 d Exp $ + * $FreeBSD: uthread_gc.c,v 1.10 1999/08/28 00:03:34 peter Exp $ * * Garbage collector thread. Frees memory allocated for dead threads. * @@ -38,12 +38,10 @@ #include <errno.h> #include <time.h> #include <unistd.h> -#include <stdlib.h> #include <sys/types.h> -#include <sys/time.h> -#ifdef _THREAD_SAFE +#include <sys/types.h> +#include <sys/mman.h> #include <pthread.h> -#include <pthread_np.h> #include "pthread_private.h" pthread_addr_t @@ -71,7 +69,7 @@ _thread_gc(pthread_addr_t arg) f_debug = (getenv("LIBC_R_DEBUG") != NULL); /* Set the name of this thread. */ - pthread_set_name_np(_thread_run, "GC"); + pthread_set_name_np(_thread_run,"GC"); while (!f_done) { /* Check if debugging this application. */ @@ -79,20 +77,26 @@ _thread_gc(pthread_addr_t arg) /* Dump thread info to file. */ _thread_dump_info(); - /* Lock the thread list: */ - _lock_thread_list(); + /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); /* Check if this is the last running thread: */ - if (_thread_link_list == _thread_run && - _thread_link_list->nxt == NULL) + if (TAILQ_FIRST(&_thread_list) == _thread_run && + TAILQ_NEXT(_thread_run, tle) == NULL) /* * This is the last thread, so it can exit * now. */ f_done = 1; - /* Unlock the thread list: */ - _unlock_thread_list(); + /* + * Undefer and handle pending signals, yielding if + * necessary: + */ + _thread_kern_sig_undefer(); /* * Lock the garbage collector mutex which ensures that @@ -105,98 +109,50 @@ _thread_gc(pthread_addr_t arg) p_stack = NULL; pthread_cln = NULL; - /* Point to the first dead thread (if there are any): */ - pthread = _thread_dead; - - /* There is no previous dead thread: */ - pthread_prv = NULL; - /* * Enter a loop to search for the first dead thread that * has memory to free. */ - while (p_stack == NULL && pthread_cln == NULL && - pthread != NULL) { - /* Save a pointer to the next thread: */ - pthread_nxt = pthread->nxt_dead; - + for (pthread = TAILQ_FIRST(&_dead_list); + p_stack == NULL && pthread_cln == NULL && pthread != NULL; + pthread = TAILQ_NEXT(pthread, dle)) { /* Check if the initial thread: */ - if (pthread == _thread_initial) + if (pthread == _thread_initial) { /* Don't destroy the initial thread. */ - pthread_prv = pthread; - + } /* * Check if this thread has detached: */ else if ((pthread->attr.flags & - PTHREAD_DETACHED) != 0) { - /* - * Check if there is no previous dead - * thread: - */ - if (pthread_prv == NULL) - /* - * The dead thread is at the head - * of the list: - */ - _thread_dead = pthread_nxt; - else - /* - * The dead thread is not at the - * head of the list: - */ - pthread_prv->nxt_dead = - pthread->nxt_dead; + PTHREAD_DETACHED) != 0) { + /* Remove this thread from the dead list: */ + TAILQ_REMOVE(&_dead_list, pthread, dle); /* - * Check if the stack was not specified by - * the caller to pthread_create and has not - * been destroyed yet: + * Point to the stack structure that must + * be freed outside the locks: */ - if (pthread->attr.stackaddr_attr == NULL && - pthread->stack != NULL) { - /* - * Point to the stack that must - * be freed outside the locks: - */ + if (pthread->stack != NULL) p_stack = pthread->stack; - } /* * Point to the thread structure that must * be freed outside the locks: */ pthread_cln = pthread; + } else { /* * This thread has not detached, so do - * not destroy it: + * not destroy it. + * + * But we can destroy its stack. */ - pthread_prv = pthread; - - /* - * 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) { - /* - * Point to the stack that must - * be freed outside the locks: - */ + if (pthread->stack != NULL) { p_stack = pthread->stack; - - /* - * NULL the stack pointer now - * that the memory has been freed: - */ pthread->stack = NULL; } } - - /* Point to the next thread: */ - pthread = pthread_nxt; } /* @@ -233,58 +189,18 @@ _thread_gc(pthread_addr_t arg) * locks. */ if (p_stack != NULL) - free(p_stack); - if (pthread_cln != NULL) { - /* Lock the thread list: */ - _lock_thread_list(); - - /* - * Check if the thread is at the head of the - * linked list. - */ - if (_thread_link_list == pthread_cln) - /* There is no previous thread: */ - _thread_link_list = pthread_cln->nxt; - else { - /* Point to the first thread in the list: */ - pthread = _thread_link_list; - - /* - * Enter a loop to find the thread in the - * linked list before the thread that is - * about to be freed. - */ - while (pthread != NULL && - pthread->nxt != pthread_cln) - /* Point to the next thread: */ - pthread = pthread->nxt; - - /* Check that a previous thread was found: */ - if (pthread != NULL) { - /* - * Point the previous thread to - * the one after the thread being - * freed: - */ - pthread->nxt = pthread_cln->nxt; - } - } - - /* Unlock the thread list: */ - _unlock_thread_list(); - - /* Free memory allocated for the thread's name: */ - if (pthread_cln->name != NULL) - free(pthread_cln->name); + /* Free the stack storage. */ + _thread_stack_free(p_stack); + if (pthread_cln != NULL) { /* * Free the memory allocated for the thread * structure. */ + if (pthread_cln->name != NULL) + free(pthread_cln->name); free(pthread_cln); } - } return (NULL); } -#endif /* _THREAD_SAFE */ diff --git a/lib/libpthread/uthread/uthread_getdirentries.c b/lib/libpthread/uthread/uthread_getdirentries.c index 60cd50ec6e2..1dd8d30e651 100644 --- a/lib/libpthread/uthread/uthread_getdirentries.c +++ b/lib/libpthread/uthread/uthread_getdirentries.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getdirentries.c,v 1.3 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getdirentries.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_getdirentries.c,v 1.5 1999/08/28 00:03:34 peter Exp $ */ #include <sys/types.h> #include <dirent.h> diff --git a/lib/libpthread/uthread/uthread_getpeername.c b/lib/libpthread/uthread/uthread_getpeername.c index adb3ab3587b..378f23f7416 100644 --- a/lib/libpthread/uthread/uthread_getpeername.c +++ b/lib/libpthread/uthread/uthread_getpeername.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getpeername.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getpeername.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_getpeername.c,v 1.5 1999/08/28 00:03:34 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> @@ -38,7 +39,7 @@ #include "pthread_private.h" int -getpeername(int fd, struct sockaddr *peer, socklen_t *paddrlen) +getpeername(int fd, struct sockaddr * peer, socklen_t *paddrlen) { int ret; diff --git a/lib/libpthread/uthread/uthread_getprio.c b/lib/libpthread/uthread/uthread_getprio.c index 074bff3e514..725fb0bde54 100644 --- a/lib/libpthread/uthread/uthread_getprio.c +++ b/lib/libpthread/uthread/uthread_getprio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_getprio.c,v 1.3 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_getprio.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_getprio.c,v 1.6 1999/08/28 00:03:35 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_getschedparam.c b/lib/libpthread/uthread/uthread_getschedparam.c index 7905c1960f4..3bfadd1709f 100644 --- a/lib/libpthread/uthread/uthread_getschedparam.c +++ b/lib/libpthread/uthread/uthread_getschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_getschedparam.c,v 1.1 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_getschedparam.c,v 1.2 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_getschedparam.c,v 1.3 1999/08/28 00:03:35 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_getsockname.c b/lib/libpthread/uthread/uthread_getsockname.c index 4ed580dc2cf..683cc910f15 100644 --- a/lib/libpthread/uthread/uthread_getsockname.c +++ b/lib/libpthread/uthread/uthread_getsockname.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getsockname.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getsockname.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_getsockname.c,v 1.5 1999/08/28 00:03:36 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libpthread/uthread/uthread_getsockopt.c b/lib/libpthread/uthread/uthread_getsockopt.c index 7205ac345a3..f73b54780ea 100644 --- a/lib/libpthread/uthread/uthread_getsockopt.c +++ b/lib/libpthread/uthread/uthread_getsockopt.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_getsockopt.c,v 1.4 1999/11/25 07:01:36 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_getsockopt.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_getsockopt.c,v 1.5 1999/08/28 00:03:36 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libpthread/uthread/uthread_init.c b/lib/libpthread/uthread/uthread_init.c index 281808e75f4..cbcb33083ac 100644 --- a/lib/libpthread/uthread/uthread_init.c +++ b/lib/libpthread/uthread/uthread_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_init.c,v 1.9 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_init.c,v 1.10 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_init.c,v 1.18 1999/08/28 00:03:36 peter Exp $ */ #include <errno.h> @@ -37,80 +38,68 @@ #include <string.h> #include <fcntl.h> #include <paths.h> +#include <poll.h> #include <unistd.h> +#include <sys/param.h> +#include <sys/sysctl.h> #include <sys/time.h> #include <sys/ttycom.h> #include <sys/param.h> -#include <sys/ioctl.h> -#include <signal.h> +#include <sys/user.h> +#include <sys/mman.h> #ifdef _THREAD_SAFE #include <machine/reg.h> #include <pthread.h> -#include <pthread_np.h> #include "pthread_private.h" -/* Allocate space for global thread variables here: */ - -static struct pthread kern_thread; -struct pthread * volatile _thread_kern_threadp = &kern_thread; -struct pthread * volatile _thread_run = &kern_thread; -struct pthread * volatile _last_user_thread = &kern_thread; -struct pthread * volatile _thread_single = NULL; -struct pthread * volatile _thread_link_list = NULL; -int _thread_kern_pipe[2] = { -1, -1 }; -int _thread_kern_in_select = 0; -int _thread_kern_in_sched = 0; -struct timeval kern_inc_prio_time = { 0, 0 }; -struct pthread * volatile _thread_dead = NULL; -struct pthread * _thread_initial = NULL; -struct pthread_attr pthread_attr_default = { - SCHED_RR, /* sched_policy */ - 0, /* sched_inherit */ - TIMESLICE_USEC, /* sched_interval */ - PTHREAD_DEFAULT_PRIORITY, /* prio */ - PTHREAD_CREATE_RUNNING, /* suspend */ - PTHREAD_CREATE_JOINABLE, /* flags */ - NULL, /* arg_attr */ - NULL, /* cleanup_attr */ - NULL, /* stackaddr_attr */ - PTHREAD_STACK_DEFAULT /* stacksize_attr */ -}; -struct pthread_mutex_attr pthread_mutexattr_default = { - PTHREAD_MUTEX_DEFAULT, /* m_type */ - PTHREAD_PRIO_NONE, /* m_protocol */ - 0, /* m_ceiling */ - 0 /* m_flags */ -}; -struct pthread_cond_attr pthread_condattr_default = { - COND_TYPE_FAST, /* c_type */ - 0 /* c_flags */ -}; -int _pthread_stdio_flags[3]; -struct fd_table_entry ** _thread_fd_table = NULL; -int _thread_dtablesize = NOFILE_MAX; -pthread_mutex_t _gc_mutex = NULL; -pthread_cond_t _gc_cond = NULL; -struct sigaction _thread_sigact[NSIG]; - -const int dtablecount = 4096/sizeof(struct fd_table_entry); -pq_queue_t _readyq; -_waitingq_t _waitingq; -volatile int _waitingq_check_reqd = 0; -pthread_switch_routine_t _sched_switch_hook = NULL; - -/* Automatic init module. */ +/* Global thread variables. */ +struct pthread _thread_kern_thread; +struct pthread *volatile _thread_run = &_thread_kern_thread; +struct pthread *volatile _last_user_thread = &_thread_kern_thread; +struct pthread *volatile _thread_single = NULL; +_thread_list_t _thread_list = TAILQ_HEAD_INITIALIZER(_thread_list); +int _thread_kern_pipe[2] = { -1, -1 }; +int volatile _queue_signals = 0; +int _thread_kern_in_sched = 0; +struct timeval kern_inc_prio_time = { 0, 0 }; +_thread_list_t _dead_list = TAILQ_HEAD_INITIALIZER(_dead_list); +struct pthread *_thread_initial = NULL; +struct pthread_attr pthread_attr_default = { + SCHED_RR, 0, TIMESLICE_USEC, PTHREAD_DEFAULT_PRIORITY, + PTHREAD_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, + NULL, NULL, NULL, PTHREAD_STACK_DEFAULT }; +struct pthread_mutex_attr pthread_mutexattr_default = { + PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, 0 }; +struct pthread_cond_attr pthread_condattr_default = { COND_TYPE_FAST, 0 }; +int _pthread_stdio_flags[3]; +struct fd_table_entry **_thread_fd_table = NULL; +struct pollfd *_thread_pfd_table = NULL; +const int dtablecount = 4096/sizeof(struct fd_table_entry); +int _thread_dtablesize = 0; +int _clock_res_nsec = CLOCK_RES_NSEC; +pthread_mutex_t _gc_mutex = NULL; +pthread_cond_t _gc_cond = NULL; +struct sigaction _thread_sigact[NSIG]; +pq_queue_t _readyq; +_thread_list_t _waitingq; +_thread_list_t _workq; +volatile int _spinblock_count = 0; +volatile int _sigq_check_reqd = 0; +pthread_switch_routine_t _sched_switch_hook = NULL; +_stack_list_t _stackq; +int _thread_kern_new_state = 0; + extern int _thread_autoinit_dummy_decl; #ifdef GCC_2_8_MADE_THREAD_AWARE -/* see src/gnu/usr.bin/gcc/libgcc2.c */ typedef void *** (*dynamic_handler_allocator)(); extern void __set_dynamic_handler_allocator(dynamic_handler_allocator); static pthread_key_t except_head_key; typedef struct { - void **__dynamic_handler_chain; - void *top_elt[2]; + void **__dynamic_handler_chain; + void *top_elt[2]; } except_struct; static void ***dynamic_allocator_handler_fn() @@ -136,6 +125,9 @@ _thread_init(void) int fd; int flags; int i; + size_t len; + int mib[2]; + struct clockinfo clockinfo; struct sigaction act; /* Check if this function has already been called: */ @@ -152,26 +144,27 @@ _thread_init(void) * Setup a new session for this process which is * assumed to be running as root. */ - if (setsid() == -1) + if (setsid() == -1) PANIC("Can't set session ID"); - if (revoke(_PATH_CONSOLE) != 0) + if (revoke(_PATH_CONSOLE) != 0) PANIC("Can't revoke console"); - if ((fd = _thread_sys_open(_PATH_CONSOLE, O_RDWR)) < 0) + if ((fd = _thread_sys_open(_PATH_CONSOLE, O_RDWR)) < 0) PANIC("Can't open console"); - if (setlogin("root") == -1) + if (setlogin("root") == -1) PANIC("Can't set login to root"); - if (_thread_sys_ioctl(fd,TIOCSCTTY, (char *) NULL) == -1) + if (_thread_sys_ioctl(fd,TIOCSCTTY, (char *) NULL) == -1) PANIC("Can't set controlling terminal"); - if (_thread_sys_dup2(fd,0) == -1 || - _thread_sys_dup2(fd,1) == -1 || - _thread_sys_dup2(fd,2) == -1) + if (_thread_sys_dup2(fd,0) == -1 || + _thread_sys_dup2(fd,1) == -1 || + _thread_sys_dup2(fd,2) == -1) PANIC("Can't dup2"); } /* Get the standard I/O flags before messing with them : */ for (i = 0; i < 3; i++) - if ((_pthread_stdio_flags[i] = - _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) + if (((_pthread_stdio_flags[i] = + _thread_sys_fcntl(i,F_GETFL, NULL)) == -1) && + (errno != EBADF)) PANIC("Cannot get stdio flags"); /* @@ -202,9 +195,8 @@ _thread_init(void) /* Abort this application: */ PANIC("Cannot get kernel write pipe flags"); } - /* Initialize the ready queue: */ - else if (_pq_init(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_MAX_PRIORITY) -!= 0) { + /* Allocate and initialize the ready queue: */ + else if (_pq_alloc(&_readyq, PTHREAD_MIN_PRIORITY, PTHREAD_MAX_PRIORITY) != 0) { /* Abort this application: */ PANIC("Cannot allocate priority ready queue."); } @@ -217,23 +209,19 @@ _thread_init(void) PANIC("Cannot allocate memory for initial thread"); } else { /* Zero the global kernel thread structure: */ - memset(_thread_kern_threadp, 0, sizeof(struct pthread)); - _thread_kern_threadp->magic = PTHREAD_MAGIC; - - /* Set the kernel's name for the debugger: */ - pthread_set_name_np(_thread_kern_threadp, "kern"); - - /* The kernel thread is a library thread: */ - _thread_kern_threadp->flags = PTHREAD_FLAGS_PRIVATE; + memset(&_thread_kern_thread, 0, sizeof(struct pthread)); + _thread_kern_thread.flags = PTHREAD_FLAGS_PRIVATE; + memset(_thread_initial, 0, sizeof(struct pthread)); - /* Initialize the waiting queue: */ + /* Initialize the waiting and work queues: */ TAILQ_INIT(&_waitingq); + TAILQ_INIT(&_workq); /* Initialize the scheduling switch hook routine: */ _sched_switch_hook = NULL; - /* Zero the initial thread: */ - memset(_thread_initial, 0, sizeof(struct pthread)); + /* Initialize the thread stack cache: */ + SLIST_INIT(&_stackq); /* * Write a magic value to the thread structure @@ -250,27 +238,29 @@ _thread_init(void) _thread_initial->state = PS_RUNNING; /* Initialise the queue: */ - _thread_queue_init(&(_thread_initial->join_queue)); + TAILQ_INIT(&(_thread_initial->join_queue)); /* Initialize the owned mutex queue and count: */ TAILQ_INIT(&(_thread_initial->mutexq)); _thread_initial->priority_mutex_count = 0; + /* Give it a useful name */ + pthread_set_name_np(_thread_initial, "main"); + /* Initialise the rest of the fields: */ - _thread_initial->sched_defer_count = 0; - _thread_initial->yield_on_sched_undefer = 0; + _thread_initial->poll_data.nfds = 0; + _thread_initial->poll_data.fds = NULL; + _thread_initial->sig_defer_count = 0; + _thread_initial->yield_on_sig_undefer = 0; _thread_initial->specific_data = NULL; _thread_initial->cleanup = NULL; - _thread_initial->queue = NULL; - _thread_initial->qnxt = NULL; - _thread_initial->nxt = NULL; _thread_initial->flags = 0; _thread_initial->error = 0; _thread_initial->cancelstate = PTHREAD_CANCEL_ENABLE; _thread_initial->canceltype = PTHREAD_CANCEL_DEFERRED; - pthread_set_name_np(_thread_initial, "init"); - _SPINUNLOCK(&_thread_initial->lock); - _thread_link_list = _thread_initial; + _SPINLOCK_INIT(&_thread_initial->lock); + TAILQ_INIT(&_thread_list); + TAILQ_INSERT_HEAD(&_thread_list, _thread_initial, tle); _thread_run = _thread_initial; /* Initialise the global signal action structure: */ @@ -278,6 +268,9 @@ _thread_init(void) act.sa_handler = (void (*) ()) _thread_sig_handler; act.sa_flags = 0; + /* Initialize signal handling: */ + _thread_sig_init(); + /* Enter a loop to get the existing signal status: */ for (i = 1; i < NSIG; i++) { /* Check for signals which cannot be trapped: */ @@ -286,7 +279,7 @@ _thread_init(void) /* Get the signal handler details: */ else if (_thread_sys_sigaction(i, NULL, - &_thread_sigact[i - 1]) != 0) { + &_thread_sigact[i - 1]) != 0) { /* * Abort this process if signal * initialisation fails: @@ -309,6 +302,13 @@ _thread_init(void) PANIC("Cannot initialise signal handler"); } + /* Get the kernel clockrate: */ + mib[0] = CTL_KERN; + mib[1] = KERN_CLOCKRATE; + len = sizeof (struct clockinfo); + if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0) + _clock_res_nsec = clockinfo.tick * 1000; + /* Get the table size: */ if ((_thread_dtablesize = getdtablesize()) < 0) { /* @@ -319,11 +319,22 @@ _thread_init(void) } /* Allocate memory for the file descriptor table: */ if ((_thread_fd_table = (struct fd_table_entry **) malloc(sizeof(struct fd_table_entry *) * _thread_dtablesize)) == NULL) { + /* Avoid accesses to file descriptor table on exit: */ + _thread_dtablesize = 0; + /* * Cannot allocate memory for the file descriptor * table, so abort this process. */ PANIC("Cannot allocate memory for file descriptor table"); + } + /* Allocate memory for the pollfd table: */ + if ((_thread_pfd_table = (struct pollfd *) malloc(sizeof(struct pollfd) * _thread_dtablesize)) == NULL) { + /* + * Cannot allocate memory for the file descriptor + * table, so abort this process. + */ + PANIC("Cannot allocate memory for pollfd table"); } else { /* * Enter a loop to initialise the file descriptor @@ -333,13 +344,21 @@ _thread_init(void) /* Initialise the file descriptor table: */ _thread_fd_table[i] = NULL; } + + /* Initialize stdio file descriptor table entries: */ + for (i = 0; i < 3; i++) { + if ((_thread_fd_table_init(i) != 0) && + (errno != EBADF)) + PANIC("Cannot initialize stdio file " + "descriptor table entry"); + } } } #ifdef GCC_2_8_MADE_THREAD_AWARE /* Create the thread-specific data for the exception linked list. */ if(pthread_key_create(&except_head_key, NULL) != 0) - PANIC("Failed to create thread specific execption head"); + PANIC("Failed to create thread specific execption head"); /* Setup the gcc exception handler per thread. */ __set_dynamic_handler_allocator( dynamic_allocator_handler_fn ); @@ -352,10 +371,8 @@ _thread_init(void) gettimeofday(&kern_inc_prio_time, NULL); - /* Pull in automatic thread unit. */ - _thread_autoinit_dummy_decl = 1; + _thread_autoinit_dummy_decl = 0; return; } - -#endif _THREAD_SAFE +#endif diff --git a/lib/libpthread/uthread/uthread_ioctl.c b/lib/libpthread/uthread/uthread_ioctl.c index e26b7174797..d7daa17196b 100644 --- a/lib/libpthread/uthread/uthread_ioctl.c +++ b/lib/libpthread/uthread/uthread_ioctl.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_ioctl.c,v 1.3 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_ioctl.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_ioctl.c,v 1.6 1999/08/28 00:03:37 peter Exp $ */ #include <stdarg.h> #include <sys/ioctl.h> diff --git a/lib/libpthread/uthread/uthread_join.c b/lib/libpthread/uthread/uthread_join.c index 42ef1f778bc..374a5d45b90 100644 --- a/lib/libpthread/uthread/uthread_join.c +++ b/lib/libpthread/uthread/uthread_join.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_join.c,v 1.6 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_join.c,v 1.5 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_join.c,v 1.9 1999/08/28 00:03:37 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -40,34 +41,26 @@ int pthread_join(pthread_t pthread, void **thread_return) { int ret = 0; - pthread_t pthread1 = NULL; - /* This operation is a cancel point: */ + /* This is a cancellation point: */ _thread_enter_cancellation_point(); /* Check if the caller has specified an invalid thread: */ - if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) { + if (pthread == NULL || pthread->magic != PTHREAD_MAGIC) /* Invalid thread: */ - _thread_leave_cancellation_point(); - return(EINVAL); - } + ret = EINVAL; /* Check if the caller has specified itself: */ - if (pthread == _thread_run) { + else if (pthread == _thread_run) /* Avoid a deadlock condition: */ - _thread_leave_cancellation_point(); - return(EDEADLK); - } + ret = EDEADLK; /* * Find the thread in the list of active threads or in the * list of dead threads: */ - if (_find_thread(pthread) == 0 || - _find_dead_thread(pthread) == 0) - pthread1 = pthread; - - if (pthread1 == NULL) + else if (_find_thread(pthread) != 0 && + _find_dead_thread(pthread) != 0) /* Return an error: */ ret = ESRCH; @@ -79,7 +72,7 @@ pthread_join(pthread_t pthread, void **thread_return) /* Check if the thread is not dead: */ else if (pthread->state != PS_DEAD) { /* Add the running thread to the join queue: */ - _thread_queue_enq(&(pthread->join_queue), _thread_run); + TAILQ_INSERT_TAIL(&(pthread->join_queue), _thread_run, qe); /* Schedule the next thread: */ _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); diff --git a/lib/libpthread/uthread/uthread_kern.c b/lib/libpthread/uthread/uthread_kern.c index 78223f4ad10..56d6c7a3999 100644 --- a/lib/libpthread/uthread/uthread_kern.c +++ b/lib/libpthread/uthread/uthread_kern.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_kern.c,v 1.8 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_kern.c,v 1.9 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -30,22 +30,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_kern.c,v 1.18 1999/05/08 07:50:05 jasone Exp $ + * $FreeBSD: uthread_kern.c,v 1.23 1999/09/29 15:18:39 marcel Exp $ * */ #include <errno.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> +#include <poll.h> #include <unistd.h> #include <setjmp.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/socket.h> -#ifdef _THREAD_RUSAGE -#include <sys/resource.h> -#endif #include <sys/uio.h> #include <sys/syscall.h> #include <fcntl.h> @@ -55,26 +53,34 @@ /* Static function prototype definitions: */ static void -_thread_kern_select(int wait_reqd); +_thread_kern_poll(int wait_reqd); + +static void +dequeue_signals(void); static inline void thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in); +static void +_thread_check_cancel() +{ + if (!(_thread_run->flags & PTHREAD_FLAGS_CANCELPT) && + (_thread_run->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)) + /* + * Check if an async-cancellable thread + * has been cancelled. + */ + _thread_cancellation_point(); +} + void _thread_kern_sched(struct sigcontext * scp) { - pthread_t pthread; - pthread_t pthread_h = NULL; - pthread_t last_thread = NULL; + pthread_t pthread, pthread_h = NULL; struct itimerval itimer; - struct timespec ts; - struct timespec ts1; - struct timeval tv; - struct timeval tv1; -#ifdef _THREAD_RUSAGE - struct rusage ru; - static struct rusage ru_prev; -#endif + struct timespec ts, ts1; + struct timeval tv, tv1; + int set_timer = 0; /* * Flag the pthread kernel as executing scheduler code @@ -91,7 +97,9 @@ _thread_kern_sched(struct sigcontext * scp) */ memcpy(&_thread_run->saved_sigcontext, scp, sizeof(_thread_run->saved_sigcontext)); - /* Save the floating point data: */ + /* + * Save floating point state. + */ _thread_machdep_save_float_state(_thread_run); /* Flag the signal context as the last state saved: */ @@ -112,25 +120,7 @@ _thread_kern_sched(struct sigcontext * scp) thread_run_switch_hook(_last_user_thread, _thread_run); } - if (!(_thread_run->flags & PTHREAD_AT_CANCEL_POINT) && - (_thread_run->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)) { - /* - * Cancelations override signals. - * - * Stick a cancellation point at the start of - * each async-cancellable thread's resumption. - * - * We allow threads woken at cancel points to do their - * own checks. - */ - _thread_cancellation_point(); - } - - /* - * There might be pending signals for this thread, so - * dispatch any that aren't blocked: - */ - _dispatch_signals(); + _thread_check_cancel(); return; } else @@ -144,18 +134,6 @@ _thread_kern_sched(struct sigcontext * scp) /* Save errno. */ _thread_run->error = errno; -#ifdef _THREAD_RUSAGE - /* Accumulate time spent */ - if (getrusage(RUSAGE_SELF, &ru)) - PANIC("Cannot get resource usage"); - timersub(&ru.ru_utime, &ru_prev.ru_utime, &tv); - timeradd(&tv, &_thread_run->ru_utime, &_thread_run->ru_utime); - timersub(&ru.ru_stime, &ru_prev.ru_stime, &tv); - timeradd(&tv, &_thread_run->ru_stime, &_thread_run->ru_stime); - memcpy(&ru_prev.ru_utime, &ru.ru_utime, sizeof ru_prev.ru_utime); - memcpy(&ru_prev.ru_stime, &ru.ru_stime, sizeof ru_prev.ru_stime); -#endif /* _THREAD_RUSAGE */ - /* * Enter a scheduling loop that finds the next thread that is * ready to run. This loop completes when there are no more threads @@ -163,238 +141,208 @@ _thread_kern_sched(struct sigcontext * scp) * either a sigreturn (if the state was saved as a sigcontext) or a * longjmp (if the state was saved by a setjmp). */ - while (_thread_link_list != NULL) { + while (!(TAILQ_EMPTY(&_thread_list))) { /* Get the current time of day: */ gettimeofday(&tv, NULL); TIMEVAL_TO_TIMESPEC(&tv, &ts); /* - * Poll file descriptors to update the state of threads - * waiting on file I/O where data may be available: + * Protect the scheduling queues from access by the signal + * handler. */ - _thread_kern_select(0); + _queue_signals = 1; - /* - * Define the maximum time before a scheduling signal - * is required: - */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = TIMESLICE_USEC; - - /* - * The interval timer is not reloaded when it - * times out. The interval time needs to be - * calculated every time. - */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = 0; - - /* - * Enter a loop to look for sleeping threads that are ready - * or timedout. While we're at it, also find the smallest - * timeout value for threads waiting for a time. - */ - _waitingq_check_reqd = 0; /* reset flag before loop */ - TAILQ_FOREACH(pthread, &_waitingq, pqe) { - /* Check if this thread is ready: */ - if (pthread->state == PS_RUNNING) { - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); - } + if (_thread_run != &_thread_kern_thread) { /* - * Check if this thread is blocked by an - * atomic lock: + * This thread no longer needs to yield the CPU. + */ + _thread_run->yield_on_sig_undefer = 0; + + /* + * Save the current time as the time that the thread + * became inactive: + */ + _thread_run->last_inactive.tv_sec = tv.tv_sec; + _thread_run->last_inactive.tv_usec = tv.tv_usec; + + /* + * Place the currently running thread into the + * appropriate queue(s). */ - else if (pthread->state == PS_SPINBLOCK) { + switch (_thread_run->state) { + case PS_DEAD: /* - * If the lock is available, let - * the thread run. + * Dead threads are not placed in any queue: */ - if (pthread->data.spinlock->access_lock == 0) { - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - } + break; - /* Check if this thread is to timeout: */ - } else if (pthread->state == PS_COND_WAIT || - pthread->state == PS_SLEEP_WAIT || - pthread->state == PS_FDR_WAIT || - pthread->state == PS_FDW_WAIT || - pthread->state == PS_SELECT_WAIT) { - /* Check if this thread is to wait forever: */ - if (pthread->wakeup_time.tv_sec == -1) { - } + case PS_RUNNING: /* - * Check if this thread is to wakeup - * immediately or if it is past its wakeup - * time: + * Runnable threads can't be placed in the + * priority queue until after waiting threads + * are polled (to preserve round-robin + * scheduling). */ - else if ((pthread->wakeup_time.tv_sec == 0 && - pthread->wakeup_time.tv_nsec == 0) || - (ts.tv_sec > pthread->wakeup_time.tv_sec) || - ((ts.tv_sec == pthread->wakeup_time.tv_sec) && - (ts.tv_nsec >= pthread->wakeup_time.tv_nsec))) { + if ((_thread_run->slice_usec != -1) && + (_thread_run->attr.sched_policy != SCHED_FIFO)) { /* - * Check if this thread is waiting on - * select: + * Accumulate the number of microseconds that + * this thread has run for: */ - if (pthread->state == PS_SELECT_WAIT) { - /* - * The select has timed out, so - * zero the file descriptor - * sets: - */ - FD_ZERO(&pthread->data.select_data->readfds); - FD_ZERO(&pthread->data.select_data->writefds); - FD_ZERO(&pthread->data.select_data->exceptfds); - pthread->data.select_data->nfds = 0; - } - /* - * Return an error as an interrupted - * wait: - */ - _thread_seterrno(pthread, EINTR); + _thread_run->slice_usec += + (_thread_run->last_inactive.tv_sec - + _thread_run->last_active.tv_sec) * 1000000 + + _thread_run->last_inactive.tv_usec - + _thread_run->last_active.tv_usec; + + /* Check for time quantum exceeded: */ + if (_thread_run->slice_usec > TIMESLICE_USEC) + _thread_run->slice_usec = -1; + } + break; - /* - * Flag the timeout in the thread - * structure: - */ - pthread->timeout = 1; + /* + * States which do not depend on file descriptor I/O + * operations or timeouts: + */ + case PS_DEADLOCK: + case PS_FDLR_WAIT: + case PS_FDLW_WAIT: + case PS_FILE_WAIT: + case PS_JOIN: + case PS_MUTEX_WAIT: + case PS_SIGSUSPEND: + case PS_SIGTHREAD: + case PS_SIGWAIT: + case PS_SUSPENDED: + case PS_WAIT_WAIT: + /* No timeouts for these states: */ + _thread_run->wakeup_time.tv_sec = -1; + _thread_run->wakeup_time.tv_nsec = -1; - /* - * Change the threads state to allow - * it to be restarted: - */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - } else { - /* - * Calculate the time until this thread - * is ready, allowing for the clock - * resolution: - */ - ts1.tv_sec = pthread->wakeup_time.tv_sec - - ts.tv_sec; - ts1.tv_nsec = pthread->wakeup_time.tv_nsec - - ts.tv_nsec + CLOCK_RES_NSEC; + /* Restart the time slice: */ + _thread_run->slice_usec = -1; - /* - * Check for underflow of the - * nanosecond field: - */ - if (ts1.tv_nsec < 0) { - /* - * Allow for the underflow - * of the nanosecond field: - */ - ts1.tv_sec--; - ts1.tv_nsec += 1000000000; - } - /* - * Check for overflow of the nanosecond - * field: - */ - if (ts1.tv_nsec >= 1000000000) { - /* - * Allow for the overflow of - * the nanosecond field: - */ - ts1.tv_sec++; - ts1.tv_nsec -= 1000000000; - } - /* - * Convert the timespec structure - * to a timeval structure: - */ - TIMESPEC_TO_TIMEVAL(&tv1, &ts1); + /* Insert into the waiting queue: */ + PTHREAD_WAITQ_INSERT(_thread_run); + break; - /* - * Check if the thread will be ready - * sooner than the earliest ones found - * so far: - */ - if (timercmp(&tv1, &itimer.it_value, <)) { - /* - * Update the time value: - */ - itimer.it_value.tv_sec = tv1.tv_sec; - itimer.it_value.tv_usec = tv1.tv_usec; - } - } + /* States which can timeout: */ + case PS_COND_WAIT: + case PS_SLEEP_WAIT: + /* Restart the time slice: */ + _thread_run->slice_usec = -1; + /* Insert into the waiting queue: */ + PTHREAD_WAITQ_INSERT(_thread_run); + break; + + /* States that require periodic work: */ + case PS_SPINBLOCK: + /* No timeouts for this state: */ + _thread_run->wakeup_time.tv_sec = -1; + _thread_run->wakeup_time.tv_nsec = -1; + + /* Increment spinblock count: */ + _spinblock_count++; + + /* fall through */ + case PS_FDR_WAIT: + case PS_FDW_WAIT: + case PS_POLL_WAIT: + case PS_SELECT_WAIT: + /* Restart the time slice: */ + _thread_run->slice_usec = -1; + + /* Insert into the waiting queue: */ + PTHREAD_WAITQ_INSERT(_thread_run); + + /* Insert into the work queue: */ + PTHREAD_WORKQ_INSERT(_thread_run); } } - /* Check if there is a current thread: */ - if (_thread_run != _thread_kern_threadp) { - /* - * This thread no longer needs to yield the CPU. - */ - _thread_run->yield_on_sched_undefer = 0; + /* Unprotect the scheduling queues: */ + _queue_signals = 0; - /* - * Save the current time as the time that the thread - * became inactive: - */ - _thread_run->last_inactive.tv_sec = tv.tv_sec; - _thread_run->last_inactive.tv_usec = tv.tv_usec; + /* + * Poll file descriptors to update the state of threads + * waiting on file I/O where data may be available: + */ + _thread_kern_poll(0); + /* Protect the scheduling queues: */ + _queue_signals = 1; + + /* + * Wake up threads that have timedout. This has to be + * done after polling in case a thread does a poll or + * select with zero time. + */ + PTHREAD_WAITQ_SETACTIVE(); + while (((pthread = TAILQ_FIRST(&_waitingq)) != NULL) && + (pthread->wakeup_time.tv_sec != -1) && + (((pthread->wakeup_time.tv_sec == 0) && + (pthread->wakeup_time.tv_nsec == 0)) || + (pthread->wakeup_time.tv_sec < ts.tv_sec) || + ((pthread->wakeup_time.tv_sec == ts.tv_sec) && + (pthread->wakeup_time.tv_nsec <= ts.tv_nsec)))) { + switch (pthread->state) { + case PS_POLL_WAIT: + case PS_SELECT_WAIT: + /* Return zero file descriptors ready: */ + pthread->data.poll_data->nfds = 0; + /* fall through */ + default: + /* + * Remove this thread from the waiting queue + * (and work queue if necessary) and place it + * in the ready queue. + */ + PTHREAD_WAITQ_CLEARACTIVE(); + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread, PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); + break; + } /* - * Accumulate the number of microseconds that this - * thread has run for: + * Flag the timeout in the thread structure: */ - if ((_thread_run->slice_usec != -1) && - (_thread_run->attr.sched_policy != SCHED_FIFO)) { - _thread_run->slice_usec += - (_thread_run->last_inactive.tv_sec - - _thread_run->last_active.tv_sec) * 1000000 + - _thread_run->last_inactive.tv_usec - - _thread_run->last_active.tv_usec; - - /* Check for time quantum exceeded: */ - if (_thread_run->slice_usec > TIMESLICE_USEC) - _thread_run->slice_usec = -1; - } - if (_thread_run->state == PS_RUNNING) { - if (_thread_run->slice_usec == -1) { - /* - * The thread exceeded its time - * quantum or it yielded the CPU; - * place it at the tail of the - * queue for its priority. - */ - PTHREAD_PRIOQ_INSERT_TAIL(_thread_run); - } else { - /* - * The thread hasn't exceeded its - * interval. Place it at the head - * of the queue for its priority. - */ - PTHREAD_PRIOQ_INSERT_HEAD(_thread_run); - } - } - else if (_thread_run->state == PS_DEAD) { + pthread->timeout = 1; + } + PTHREAD_WAITQ_CLEARACTIVE(); + + /* + * Check if there is a current runnable thread that isn't + * already in the ready queue: + */ + if ((_thread_run != &_thread_kern_thread) && + (_thread_run->state == PS_RUNNING) && + ((_thread_run->flags & PTHREAD_FLAGS_IN_PRIOQ) == 0)) { + if (_thread_run->slice_usec == -1) { /* - * Don't add dead threads to the waiting - * queue, because when they're reaped, it - * will corrupt the queue. + * The thread exceeded its time + * quantum or it yielded the CPU; + * place it at the tail of the + * queue for its priority. */ - } - else { + PTHREAD_PRIOQ_INSERT_TAIL(_thread_run); + } else { /* - * This thread has changed state and needs - * to be placed in the waiting queue. + * The thread hasn't exceeded its + * interval. Place it at the head + * of the queue for its priority. */ - PTHREAD_WAITQ_INSERT(_thread_run); - - /* Restart the time slice: */ - _thread_run->slice_usec = -1; + PTHREAD_PRIOQ_INSERT_HEAD(_thread_run); } } /* * Get the highest priority thread in the ready queue. */ - pthread_h = PTHREAD_PRIOQ_FIRST; + pthread_h = PTHREAD_PRIOQ_FIRST(); /* Check if there are no threads ready to run: */ if (pthread_h == NULL) { @@ -403,20 +351,86 @@ _thread_kern_sched(struct sigcontext * scp) * the running thread to point to the global kernel * thread structure: */ - _thread_run = _thread_kern_threadp; + _thread_run = &_thread_kern_thread; + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; /* * There are no threads ready to run, so wait until * something happens that changes this condition: */ - _thread_kern_select(1); - } else { + _thread_kern_poll(1); + } + else { + /* Remove the thread from the ready queue: */ + PTHREAD_PRIOQ_REMOVE(pthread_h); + + /* Get first thread on the waiting list: */ + pthread = TAILQ_FIRST(&_waitingq); + + /* Check to see if there is more than one thread: */ + if (pthread_h != TAILQ_FIRST(&_thread_list) || + TAILQ_NEXT(pthread_h, tle) != NULL) + set_timer = 1; + else + set_timer = 0; + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; + + /* + * Check for signals queued while the scheduling + * queues were protected: + */ + while (_sigq_check_reqd != 0) { + /* Clear before handling queued signals: */ + _sigq_check_reqd = 0; + + /* Protect the scheduling queues again: */ + _queue_signals = 1; + + dequeue_signals(); + + /* + * Check for a higher priority thread that + * became runnable due to signal handling. + */ + if (((pthread = PTHREAD_PRIOQ_FIRST()) != NULL) && + (pthread->active_priority > pthread_h->active_priority)) { + /* + * Insert the lower priority thread + * at the head of its priority list: + */ + PTHREAD_PRIOQ_INSERT_HEAD(pthread_h); + + /* Remove the thread from the ready queue: */ + PTHREAD_PRIOQ_REMOVE(pthread); + + /* There's a new thread in town: */ + pthread_h = pthread; + } + + /* Get first thread on the waiting list: */ + pthread = TAILQ_FIRST(&_waitingq); + + /* + * Check to see if there is more than one + * thread: + */ + if (pthread_h != TAILQ_FIRST(&_thread_list) || + TAILQ_NEXT(pthread_h, tle) != NULL) + set_timer = 1; + else + set_timer = 0; + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; + } + /* Make the selected thread the current thread: */ _thread_run = pthread_h; - /* Remove the thread from the ready queue. */ - PTHREAD_PRIOQ_REMOVE(_thread_run); - /* * Save the current time as the time that the thread * became active: @@ -425,6 +439,76 @@ _thread_kern_sched(struct sigcontext * scp) _thread_run->last_active.tv_usec = tv.tv_usec; /* + * Define the maximum time before a scheduling signal + * is required: + */ + itimer.it_value.tv_sec = 0; + itimer.it_value.tv_usec = TIMESLICE_USEC; + + /* + * The interval timer is not reloaded when it + * times out. The interval time needs to be + * calculated every time. + */ + itimer.it_interval.tv_sec = 0; + itimer.it_interval.tv_usec = 0; + + /* Get first thread on the waiting list: */ + if ((pthread != NULL) && + (pthread->wakeup_time.tv_sec != -1)) { + /* + * Calculate the time until this thread + * is ready, allowing for the clock + * resolution: + */ + ts1.tv_sec = pthread->wakeup_time.tv_sec + - ts.tv_sec; + ts1.tv_nsec = pthread->wakeup_time.tv_nsec + - ts.tv_nsec + _clock_res_nsec; + + /* + * Check for underflow of the nanosecond field: + */ + while (ts1.tv_nsec < 0) { + /* + * Allow for the underflow of the + * nanosecond field: + */ + ts1.tv_sec--; + ts1.tv_nsec += 1000000000; + } + /* + * Check for overflow of the nanosecond field: + */ + while (ts1.tv_nsec >= 1000000000) { + /* + * Allow for the overflow of the + * nanosecond field: + */ + ts1.tv_sec++; + ts1.tv_nsec -= 1000000000; + } + /* + * Convert the timespec structure to a + * timeval structure: + */ + TIMESPEC_TO_TIMEVAL(&tv1, &ts1); + + /* + * Check if the thread will be ready + * sooner than the earliest ones found + * so far: + */ + if (timercmp(&tv1, &itimer.it_value, <)) { + /* + * Update the time value: + */ + itimer.it_value.tv_sec = tv1.tv_sec; + itimer.it_value.tv_usec = tv1.tv_usec; + } + } + + /* * Check if this thread is running for the first time * or running again after using its full time slice * allocation: @@ -435,7 +519,7 @@ _thread_kern_sched(struct sigcontext * scp) } /* Check if there is more than one thread: */ - if (_thread_run != _thread_link_list || _thread_run->nxt != NULL) { + if (set_timer != 0) { /* * Start the interval timer for the * calculated time interval: @@ -454,8 +538,9 @@ _thread_kern_sched(struct sigcontext * scp) /* Check if a signal context was saved: */ if (_thread_run->sig_saved == 1) { - - /* Restore the floating point state: */ + /* + * Restore floating point state. + */ _thread_machdep_restore_float_state(_thread_run); /* @@ -474,13 +559,14 @@ _thread_kern_sched(struct sigcontext * scp) _thread_run); } _thread_sys_sigreturn(&_thread_run->saved_sigcontext); - } else + } else { /* * Do a longjmp to restart the thread that * was context switched out (by a longjmp to * a different thread): */ _thread_machdep_longjmp(_thread_run->saved_jmp_buf, 1); + } /* This point should not be reached. */ PANIC("Thread has returned from sigreturn or longjmp"); @@ -494,6 +580,19 @@ _thread_kern_sched(struct sigcontext * scp) void _thread_kern_sched_state(enum pthread_state state, const char *fname, int lineno) { + /* + * Flag the pthread kernel as executing scheduler code + * to avoid a scheduler signal from interrupting this + * execution and calling the scheduler again. + */ + _thread_kern_in_sched = 1; + + /* + * Prevent the signal handler from fiddling with this thread + * before its state is set and is placed into the proper queue. + */ + _queue_signals = 1; + /* Change the state of the current thread: */ _thread_run->state = state; _thread_run->fname = fname; @@ -508,6 +607,20 @@ void _thread_kern_sched_state_unlock(enum pthread_state state, spinlock_t *lock, char *fname, int lineno) { + /* + * Flag the pthread kernel as executing scheduler code + * to avoid a scheduler signal from interrupting this + * execution and calling the scheduler again. + */ + _thread_kern_in_sched = 1; + + /* + * Prevent the signal handler from fiddling with this thread + * before its state is set and it is placed into the proper + * queue(s). + */ + _queue_signals = 1; + /* Change the state of the current thread: */ _thread_run->state = state; _thread_run->fname = fname; @@ -521,385 +634,193 @@ _thread_kern_sched_state_unlock(enum pthread_state state, } static void -_thread_kern_select(int wait_reqd) +_thread_kern_poll(int wait_reqd) { - char bufr[128]; - fd_set fd_set_except; - fd_set fd_set_read; - fd_set fd_set_write; int count = 0; - int count_dec; - int found_one; - int i; - int nfds = -1; - int settimeout; - pthread_t pthread; - ssize_t num; + int i, found; + int kern_pipe_added = 0; + int nfds = 0; + int timeout_ms = 0; + struct pthread *pthread; struct timespec ts; - struct timespec ts1; - struct timeval *p_tv; struct timeval tv; - struct timeval tv1; - - /* Zero the file descriptor sets: */ - FD_ZERO(&fd_set_read); - FD_ZERO(&fd_set_write); - FD_ZERO(&fd_set_except); /* Check if the caller wants to wait: */ - if (wait_reqd) { - /* - * Add the pthread kernel pipe file descriptor to the read - * set: - */ - FD_SET(_thread_kern_pipe[0], &fd_set_read); - nfds = _thread_kern_pipe[0]; - + if (wait_reqd == 0) { + timeout_ms = 0; + } + else { /* Get the current time of day: */ gettimeofday(&tv, NULL); TIMEVAL_TO_TIMESPEC(&tv, &ts); + + _queue_signals = 1; + pthread = TAILQ_FIRST(&_waitingq); + _queue_signals = 0; + + if ((pthread == NULL) || (pthread->wakeup_time.tv_sec == -1)) { + /* + * Either there are no threads in the waiting queue, + * or there are no threads that can timeout. + */ + timeout_ms = -1; + } + else { + /* + * Calculate the time left for the next thread to + * timeout allowing for the clock resolution: + */ + timeout_ms = ((pthread->wakeup_time.tv_sec - ts.tv_sec) * + 1000) + ((pthread->wakeup_time.tv_nsec - ts.tv_nsec + + _clock_res_nsec) / 1000000); + /* + * Don't allow negative timeouts: + */ + if (timeout_ms < 0) + timeout_ms = 0; + } } - /* Initialise the time value structure: */ - tv.tv_sec = 0; - tv.tv_usec = 0; + + /* Protect the scheduling queues: */ + _queue_signals = 1; /* - * Enter a loop to process threads waiting on either file descriptors - * or times: + * Check to see if the signal queue needs to be walked to look + * for threads awoken by a signal while in the scheduler. */ - _waitingq_check_reqd = 0; /* reset flag before loop */ - TAILQ_FOREACH (pthread, &_waitingq, pqe) { - /* Assume that this state does not time out: */ - settimeout = 0; + if (_sigq_check_reqd != 0) { + /* Reset flag before handling queued signals: */ + _sigq_check_reqd = 0; - /* Process according to thread state: */ - switch (pthread->state) { + dequeue_signals(); + } + + /* + * Check for a thread that became runnable due to a signal: + */ + if (PTHREAD_PRIOQ_FIRST() != NULL) { /* - * States which do not depend on file descriptor I/O - * operations or timeouts: + * Since there is at least one runnable thread, + * disable the wait. */ - case PS_DEAD: - case PS_DEADLOCK: - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FILE_WAIT: - case PS_JOIN: - case PS_MUTEX_WAIT: - case PS_SIGTHREAD: - case PS_SIGWAIT: - case PS_STATE_MAX: - case PS_WAIT_WAIT: - case PS_SUSPENDED: - case PS_SIGSUSPEND: - /* Nothing to do here. */ - break; + timeout_ms = 0; + } + + /* + * Form the poll table: + */ + nfds = 0; + if (timeout_ms != 0) { + /* Add the kernel pipe to the poll table: */ + _thread_pfd_table[nfds].fd = _thread_kern_pipe[0]; + _thread_pfd_table[nfds].events = POLLRDNORM; + _thread_pfd_table[nfds].revents = 0; + nfds++; + kern_pipe_added = 1; + } - case PS_RUNNING: + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { + switch (pthread->state) { + case PS_SPINBLOCK: /* - * A signal occurred and made this thread ready - * while in the scheduler or while the scheduling - * queues were protected. + * If the lock is available, let the thread run. */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); + /* One less thread in a spinblock state: */ + _spinblock_count--; + /* + * Since there is at least one runnable + * thread, disable the wait. + */ + timeout_ms = 0; + } break; /* File descriptor read wait: */ case PS_FDR_WAIT: - /* Add the file descriptor to the read set: */ - FD_SET(pthread->data.fd.fd, &fd_set_read); - - /* - * Check if this file descriptor is greater than any - * of those seen so far: - */ - if (pthread->data.fd.fd > nfds) { - /* Remember this file descriptor: */ - nfds = pthread->data.fd.fd; + /* Limit number of polled files to table size: */ + if (nfds < _thread_dtablesize) { + _thread_pfd_table[nfds].events = POLLRDNORM; + _thread_pfd_table[nfds].fd = pthread->data.fd.fd; + nfds++; } - /* Increment the file descriptor count: */ - count++; - - /* This state can time out: */ - settimeout = 1; break; /* File descriptor write wait: */ case PS_FDW_WAIT: - /* Add the file descriptor to the write set: */ - FD_SET(pthread->data.fd.fd, &fd_set_write); - - /* - * Check if this file descriptor is greater than any - * of those seen so far: - */ - if (pthread->data.fd.fd > nfds) { - /* Remember this file descriptor: */ - nfds = pthread->data.fd.fd; + /* Limit number of polled files to table size: */ + if (nfds < _thread_dtablesize) { + _thread_pfd_table[nfds].events = POLLWRNORM; + _thread_pfd_table[nfds].fd = pthread->data.fd.fd; + nfds++; } - /* Increment the file descriptor count: */ - count++; - - /* This state can time out: */ - settimeout = 1; - break; - - /* States that time out: */ - case PS_SLEEP_WAIT: - case PS_COND_WAIT: - /* Flag a timeout as required: */ - settimeout = 1; break; - /* Select wait: */ + /* File descriptor poll or select wait: */ + case PS_POLL_WAIT: case PS_SELECT_WAIT: - /* - * Enter a loop to process each file descriptor in - * the thread-specific file descriptor sets: - */ - for (i = 0; i < pthread->data.select_data->nfds; i++) { - /* - * Check if this file descriptor is set for - * exceptions: - */ - if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) { - /* - * Add the file descriptor to the - * exception set: - */ - FD_SET(i, &fd_set_except); - - /* - * Increment the file descriptor - * count: - */ - count++; - - /* - * Check if this file descriptor is - * greater than any of those seen so - * far: - */ - if (i > nfds) { - /* - * Remember this file - * descriptor: - */ - nfds = i; - } - } - /* - * Check if this file descriptor is set for - * write: - */ - if (FD_ISSET(i, &pthread->data.select_data->writefds)) { - /* - * Add the file descriptor to the - * write set: - */ - FD_SET(i, &fd_set_write); - - /* - * Increment the file descriptor - * count: - */ - count++; - - /* - * Check if this file descriptor is - * greater than any of those seen so - * far: - */ - if (i > nfds) { - /* - * Remember this file - * descriptor: - */ - nfds = i; - } - } - /* - * Check if this file descriptor is set for - * read: - */ - if (FD_ISSET(i, &pthread->data.select_data->readfds)) { - /* - * Add the file descriptor to the - * read set: - */ - FD_SET(i, &fd_set_read); - - /* - * Increment the file descriptor - * count: - */ - count++; - - /* - * Check if this file descriptor is - * greater than any of those seen so - * far: - */ - if (i > nfds) { - /* - * Remember this file - * descriptor: - */ - nfds = i; - } + /* Limit number of polled files to table size: */ + if (pthread->data.poll_data->nfds + nfds < + _thread_dtablesize) { + for (i = 0; i < pthread->data.poll_data->nfds; i++) { + _thread_pfd_table[nfds + i].fd = + pthread->data.poll_data->fds[i].fd; + _thread_pfd_table[nfds + i].events = + pthread->data.poll_data->fds[i].events; } + nfds += pthread->data.poll_data->nfds; } - - /* This state can time out: */ - settimeout = 1; break; - } - - /* - * Check if the caller wants to wait and if the thread state - * is one that times out: - */ - if (wait_reqd && settimeout) { - /* Check if this thread wants to wait forever: */ - if (pthread->wakeup_time.tv_sec == -1) { - } - /* Check if this thread doesn't want to wait at all: */ - else if (pthread->wakeup_time.tv_sec == 0 && - pthread->wakeup_time.tv_nsec == 0) { - /* Override the caller's request to wait: */ - wait_reqd = 0; - } else { - /* - * Calculate the time until this thread is - * ready, allowing for the clock resolution: - */ - ts1.tv_sec = pthread->wakeup_time.tv_sec - ts.tv_sec; - ts1.tv_nsec = pthread->wakeup_time.tv_nsec - ts.tv_nsec + - CLOCK_RES_NSEC; - /* - * Check for underflow of the nanosecond - * field: - */ - if (ts1.tv_nsec < 0) { - /* - * Allow for the underflow of the - * nanosecond field: - */ - ts1.tv_sec--; - ts1.tv_nsec += 1000000000; - } - /* - * Check for overflow of the nanosecond - * field: - */ - if (ts1.tv_nsec >= 1000000000) { - /* - * Allow for the overflow of the - * nanosecond field: - */ - ts1.tv_sec++; - ts1.tv_nsec -= 1000000000; - } - /* - * Convert the timespec structure to a - * timeval structure: - */ - TIMESPEC_TO_TIMEVAL(&tv1, &ts1); - - /* - * Check if no time value has been found yet, - * or if the thread will be ready sooner that - * the earliest one found so far: - */ - if ((tv.tv_sec == 0 && tv.tv_usec == 0) || timercmp(&tv1, &tv, <)) { - /* Update the time value: */ - tv.tv_sec = tv1.tv_sec; - tv.tv_usec = tv1.tv_usec; - } - } + /* Other states do not depend on file I/O. */ + default: + break; } } + PTHREAD_WAITQ_CLEARACTIVE(); - /* Check if the caller wants to wait: */ - if (wait_reqd) { - /* Check if no threads were found with timeouts: */ - if (tv.tv_sec == 0 && tv.tv_usec == 0) { - /* Wait forever: */ - p_tv = NULL; - } else { - /* - * Point to the time value structure which contains - * the earliest time that a thread will be ready: - */ - p_tv = &tv; - } + /* + * Wait for a file descriptor to be ready for read, write, or + * an exception, or a timeout to occur: + */ + count = _thread_sys_poll(_thread_pfd_table, nfds, timeout_ms); + if (kern_pipe_added != 0) /* - * Flag the pthread kernel as in a select. This is to avoid - * the window between the next statement that unblocks - * signals and the select statement which follows. + * Remove the pthread kernel pipe file descriptor + * from the pollfd table: */ - _thread_kern_in_select = 1; + nfds = 1; + else + nfds = 0; + /* + * Check if it is possible that there are bytes in the kernel + * read pipe waiting to be read: + */ + if (count < 0 || ((kern_pipe_added != 0) && + (_thread_pfd_table[0].revents & POLLRDNORM))) { /* - * Wait for a file descriptor to be ready for read, write, or - * an exception, or a timeout to occur: + * If the kernel read pipe was included in the + * count: */ - count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv); + if (count > 0) { + /* Decrement the count of file descriptors: */ + count--; + } - /* Reset the kernel in select flag: */ - _thread_kern_in_select = 0; + if (_sigq_check_reqd != 0) { + /* Reset flag before handling signals: */ + _sigq_check_reqd = 0; - /* - * Check if it is possible that there are bytes in the kernel - * read pipe waiting to be read: - */ - if (count < 0 || FD_ISSET(_thread_kern_pipe[0], &fd_set_read)) { - /* - * Check if the kernel read pipe was included in the - * count: - */ - if (count > 0) { - /* - * Remove the kernel read pipe from the - * count: - */ - FD_CLR(_thread_kern_pipe[0], &fd_set_read); - - /* Decrement the count of file descriptors: */ - count--; - } - /* - * Enter a loop to read (and trash) bytes from the - * pthread kernel pipe: - */ - while ((num = _thread_sys_read(_thread_kern_pipe[0], bufr, sizeof(bufr))) > 0) { - /* - * The buffer read contains one byte per - * signal and each byte is the signal number. - * This data is not used, but the fact that - * the signal handler wrote to the pipe *is* - * used to cause the _select call - * to complete if the signal occurred between - * the time when signals were unblocked and - * the _select select call being - * made. - */ - } + dequeue_signals(); } } - /* Check if there are file descriptors to poll: */ - else if (count > 0) { - /* - * Point to the time value structure which has been zeroed so - * that the call to _select will not wait: - */ - p_tv = &tv; - - /* Poll file descrptors without wait: */ - count = _thread_sys_select(nfds + 1, &fd_set_read, &fd_set_write, &fd_set_except, p_tv); - } /* * Check if any file descriptors are ready: @@ -908,302 +829,133 @@ _thread_kern_select(int wait_reqd) /* * Enter a loop to look for threads waiting on file * descriptors that are flagged as available by the - * _select syscall: + * _poll syscall: */ - TAILQ_FOREACH (pthread, &_waitingq, pqe) { - /* Process according to thread state: */ + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { switch (pthread->state) { - /* - * States which do not depend on file - * descriptor I/O operations: - */ - case PS_COND_WAIT: - case PS_DEAD: - case PS_DEADLOCK: - case PS_FDLR_WAIT: - case PS_FDLW_WAIT: - case PS_FILE_WAIT: - case PS_JOIN: - case PS_MUTEX_WAIT: - case PS_SIGWAIT: - case PS_SLEEP_WAIT: - case PS_WAIT_WAIT: - case PS_SIGTHREAD: - case PS_STATE_MAX: - case PS_SUSPENDED: - case PS_SIGSUSPEND: - /* Nothing to do here. */ - break; - - case PS_RUNNING: + case PS_SPINBLOCK: /* - * A signal occurred and made this thread - * ready while in the scheduler. + * If the lock is available, let the thread run. */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); - break; + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); - /* File descriptor read wait: */ - case PS_FDR_WAIT: - /* - * Check if the file descriptor is available - * for read: - */ - if (FD_ISSET(pthread->data.fd.fd, &fd_set_read)) { /* - * Change the thread state to allow - * it to read from the file when it - * is scheduled next: + * One less thread in a spinblock state: */ - pthread->state = PS_RUNNING; + _spinblock_count--; + } + break; - /* - * Remove it from the waiting queue - * and add it to the ready queue: - */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + /* File descriptor read wait: */ + case PS_FDR_WAIT: + if ((nfds < _thread_dtablesize) && + (_thread_pfd_table[nfds].revents & POLLRDNORM)) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); } + nfds++; break; /* File descriptor write wait: */ case PS_FDW_WAIT: - /* - * Check if the file descriptor is available - * for write: - */ - if (FD_ISSET(pthread->data.fd.fd, &fd_set_write)) { - /* - * Change the thread state to allow - * it to write to the file when it is - * scheduled next: - */ - pthread->state = PS_RUNNING; - - /* - * Remove it from the waiting queue - * and add it to the ready queue: - */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + if ((nfds < _thread_dtablesize) && + (_thread_pfd_table[nfds].revents & POLLWRNORM)) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); } + nfds++; break; - /* Select wait: */ + /* File descriptor poll or select wait: */ + case PS_POLL_WAIT: case PS_SELECT_WAIT: - /* - * Reset the flag that indicates if a file - * descriptor is ready for some type of - * operation: - */ - count_dec = 0; - - /* - * Enter a loop to search though the - * thread-specific select file descriptors - * for the first descriptor that is ready: - */ - for (i = 0; i < pthread->data.select_data->nfds && count_dec == 0; i++) { - /* - * Check if this file descriptor does - * not have an exception: - */ - if (FD_ISSET(i, &pthread->data.select_data->exceptfds) && FD_ISSET(i, &fd_set_except)) { - /* - * Flag this file descriptor - * as ready: - */ - count_dec = 1; - } + if (pthread->data.poll_data->nfds + nfds < + _thread_dtablesize) { /* - * Check if this file descriptor is - * not ready for write: + * Enter a loop looking for I/O + * readiness: */ - if (FD_ISSET(i, &pthread->data.select_data->writefds) && FD_ISSET(i, &fd_set_write)) { - /* - * Flag this file descriptor - * as ready: - */ - count_dec = 1; + found = 0; + for (i = 0; i < pthread->data.poll_data->nfds; i++) { + if (_thread_pfd_table[nfds + i].revents != 0) { + pthread->data.poll_data->fds[i].revents = + _thread_pfd_table[nfds + i].revents; + found++; + } } - /* - * Check if this file descriptor is - * not ready for read: - */ - if (FD_ISSET(i, &pthread->data.select_data->readfds) && FD_ISSET(i, &fd_set_read)) { - /* - * Flag this file descriptor - * as ready: - */ - count_dec = 1; + + /* Increment before destroying: */ + nfds += pthread->data.poll_data->nfds; + + if (found != 0) { + pthread->data.poll_data->nfds = found; + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); } } + else + nfds += pthread->data.poll_data->nfds; + break; + /* Other states do not depend on file I/O. */ + default: + break; + } + } + PTHREAD_WAITQ_CLEARACTIVE(); + } + else if (_spinblock_count != 0) { + /* + * Enter a loop to look for threads waiting on a spinlock + * that is now available. + */ + PTHREAD_WAITQ_SETACTIVE(); + TAILQ_FOREACH(pthread, &_workq, qe) { + if (pthread->state == PS_SPINBLOCK) { /* - * Check if any file descriptors are ready - * for the current thread: + * If the lock is available, let the thread run. */ - if (count_dec) { - /* - * Reset the count of file - * descriptors that are ready for - * this thread: - */ - found_one = 0; - - /* - * Enter a loop to search though the - * thread-specific select file - * descriptors: - */ - for (i = 0; i < pthread->data.select_data->nfds; i++) { - /* - * Reset the count of - * operations for which the - * current file descriptor is - * ready: - */ - count_dec = 0; - - /* - * Check if this file - * descriptor is selected for - * exceptions: - */ - if (FD_ISSET(i, &pthread->data.select_data->exceptfds)) { - /* - * Check if this file - * descriptor has an - * exception: - */ - if (FD_ISSET(i, &fd_set_except)) { - /* - * Increment - * the count - * for this - * file: - */ - count_dec++; - } else { - /* - * Clear the - * file - * descriptor - * in the - * thread-spec - * ific file - * descriptor - * set: - */ - FD_CLR(i, &pthread->data.select_data->exceptfds); - } - } - /* - * Check if this file - * descriptor is selected for - * write: - */ - if (FD_ISSET(i, &pthread->data.select_data->writefds)) { - /* - * Check if this file - * descriptor is - * ready for write: - */ - if (FD_ISSET(i, &fd_set_write)) { - /* - * Increment - * the count - * for this - * file: - */ - count_dec++; - } else { - /* - * Clear the - * file - * descriptor - * in the - * thread-spec - * ific file - * descriptor - * set: - */ - FD_CLR(i, &pthread->data.select_data->writefds); - } - } - /* - * Check if this file - * descriptor is selected for - * read: - */ - if (FD_ISSET(i, &pthread->data.select_data->readfds)) { - /* - * Check if this file - * descriptor is - * ready for read: - */ - if (FD_ISSET(i, &fd_set_read)) { - /* - * Increment - * the count - * for this - * file: - */ - count_dec++; - } else { - /* - * Clear the - * file - * descriptor - * in the - * thread-spec - * ific file - * descriptor - * set: - */ - FD_CLR(i, &pthread->data.select_data->readfds); - } - } - /* - * Check if the current file - * descriptor is ready for - * any one of the operations: - */ - if (count_dec > 0) { - /* - * Increment the - * count of file - * descriptors that - * are ready for the - * current thread: - */ - found_one++; - } - } - - /* - * Return the number of file - * descriptors that are ready: - */ - pthread->data.select_data->nfds = found_one; - - /* - * Change the state of the current - * thread to run: - */ - pthread->state = PS_RUNNING; + if (pthread->data.spinlock->access_lock == 0) { + PTHREAD_WAITQ_CLEARACTIVE(); + PTHREAD_WORKQ_REMOVE(pthread); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_WAITQ_SETACTIVE(); /* - * Remove it from the waiting queue - * and add it to the ready queue: + * One less thread in a spinblock state: */ - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); + _spinblock_count--; } - break; } } + PTHREAD_WAITQ_CLEARACTIVE(); + } + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; + + while (_sigq_check_reqd != 0) { + /* Handle queued signals: */ + _sigq_check_reqd = 0; + + /* Protect the scheduling queues: */ + _queue_signals = 1; + + dequeue_signals(); + + /* Unprotect the scheduling queues: */ + _queue_signals = 0; } /* Nothing to return. */ @@ -1253,59 +1005,101 @@ _thread_kern_set_timeout(struct timespec * timeout) } void -_thread_kern_sched_defer(void) +_thread_kern_sig_defer(void) { - /* Allow scheduling deferral to be recursive. */ - _thread_run->sched_defer_count++; + /* Allow signal deferral to be recursive. */ + _thread_run->sig_defer_count++; } void -_thread_kern_sched_undefer(void) +_thread_kern_sig_undefer(void) { pthread_t pthread; int need_resched = 0; /* * Perform checks to yield only if we are about to undefer - * scheduling. + * signals. */ - if (_thread_run->sched_defer_count == 1) { + if (_thread_run->sig_defer_count > 1) { + /* Decrement the signal deferral count. */ + _thread_run->sig_defer_count--; + } + else if (_thread_run->sig_defer_count == 1) { + /* Reenable signals: */ + _thread_run->sig_defer_count = 0; + /* - * Check if the waiting queue needs to be examined for - * threads that are now ready: + * Check if there are queued signals: */ - while (_waitingq_check_reqd != 0) { - /* Clear the flag before checking the waiting queue: */ - _waitingq_check_reqd = 0; - - TAILQ_FOREACH(pthread, &_waitingq, pqe) { - if (pthread->state == PS_RUNNING) { - PTHREAD_WAITQ_REMOVE(pthread); - PTHREAD_PRIOQ_INSERT_TAIL(pthread); - } + while (_sigq_check_reqd != 0) { + /* Defer scheduling while we process queued signals: */ + _thread_run->sig_defer_count = 1; + + /* Clear the flag before checking the signal queue: */ + _sigq_check_reqd = 0; + + /* Dequeue and handle signals: */ + dequeue_signals(); + + /* + * Avoiding an unnecessary check to reschedule, check + * to see if signal handling caused a higher priority + * thread to become ready. + */ + if ((need_resched == 0) && + (((pthread = PTHREAD_PRIOQ_FIRST()) != NULL) && + (pthread->active_priority > _thread_run->active_priority))) { + need_resched = 1; } + + /* Reenable signals: */ + _thread_run->sig_defer_count = 0; } - /* - * We need to yield if a thread change of state caused a - * higher priority thread to become ready, or if a - * scheduling signal occurred while preemption was disabled. - */ - if ((((pthread = PTHREAD_PRIOQ_FIRST) != NULL) && - (pthread->active_priority > _thread_run->active_priority)) || - (_thread_run->yield_on_sched_undefer != 0)) { - _thread_run->yield_on_sched_undefer = 0; - need_resched = 1; + /* Yield the CPU if necessary: */ + if (need_resched || _thread_run->yield_on_sig_undefer != 0) { + _thread_run->yield_on_sig_undefer = 0; + _thread_kern_sched(NULL); } } +} - if (_thread_run->sched_defer_count > 0) { - /* Decrement the scheduling deferral count. */ - _thread_run->sched_defer_count--; +static void +dequeue_signals(void) +{ + char bufr[128]; + int i, num; - /* Yield the CPU if necessary: */ - if (need_resched) - _thread_kern_sched(NULL); + /* + * Enter a loop to read and handle queued signals from the + * pthread kernel pipe: + */ + while (((num = _thread_sys_read(_thread_kern_pipe[0], bufr, + sizeof(bufr))) > 0) || (num == -1 && errno == EINTR)) { + /* + * The buffer read contains one byte per signal and + * each byte is the signal number. + */ + for (i = 0; i < num; i++) { + if ((int) bufr[i] == _SCHED_SIGNAL) { + /* + * Scheduling signals shouldn't ever be + * queued; just ignore it for now. + */ + } + else { + /* Handle this signal: */ + _thread_sig_handle((int) bufr[i], NULL); + } + } + } + if ((num < 0) && (errno != EAGAIN)) { + /* + * The only error we should expect is if there is + * no data to read. + */ + PANIC("Unable to read from thread kernel pipe"); } } @@ -1316,10 +1110,10 @@ thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in) pthread_t tid_in = thread_in; if ((tid_out != NULL) && - (tid_out->flags & PTHREAD_FLAGS_PRIVATE != 0)) + ((tid_out->flags & PTHREAD_FLAGS_PRIVATE) != 0)) tid_out = NULL; if ((tid_in != NULL) && - (tid_in->flags & PTHREAD_FLAGS_PRIVATE != 0)) + ((tid_in->flags & PTHREAD_FLAGS_PRIVATE) != 0)) tid_in = NULL; if ((_sched_switch_hook != NULL) && (tid_out != tid_in)) { diff --git a/lib/libpthread/uthread/uthread_kill.c b/lib/libpthread/uthread/uthread_kill.c index dc698ff1660..172d3817513 100644 --- a/lib/libpthread/uthread/uthread_kill.c +++ b/lib/libpthread/uthread/uthread_kill.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_kill.c,v 1.6 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_kill.c,v 1.7 1999/11/25 07:01:37 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -21,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_kill.c,v 1.9 1999/08/28 00:03:38 peter Exp $ */ #include <errno.h> #include <signal.h> @@ -47,18 +48,18 @@ pthread_kill(pthread_t pthread, int sig) /* Invalid signal: */ ret = EINVAL; - /* Ignored signals get dropped on the floor. */ - else if (_thread_sigact[sig - 1].sa_handler == SIG_IGN) - ret = 0; - - /* Find the thread in the list of active threads: */ - else if ((ret = _find_thread(pthread)) == 0) { + /* + * Ensure the thread is in the list of active threads, and the + * signal is valid (signal 0 specifies error checking only) and + * not being ignored: + */ + else if (((ret = _find_thread(pthread)) == 0) && (sig > 0) && + (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); switch (pthread->state) { case PS_SIGSUSPEND: @@ -91,15 +92,19 @@ pthread_kill(pthread_t pthread, int sig) sigaddset(&pthread->sigpend,sig); break; - case PS_SELECT_WAIT: case PS_FDR_WAIT: case PS_FDW_WAIT: + case PS_POLL_WAIT: case PS_SLEEP_WAIT: + case PS_SELECT_WAIT: if (!sigismember(&pthread->sigmask, sig) && (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { /* Flag the operation as interrupted: */ pthread->interrupted = 1; + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + /* Change the state of the thread to run: */ PTHREAD_NEW_STATE(pthread,PS_RUNNING); @@ -117,11 +122,43 @@ pthread_kill(pthread_t pthread, int sig) break; } + + /* + * Check that a custom handler is installed + * and if the signal is not blocked: + */ + if (_thread_sigact[sig - 1].sa_handler != SIG_DFL && + _thread_sigact[sig - 1].sa_handler != SIG_IGN && + sigismember(&pthread->sigpend, sig) && + !sigismember(&pthread->sigmask, sig)) { + pthread_t pthread_saved = _thread_run; + + /* Current thread inside critical region? */ + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count++; + + _thread_run = pthread; + + /* Clear the pending signal: */ + sigdelset(&pthread->sigpend, sig); + + /* + * Dispatch the signal via the custom signal + * handler: + */ + (*(_thread_sigact[sig - 1].sa_handler))(sig); + + _thread_run = pthread_saved; + + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count--; + } + /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ diff --git a/lib/libpthread/uthread/uthread_listen.c b/lib/libpthread/uthread/uthread_listen.c index 880cb4c6b12..0f9b312b3bb 100644 --- a/lib/libpthread/uthread/uthread_listen.c +++ b/lib/libpthread/uthread/uthread_listen.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_listen.c,v 1.3 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_listen.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_listen.c,v 1.5 1999/08/28 00:03:38 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libpthread/uthread/uthread_mattr_init.c b/lib/libpthread/uthread/uthread_mattr_init.c index 65b79e9539f..172ddb45b35 100644 --- a/lib/libpthread/uthread/uthread_mattr_init.c +++ b/lib/libpthread/uthread/uthread_mattr_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mattr_init.c,v 1.3 1999/05/26 00:18:24 d Exp $ */ +/* $OpenBSD: uthread_mattr_init.c,v 1.4 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1996 Jeffrey Hsu <hsu@freebsd.org>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mattr_init.c,v 1.5 1999/08/28 00:03:39 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libpthread/uthread/uthread_mattr_kind_np.c b/lib/libpthread/uthread/uthread_mattr_kind_np.c index 5f5d1b3a992..073c30da4e9 100644 --- a/lib/libpthread/uthread/uthread_mattr_kind_np.c +++ b/lib/libpthread/uthread/uthread_mattr_kind_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_mattr_kind_np.c,v 1.5 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1996 Jeffrey Hsu <hsu@freebsd.org>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_mattr_kind_np.c,v 1.4 1999/05/26 00:18:25 d Exp $ + * $FreeBSD: uthread_mattr_kind_np.c,v 1.4 1999/08/28 00:03:39 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -68,7 +69,8 @@ pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { int ret; if (attr == NULL || *attr == NULL || type >= MUTEX_TYPE_MAX) { - return EINVAL; + errno = EINVAL; + ret = -1; } else { (*attr)->m_type = type; ret = 0; diff --git a/lib/libpthread/uthread/uthread_msync.c b/lib/libpthread/uthread/uthread_msync.c index fb7d5a7e86e..3edde1a31d4 100644 --- a/lib/libpthread/uthread/uthread_msync.c +++ b/lib/libpthread/uthread/uthread_msync.c @@ -1,7 +1,7 @@ /* * David Leonard <d@openbsd.org>, 1999. Public Domain. * - * $OpenBSD: uthread_msync.c,v 1.2 1999/06/09 07:16:17 d Exp $ + * $OpenBSD: uthread_msync.c,v 1.3 1999/11/25 07:01:38 d Exp $ */ #include <sys/types.h> @@ -18,13 +18,6 @@ msync(addr, len, flags) { int ret; - /* - * XXX This is quite pointless unless we know how to get the - * file descriptor associated with the memory, and lock it for - * write. The only real use of this wrapper is to guarantee - * a cancellation point, as per the standard. sigh. - */ - /* This is a cancellation point: */ _thread_enter_cancellation_point(); diff --git a/lib/libpthread/uthread/uthread_multi_np.c b/lib/libpthread/uthread/uthread_multi_np.c index 4da9793804c..88c6cbbfddf 100644 --- a/lib/libpthread/uthread/uthread_multi_np.c +++ b/lib/libpthread/uthread/uthread_multi_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_multi_np.c,v 1.3 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_multi_np.c,v 1.2 1999/01/06 05:29:24 d Exp $ + * $FreeBSD: uthread_multi_np.c,v 1.3 1999/08/28 00:03:40 peter Exp $ */ #include <string.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_mutex.c b/lib/libpthread/uthread/uthread_mutex.c index 8cb8760046c..1ddce4f6131 100644 --- a/lib/libpthread/uthread/uthread_mutex.c +++ b/lib/libpthread/uthread/uthread_mutex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex.c,v 1.8 1999/06/09 07:06:54 d Exp $ */ +/* $OpenBSD: uthread_mutex.c,v 1.9 1999/11/25 07:01:38 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mutex.c,v 1.16 1999/08/28 00:03:40 peter Exp $ */ #include <stdlib.h> #include <errno.h> @@ -40,6 +41,25 @@ #include <pthread.h> #include "pthread_private.h" +#if defined(_PTHREADS_INVARIANTS) +#define _MUTEX_INIT_LINK(m) do { \ + (m)->m_qe.tqe_prev = NULL; \ + (m)->m_qe.tqe_next = NULL; \ +} while (0) +#define _MUTEX_ASSERT_IS_OWNED(m) do { \ + if ((m)->m_qe.tqe_prev == NULL) \ + PANIC("mutex is not on list"); \ +} while (0) +#define _MUTEX_ASSERT_NOT_OWNED(m) do { \ + if (((m)->m_qe.tqe_prev != NULL) || \ + ((m)->m_qe.tqe_next != NULL)) \ + PANIC("mutex is on list"); \ +} while (0) +#else +#define _MUTEX_INIT_LINK(m) +#define _MUTEX_ASSERT_IS_OWNED(m) +#define _MUTEX_ASSERT_NOT_OWNED(m) +#endif /* * Prototypes @@ -56,6 +76,34 @@ static inline void mutex_queue_enq(pthread_mutex_t, pthread_t); static spinlock_t static_init_lock = _SPINLOCK_INITIALIZER; +/* Reinitialize a mutex to defaults. */ +int +_mutex_reinit(pthread_mutex_t * mutex) +{ + int ret = 0; + + if (mutex == NULL) + ret = EINVAL; + else if (*mutex == NULL) + ret = pthread_mutex_init(mutex, NULL); + else { + /* + * Initialize the mutex structure: + */ + (*mutex)->m_type = PTHREAD_MUTEX_DEFAULT; + (*mutex)->m_protocol = PTHREAD_PRIO_NONE; + TAILQ_INIT(&(*mutex)->m_queue); + (*mutex)->m_owner = NULL; + (*mutex)->m_data.m_count = 0; + (*mutex)->m_flags = MUTEX_FLAGS_INITED; + (*mutex)->m_refcount = 0; + (*mutex)->m_prio = 0; + (*mutex)->m_saved_prio = 0; + _MUTEX_INIT_LINK(*mutex); + _SPINLOCK_INIT(&(*mutex)->lock); + } + return (ret); +} int pthread_mutex_init(pthread_mutex_t * mutex, @@ -139,7 +187,8 @@ pthread_mutex_init(pthread_mutex_t * mutex, else pmutex->m_prio = 0; pmutex->m_saved_prio = 0; - _SPINUNLOCK(&pmutex->lock); + _MUTEX_INIT_LINK(pmutex); + memset(&pmutex->lock, 0, sizeof(pmutex->lock)); *mutex = pmutex; } else { free(pmutex); @@ -148,7 +197,7 @@ pthread_mutex_init(pthread_mutex_t * mutex, } } /* Return the completion status: */ - return (ret); + return(ret); } int @@ -178,6 +227,7 @@ pthread_mutex_destroy(pthread_mutex_t * mutex) * Free the memory allocated for the mutex * structure: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); free(*mutex); /* @@ -223,28 +273,24 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) */ else if (*mutex != NULL || (ret = init_static(mutex)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* * If the mutex was statically allocated, properly * initialize the tail queue. */ if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) { TAILQ_INIT(&(*mutex)->m_queue); + _MUTEX_INIT_LINK(*mutex); (*mutex)->m_flags |= MUTEX_FLAGS_INITED; } - /* - * Guard against being preempted by a scheduling signal. - * To support priority inheritence mutexes, we need to - * maintain lists of mutex ownerships for each thread as - * well as lists of waiting threads for each mutex. In - * order to propagate priorities we need to atomically - * walk these lists and cannot rely on a single mutex - * lock to provide protection against modification. - */ - _thread_kern_sched_defer(); - - /* Lock the mutex structure: */ - _SPINLOCK(&(*mutex)->lock); - /* Process according to mutex type: */ switch ((*mutex)->m_protocol) { /* Default POSIX mutex: */ @@ -255,6 +301,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) (*mutex)->m_owner = _thread_run; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -283,6 +330,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) _thread_run->inherited_priority; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -318,6 +366,7 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) (*mutex)->m_prio; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -338,10 +387,10 @@ pthread_mutex_trylock(pthread_mutex_t * mutex) _SPINUNLOCK(&(*mutex)->lock); /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -362,28 +411,24 @@ pthread_mutex_lock(pthread_mutex_t * mutex) */ else if (*mutex != NULL || (ret = init_static(mutex)) == 0) { /* + * Defer signals to protect the scheduling queues from + * access by the signal handler: + */ + _thread_kern_sig_defer(); + + /* Lock the mutex structure: */ + _SPINLOCK(&(*mutex)->lock); + + /* * If the mutex was statically allocated, properly * initialize the tail queue. */ if (((*mutex)->m_flags & MUTEX_FLAGS_INITED) == 0) { TAILQ_INIT(&(*mutex)->m_queue); (*mutex)->m_flags |= MUTEX_FLAGS_INITED; + _MUTEX_INIT_LINK(*mutex); } - /* - * Guard against being preempted by a scheduling signal. - * To support priority inheritence mutexes, we need to - * maintain lists of mutex ownerships for each thread as - * well as lists of waiting threads for each mutex. In - * order to propagate priorities we need to atomically - * walk these lists and cannot rely on a single mutex - * lock to provide protection against modification. - */ - _thread_kern_sched_defer(); - - /* Lock the mutex structure: */ - _SPINLOCK(&(*mutex)->lock); - /* Process according to mutex type: */ switch ((*mutex)->m_protocol) { /* Default POSIX mutex: */ @@ -393,6 +438,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) (*mutex)->m_owner = _thread_run; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); @@ -420,12 +466,6 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Lock the mutex structure again: */ _SPINLOCK(&(*mutex)->lock); - - /* - * This thread is no longer waiting for - * the mutex: - */ - _thread_run->data.mutex = NULL; } break; @@ -450,6 +490,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) (*mutex)->m_prio; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); @@ -482,12 +523,6 @@ pthread_mutex_lock(pthread_mutex_t * mutex) /* Lock the mutex structure again: */ _SPINLOCK(&(*mutex)->lock); - - /* - * This thread is no longer waiting for - * the mutex: - */ - _thread_run->data.mutex = NULL; } break; @@ -520,6 +555,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex) (*mutex)->m_prio; /* Add to the list of owned mutexes: */ + _MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&_thread_run->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == _thread_run) @@ -557,12 +593,6 @@ pthread_mutex_lock(pthread_mutex_t * mutex) */ ret = _thread_run->error; _thread_run->error = 0; - - /* - * This thread is no longer waiting for - * the mutex: - */ - _thread_run->data.mutex = NULL; } break; @@ -577,10 +607,10 @@ pthread_mutex_lock(pthread_mutex_t * mutex) _SPINUNLOCK(&(*mutex)->lock); /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -684,15 +714,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) ret = EINVAL; } else { /* - * Guard against being preempted by a scheduling signal. - * To support priority inheritence mutexes, we need to - * maintain lists of mutex ownerships for each thread as - * well as lists of waiting threads for each mutex. In - * order to propagate priorities we need to atomically - * walk these lists and cannot rely on a single mutex - * lock to provide protection against modification. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Lock the mutex structure: */ _SPINLOCK(&(*mutex)->lock); @@ -707,8 +732,8 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ if ((*mutex)->m_owner != _thread_run) { /* - * Return a permission error when the thread - * doesn't own the lock: + * Return a permission error when the + * thread doesn't own the lock. */ ret = EPERM; } @@ -724,8 +749,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) (*mutex)->m_data.m_count = 0; /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); /* * Get the next thread from the queue of @@ -739,6 +766,19 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ PTHREAD_NEW_STATE((*mutex)->m_owner, PS_RUNNING); + + /* + * Add the mutex to the threads list of + * owned mutexes: + */ + TAILQ_INSERT_TAIL(&(*mutex)->m_owner->mutexq, + (*mutex), m_qe); + + /* + * The owner is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; } } break; @@ -751,8 +791,8 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ if ((*mutex)->m_owner != _thread_run) { /* - * Return a permission error when the thread - * doesn't own the lock: + * Return a permission error when the + * thread doesn't own the lock. */ ret = EPERM; } @@ -785,8 +825,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) _thread_run->priority_mutex_count--; /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); /* * Get the next thread from the queue of threads @@ -858,8 +900,8 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) */ if ((*mutex)->m_owner != _thread_run) { /* - * Return a permission error when the thread - * doesn't own the lock: + * Return a permission error when the + * thread doesn't own the lock. */ ret = EPERM; } @@ -892,8 +934,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) _thread_run->priority_mutex_count--; /* Remove the mutex from the threads queue. */ + _MUTEX_ASSERT_IS_OWNED(*mutex); TAILQ_REMOVE(&(*mutex)->m_owner->mutexq, - (*mutex), m_qe); + (*mutex), m_qe); + _MUTEX_INIT_LINK(*mutex); /* * Enter a loop to find a waiting thread whose @@ -914,6 +958,11 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) (*mutex)->m_owner->error = EINVAL; PTHREAD_NEW_STATE((*mutex)->m_owner, PS_RUNNING); + /* + * The thread is no longer waiting for + * this mutex: + */ + (*mutex)->m_owner->data.mutex = NULL; } /* Check for a new owner: */ @@ -979,10 +1028,10 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) _SPINUNLOCK(&(*mutex)->lock); /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } /* Return the completion status: */ @@ -991,11 +1040,11 @@ mutex_unlock_common(pthread_mutex_t * mutex, int add_reference) /* - * This function is called when a change in base priority occurs - * for a thread that is thread holding, or waiting for, a priority - * protection or inheritence mutex. A change in a threads base - * priority can effect changes to active priorities of other threads - * and to the ordering of mutex locking by waiting threads. + * This function is called when a change in base priority occurs for + * a thread that is holding or waiting for a priority protection or + * inheritence mutex. A change in a threads base priority can effect + * changes to active priorities of other threads and to the ordering + * of mutex locking by waiting threads. * * This must be called while thread scheduling is deferred. */ @@ -1232,8 +1281,7 @@ mutex_rescan_owned (pthread_t pthread, pthread_mutex_t mutex) * If this thread is in the priority queue, it must be * removed and reinserted for its new priority. */ - if ((pthread != _thread_run) && - (pthread->state == PS_RUNNING)) { + if (pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) { /* * Remove the thread from the priority queue * before changing its priority: diff --git a/lib/libpthread/uthread/uthread_mutex_prioceiling.c b/lib/libpthread/uthread/uthread_mutex_prioceiling.c index 779c238cfe7..afcd9372d47 100644 --- a/lib/libpthread/uthread/uthread_mutex_prioceiling.c +++ b/lib/libpthread/uthread/uthread_mutex_prioceiling.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex_prioceiling.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_mutex_prioceiling.c,v 1.2 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mutex_prioceiling.c,v 1.3 1999/08/28 00:03:40 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libpthread/uthread/uthread_mutex_protocol.c b/lib/libpthread/uthread/uthread_mutex_protocol.c index fa0b9804d57..6b075ee4f2b 100644 --- a/lib/libpthread/uthread/uthread_mutex_protocol.c +++ b/lib/libpthread/uthread/uthread_mutex_protocol.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex_protocol.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_mutex_protocol.c,v 1.2 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_mutex_protocol.c,v 1.3 1999/08/28 00:03:41 peter Exp $ */ #include <string.h> #include <stdlib.h> diff --git a/lib/libpthread/uthread/uthread_mutexattr_destroy.c b/lib/libpthread/uthread/uthread_mutexattr_destroy.c index fcb3863bcab..5749e43d35f 100644 --- a/lib/libpthread/uthread/uthread_mutexattr_destroy.c +++ b/lib/libpthread/uthread/uthread_mutexattr_destroy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_mutexattr_destroy.c,v 1.3 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_mutexattr_destroy.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_mutexattr_destroy.c,v 1.4 1999/08/28 00:03:41 peter Exp $ */ #include <stdlib.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_nanosleep.c b/lib/libpthread/uthread/uthread_nanosleep.c index 4e182adfb6c..583e94e983f 100644 --- a/lib/libpthread/uthread/uthread_nanosleep.c +++ b/lib/libpthread/uthread/uthread_nanosleep.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_nanosleep.c,v 1.5 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_nanosleep.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_nanosleep.c,v 1.10 1999/08/28 00:03:41 peter Exp $ */ #include <stdio.h> #include <errno.h> @@ -42,9 +43,8 @@ nanosleep(const struct timespec * time_to_sleep, struct timespec * time_remaining) { int ret = 0; - struct timespec start_time; - struct timespec wakeup_time; struct timespec current_time; + struct timespec current_time1; struct timespec remaining_time; struct timeval tv; @@ -52,20 +52,26 @@ nanosleep(const struct timespec * time_to_sleep, _thread_enter_cancellation_point(); /* Check if the time to sleep is legal: */ - if (time_to_sleep == NULL || time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec > 1000000000 || time_to_sleep->tv_sec < 0) { + if (time_to_sleep == NULL || time_to_sleep->tv_sec < 0 || + time_to_sleep->tv_nsec < 0 || time_to_sleep->tv_nsec >= 1000000000) { /* Return an EINVAL error : */ errno = EINVAL; ret = -1; } else { /* Get the current time: */ gettimeofday(&tv, NULL); - TIMEVAL_TO_TIMESPEC(&tv, &start_time); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); /* Calculate the time for the current thread to wake up: */ - timespecadd(time_to_sleep, &start_time, &wakeup_time); + _thread_run->wakeup_time.tv_sec = current_time.tv_sec + time_to_sleep->tv_sec; + _thread_run->wakeup_time.tv_nsec = current_time.tv_nsec + time_to_sleep->tv_nsec; - _thread_run->wakeup_time.tv_sec = wakeup_time.tv_sec; - _thread_run->wakeup_time.tv_nsec = wakeup_time.tv_nsec; + /* Check if the nanosecond field has overflowed: */ + if (_thread_run->wakeup_time.tv_nsec >= 1000000000) { + /* Wrap the nanosecond field: */ + _thread_run->wakeup_time.tv_sec += 1; + _thread_run->wakeup_time.tv_nsec -= 1000000000; + } _thread_run->interrupted = 0; /* Reschedule the current thread to sleep: */ @@ -73,15 +79,31 @@ nanosleep(const struct timespec * time_to_sleep, /* Get the current time: */ gettimeofday(&tv, NULL); - TIMEVAL_TO_TIMESPEC(&tv, ¤t_time); + TIMEVAL_TO_TIMESPEC(&tv, ¤t_time1); /* Calculate the remaining time to sleep: */ - timespecsub(&wakeup_time, ¤t_time, &remaining_time); + remaining_time.tv_sec = time_to_sleep->tv_sec + current_time.tv_sec - current_time1.tv_sec; + remaining_time.tv_nsec = time_to_sleep->tv_nsec + current_time.tv_nsec - current_time1.tv_nsec; + + /* Check if the nanosecond field has underflowed: */ + if (remaining_time.tv_nsec < 0) { + /* Handle the underflow: */ + remaining_time.tv_sec -= 1; + remaining_time.tv_nsec += 1000000000; + } + + /* Check if the nanosecond field has overflowed: */ + if (remaining_time.tv_nsec >= 1000000000) { + /* Handle the overflow: */ + remaining_time.tv_sec += 1; + remaining_time.tv_nsec -= 1000000000; + } /* Check if the sleep was longer than the required time: */ if (remaining_time.tv_sec < 0) { /* Reset the time left: */ - timespecclear(&remaining_time); + remaining_time.tv_sec = 0; + remaining_time.tv_nsec = 0; } /* Check if the time remaining is to be returned: */ diff --git a/lib/libpthread/uthread/uthread_once.c b/lib/libpthread/uthread/uthread_once.c index 43ce7c39266..27b3a4d594e 100644 --- a/lib/libpthread/uthread/uthread_once.c +++ b/lib/libpthread/uthread/uthread_once.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_once.c,v 1.3 1999/11/25 07:01:40 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_once.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_once.c,v 1.3 1999/08/28 00:03:42 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libpthread/uthread/uthread_open.c b/lib/libpthread/uthread/uthread_open.c index bfdcea73091..944e46cd109 100644 --- a/lib/libpthread/uthread/uthread_open.c +++ b/lib/libpthread/uthread/uthread_open.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_open.c,v 1.5 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_open.c,v 1.4 1998/04/29 09:59:07 jb Exp $ - * $OpenBSD: uthread_open.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_open.c,v 1.6 1999/08/28 00:03:42 peter Exp $ * */ #include <stdarg.h> @@ -47,6 +47,7 @@ open(const char *path, int flags,...) { int fd; int mode = 0; + int status; va_list ap; /* This is a cancellation point: */ diff --git a/lib/libpthread/uthread/uthread_pipe.c b/lib/libpthread/uthread/uthread_pipe.c index 65610f01302..6288ab82cbc 100644 --- a/lib/libpthread/uthread/uthread_pipe.c +++ b/lib/libpthread/uthread/uthread_pipe.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_pipe.c,v 1.3 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_pipe.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_pipe.c,v 1.5 1999/08/28 00:03:42 peter Exp $ */ #include <unistd.h> #include <fcntl.h> diff --git a/lib/libpthread/uthread/uthread_poll.c b/lib/libpthread/uthread/uthread_poll.c index da3e98d1547..6392cfcb169 100644 --- a/lib/libpthread/uthread/uthread_poll.c +++ b/lib/libpthread/uthread/uthread_poll.c @@ -1,138 +1,97 @@ +/* $OpenBSD: uthread_poll.c,v 1.3 1999/11/25 07:01:41 d Exp $ */ /* - * David Leonard <d@openbsd.org>, 1999. Public Domain. + * Copyright (c) 1999 Daniel Eischen <eischen@vigrid.com> + * All rights reserved. * - * $OpenBSD: uthread_poll.c,v 1.2 1999/01/08 05:09:22 d Exp $ + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Daniel Eischen. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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: uthread_poll.c,v 1.4 1999/08/30 00:02:08 deischen Exp $ */ #include <unistd.h> #include <errno.h> #include <string.h> +#include <poll.h> #include <sys/types.h> #include <sys/time.h> -#include <poll.h> -#include <stdlib.h> +#include <sys/fcntl.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" -static void -poll_helper(nfds, fds, data) - int nfds; - struct pollfd *fds; - struct pthread_select_data *data; -{ - int maxfd; - int i; - int event; - int fd; - - FD_ZERO(&data->readfds); - FD_ZERO(&data->writefds); - FD_ZERO(&data->exceptfds); - - maxfd = -1; - for (i = 0; i < nfds; i++) { - event = fds[i].events; - fd = fds[i].fd; - - if (event & POLLIN) - FD_SET(fd, &data->readfds); - if (event & POLLOUT) - FD_SET(fd, &data->writefds); - if (fd > maxfd) - maxfd = fd; - } - data->nfds = maxfd + 1; -} -int -poll(fds, nfds, timeout) - struct pollfd fds[]; - int nfds; - int timeout; +int +poll(struct pollfd fds[], int nfds, int timeout) { - fd_set rfds, wfds, rwfds; - int i; - struct timespec ts; - int fd, event; - struct pthread_select_data data; - struct timeval zero_timeout = { 0, 0 }; - int ret; + struct timespec ts; + int numfds = nfds; + int i, ret = 0, found = 0; + struct pthread_poll_data data; - if (timeout < 0) { - /* Wait forever: */ + if (numfds > _thread_dtablesize) { + numfds = _thread_dtablesize; + } + /* Check if a timeout was specified: */ + if (timeout == -1) { + /* Wait for ever: */ _thread_kern_set_timeout(NULL); - } else { + } else if (timeout > 0) { + /* Convert the timeout in msec to a timespec: */ ts.tv_sec = timeout / 1000; - ts.tv_nsec = (timeout % 1000) * 1000000L; + ts.tv_nsec = (timeout % 1000) * 1000; + + /* Set the wake up time: */ _thread_kern_set_timeout(&ts); + } else if (timeout < 0) { + /* a timeout less than zero but not == -1 is invalid */ + errno = EINVAL; + return (-1); } - /* Obtain locks needed: */ - ret = 0; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&rwfds); - for (i = 0; i < nfds; i++) { - event = fds[i].events; - fd = fds[i].fd; - - if (event & (POLLIN|POLLOUT)) - if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds) && - !FD_ISSET(fd, &wfds)) { - if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) != 0) - break; - FD_SET(fd, &rwfds); - continue; - } - - if (event & POLLIN) - if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds)) { - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) != 0) - break; - FD_SET(fd, &rfds); - } - - if (event & POLLOUT) - if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &wfds)) { - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) != 0) - break; - FD_SET(fd, &wfds); - } - } + if (((ret = _thread_sys_poll(fds, numfds, 0)) == 0) && (timeout != 0)) { + data.nfds = numfds; + data.fds = fds; - if (ret == 0) { - poll_helper(nfds, fds, &data); - ret = _thread_sys_select(data.nfds, &data.readfds, - &data.writefds, NULL, &zero_timeout); - if (ret == 0) { - poll_helper(nfds, fds, &data); - _thread_run->data.select_data = &data; - _thread_run->interrupted = 0; - _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); - if (_thread_run->interrupted) { - errno = EINTR; - ret = -1; - } + /* + * Clear revents in case of a timeout which leaves fds + * unchanged: + */ + for (i = 0; i < numfds; i++) { + fds[i].revents = 0; } - if (ret >= 0) - ret = _thread_sys_poll(fds, nfds, 0); - } - - /* Clean up the locks: */ - for (i = 0; i < nfds; i++) { - fd = fds[i].fd; - if (FD_ISSET(fd, &rwfds)) { - _FD_UNLOCK(fd, FD_RDWR); - FD_CLR(fd, &rwfds); - } - if (FD_ISSET(fd, &rfds)) { - _FD_UNLOCK(fd, FD_READ); - FD_CLR(fd, &rfds); - } - if (FD_ISSET(fd, &wfds)) { - _FD_UNLOCK(fd, FD_WRITE); - FD_CLR(fd, &wfds); + _thread_run->data.poll_data = &data; + _thread_run->interrupted = 0; + _thread_kern_sched_state(PS_POLL_WAIT, __FILE__, __LINE__); + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + } else { + ret = data.nfds; } } diff --git a/lib/libpthread/uthread/uthread_priority_queue.c b/lib/libpthread/uthread/uthread_priority_queue.c index a5f45ef7064..eef7ed65379 100644 --- a/lib/libpthread/uthread/uthread_priority_queue.c +++ b/lib/libpthread/uthread/uthread_priority_queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_priority_queue.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_priority_queue.c,v 1.2 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_priority_queue.c,v 1.3 1999/08/28 00:03:43 peter Exp $ */ #include <stdlib.h> #include <sys/queue.h> @@ -41,9 +42,51 @@ /* Prototypes: */ static void pq_insert_prio_list(pq_queue_t *pq, int prio); +#if defined(_PTHREADS_INVARIANTS) + +static int _pq_active = 0; + +#define _PQ_IN_SCHEDQ (PTHREAD_FLAGS_IN_PRIOQ | PTHREAD_FLAGS_IN_WAITQ | PTHREAD_FLAGS_IN_WORKQ) + +#define _PQ_SET_ACTIVE() _pq_active = 1 +#define _PQ_CLEAR_ACTIVE() _pq_active = 0 +#define _PQ_ASSERT_ACTIVE(msg) do { \ + if (_pq_active == 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_INACTIVE(msg) do { \ + if (_pq_active != 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_IN_WAITQ(thrd, msg) do { \ + if (((thrd)->flags & PTHREAD_FLAGS_IN_WAITQ) == 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_IN_PRIOQ(thrd, msg) do { \ + if (((thrd)->flags & PTHREAD_FLAGS_IN_PRIOQ) == 0) \ + PANIC(msg); \ +} while (0) +#define _PQ_ASSERT_NOT_QUEUED(thrd, msg) do { \ + if ((thrd)->flags & _PQ_IN_SCHEDQ) \ + PANIC(msg); \ +} while (0) + +#else + +#define _PQ_SET_ACTIVE() +#define _PQ_CLEAR_ACTIVE() +#define _PQ_ASSERT_ACTIVE(msg) +#define _PQ_ASSERT_INACTIVE(msg) +#define _PQ_ASSERT_IN_WAITQ(thrd, msg) +#define _PQ_ASSERT_IN_PRIOQ(thrd, msg) +#define _PQ_ASSERT_NOT_QUEUED(thrd, msg) +#define _PQ_CHECK_PRIO() + +#endif + int -_pq_init(pq_queue_t *pq, int minprio, int maxprio) +_pq_alloc(pq_queue_t *pq, int minprio, int maxprio) { int i, ret = 0; int prioslots = maxprio - minprio + 1; @@ -57,8 +100,26 @@ _pq_init(pq_queue_t *pq, int minprio, int maxprio) ret = -1; else { + /* Remember the queue size: */ + pq->pq_size = prioslots; + + ret = _pq_init(pq); + + } + return (ret); +} + +int +_pq_init(pq_queue_t *pq) +{ + int i, ret = 0; + + if ((pq == NULL) || (pq->pq_lists == NULL)) + ret = -1; + + else { /* Initialize the queue for each priority slot: */ - for (i = 0; i < prioslots; i++) { + for (i = 0; i < pq->pq_size; i++) { TAILQ_INIT(&pq->pq_lists[i].pl_head); pq->pq_lists[i].pl_prio = i; pq->pq_lists[i].pl_queued = 0; @@ -66,9 +127,7 @@ _pq_init(pq_queue_t *pq, int minprio, int maxprio) /* Initialize the priority queue: */ TAILQ_INIT(&pq->pq_queue); - - /* Remember the queue size: */ - pq->pq_size = prioslots; + _PQ_CLEAR_ACTIVE(); } return (ret); } @@ -78,7 +137,27 @@ _pq_remove(pq_queue_t *pq, pthread_t pthread) { int prio = pthread->active_priority; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_remove: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_IN_PRIOQ(pthread, "_pq_remove: Not in priority queue"); + + /* + * Remove this thread from priority list. Note that if + * the priority list becomes empty, it is not removed + * from the priority queue because another thread may be + * added to the priority list (resulting in a needless + * removal/insertion). Priority lists are only removed + * from the priority queue when _pq_first is called. + */ TAILQ_REMOVE(&pq->pq_lists[prio].pl_head, pthread, pqe); + + /* This thread is now longer in the priority queue. */ + pthread->flags &= ~PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); } @@ -87,10 +166,23 @@ _pq_insert_head(pq_queue_t *pq, pthread_t pthread) { int prio = pthread->active_priority; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_insert_head: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, + "_pq_insert_head: Already in priority queue"); + TAILQ_INSERT_HEAD(&pq->pq_lists[prio].pl_head, pthread, pqe); if (pq->pq_lists[prio].pl_queued == 0) /* Insert the list into the priority queue: */ pq_insert_prio_list(pq, prio); + + /* Mark this thread as being in the priority queue. */ + pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); } @@ -99,10 +191,23 @@ _pq_insert_tail(pq_queue_t *pq, pthread_t pthread) { int prio = pthread->active_priority; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_insert_tail: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, + "_pq_insert_tail: Already in priority queue"); + TAILQ_INSERT_TAIL(&pq->pq_lists[prio].pl_head, pthread, pqe); if (pq->pq_lists[prio].pl_queued == 0) /* Insert the list into the priority queue: */ pq_insert_prio_list(pq, prio); + + /* Mark this thread as being in the priority queue. */ + pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ; + + _PQ_CLEAR_ACTIVE(); } @@ -112,6 +217,12 @@ _pq_first(pq_queue_t *pq) pq_list_t *pql; pthread_t pthread = NULL; + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_pq_first: pq_active"); + _PQ_SET_ACTIVE(); + while (((pql = TAILQ_FIRST(&pq->pq_queue)) != NULL) && (pthread == NULL)) { if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) { @@ -125,6 +236,8 @@ _pq_first(pq_queue_t *pq) pql->pl_queued = 0; } } + + _PQ_CLEAR_ACTIVE(); return (pthread); } @@ -135,9 +248,14 @@ pq_insert_prio_list(pq_queue_t *pq, int prio) pq_list_t *pql; /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_ACTIVE("pq_insert_prio_list: pq_active"); + + /* * The priority queue is in descending priority order. Start at * the beginning of the queue and find the list before which the - * new list should to be inserted. + * new list should be inserted. */ pql = TAILQ_FIRST(&pq->pq_queue); while ((pql != NULL) && (pql->pl_prio > prio)) @@ -153,4 +271,66 @@ pq_insert_prio_list(pq_queue_t *pq, int prio) pq->pq_lists[prio].pl_queued = 1; } +#if defined(_PTHREADS_INVARIANTS) +void +_waitq_insert(pthread_t pthread) +{ + pthread_t tid; + + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_waitq_insert: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_NOT_QUEUED(pthread, "_waitq_insert: Already in queue"); + + if (pthread->wakeup_time.tv_sec == -1) + TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe); + else { + tid = TAILQ_FIRST(&_waitingq); + while ((tid != NULL) && (tid->wakeup_time.tv_sec != -1) && + ((tid->wakeup_time.tv_sec < pthread->wakeup_time.tv_sec) || + ((tid->wakeup_time.tv_sec == pthread->wakeup_time.tv_sec) && + (tid->wakeup_time.tv_nsec <= pthread->wakeup_time.tv_nsec)))) + tid = TAILQ_NEXT(tid, pqe); + if (tid == NULL) + TAILQ_INSERT_TAIL(&_waitingq, pthread, pqe); + else + TAILQ_INSERT_BEFORE(tid, pthread, pqe); + } + pthread->flags |= PTHREAD_FLAGS_IN_WAITQ; + + _PQ_CLEAR_ACTIVE(); +} + +void +_waitq_remove(pthread_t pthread) +{ + /* + * Make some assertions when debugging is enabled: + */ + _PQ_ASSERT_INACTIVE("_waitq_remove: pq_active"); + _PQ_SET_ACTIVE(); + _PQ_ASSERT_IN_WAITQ(pthread, "_waitq_remove: Not in queue"); + + TAILQ_REMOVE(&_waitingq, pthread, pqe); + pthread->flags &= ~PTHREAD_FLAGS_IN_WAITQ; + + _PQ_CLEAR_ACTIVE(); +} + +void +_waitq_setactive(void) +{ + _PQ_ASSERT_INACTIVE("_waitq_setactive: pq_active"); + _PQ_SET_ACTIVE(); +} + +void +_waitq_clearactive(void) +{ + _PQ_ASSERT_ACTIVE("_waitq_clearactive: ! pq_active"); + _PQ_CLEAR_ACTIVE(); +} +#endif #endif diff --git a/lib/libpthread/uthread/uthread_queue.c b/lib/libpthread/uthread/uthread_queue.c deleted file mode 100644 index b30b5b9d425..00000000000 --- a/lib/libpthread/uthread/uthread_queue.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by John Birrell. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $OpenBSD: uthread_queue.c,v 1.2 1999/01/06 05:29:25 d Exp $ - */ -#include <stdio.h> -#ifdef _THREAD_SAFE -#include <pthread.h> -#include "pthread_private.h" - -void -_thread_queue_init(struct pthread_queue * queue) -{ - /* Initialise the pointers in the queue structure: */ - queue->q_next = NULL; - queue->q_last = NULL; - queue->q_data = NULL; - return; -} - -void -_thread_queue_enq(struct pthread_queue * queue, struct pthread * thread) -{ - if (queue->q_last) { - queue->q_last->qnxt = thread; - } else { - queue->q_next = thread; - } - queue->q_last = thread; - thread->queue = queue; - thread->qnxt = NULL; - return; -} - -struct pthread * -_thread_queue_get(struct pthread_queue * queue) -{ - /* Return the pointer to the next thread in the queue: */ - return (queue->q_next); -} - -struct pthread * -_thread_queue_deq(struct pthread_queue * queue) -{ - struct pthread *thread = NULL; - - if (queue->q_next) { - thread = queue->q_next; - if (!(queue->q_next = queue->q_next->qnxt)) { - queue->q_last = NULL; - } - thread->queue = NULL; - thread->qnxt = NULL; - } - return (thread); -} - -int -_thread_queue_remove(struct pthread_queue * queue, struct pthread * thread) -{ - struct pthread **current = &(queue->q_next); - struct pthread *prev = NULL; - int ret = -1; - - while (*current) { - if (*current == thread) { - if ((*current)->qnxt) { - *current = (*current)->qnxt; - } else { - queue->q_last = prev; - *current = NULL; - } - ret = 0; - break; - } - prev = *current; - current = &((*current)->qnxt); - } - thread->queue = NULL; - thread->qnxt = NULL; - return (ret); -} - -int -pthread_llist_remove(struct pthread ** llist, struct pthread * thread) -{ - while (*llist) { - if (*llist == thread) { - *llist = thread->qnxt; - return (0); - } - llist = &(*llist)->qnxt; - } - return (-1); -} - -#endif diff --git a/lib/libpthread/uthread/uthread_read.c b/lib/libpthread/uthread/uthread_read.c index 6b9c96352d0..08c12241ed7 100644 --- a/lib/libpthread/uthread/uthread_read.c +++ b/lib/libpthread/uthread/uthread_read.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_read.c,v 1.5 1999/11/25 07:01:41 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_read.c,v 1.6 1998/06/10 22:28:43 jb Exp $ - * $OpenBSD: uthread_read.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_read.c,v 1.8 1999/08/28 00:03:43 peter Exp $ * */ #include <sys/types.h> @@ -52,14 +52,11 @@ read(int fd, void *buf, size_t nbytes) _thread_enter_cancellation_point(); /* POSIX says to do just this: */ - if (nbytes == 0) { - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (0); - } + if (nbytes == 0) + ret = 0; /* Lock the file descriptor for read: */ - if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { + else if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) { /* Get the read/write mode type: */ type = _thread_fd_table[fd]->flags & O_ACCMODE; @@ -67,14 +64,11 @@ read(int fd, void *buf, size_t nbytes) if (type != O_RDONLY && type != O_RDWR) { /* File is not open for read: */ errno = EBADF; - _FD_UNLOCK(fd, FD_READ); - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (-1); + ret = -1; } /* Perform a non-blocking read syscall: */ - while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { + else while ((ret = _thread_sys_read(fd, buf, nbytes)) < 0) { if ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) { _thread_run->data.fd.fd = fd; @@ -101,8 +95,10 @@ read(int fd, void *buf, size_t nbytes) } _FD_UNLOCK(fd, FD_READ); } + /* No longer in a cancellation point: */ _thread_leave_cancellation_point(); + return (ret); } #endif diff --git a/lib/libpthread/uthread/uthread_readv.c b/lib/libpthread/uthread/uthread_readv.c index 293adfe0e53..1ef0ac51ba1 100644 --- a/lib/libpthread/uthread/uthread_readv.c +++ b/lib/libpthread/uthread/uthread_readv.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_readv.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_readv.c,v 1.6 1998/06/10 22:28:44 jb Exp $ - * $OpenBSD: uthread_readv.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_readv.c,v 1.8 1999/08/28 00:03:43 peter Exp $ * */ #include <sys/types.h> diff --git a/lib/libpthread/uthread/uthread_recvfrom.c b/lib/libpthread/uthread/uthread_recvfrom.c index e259eb62138..18c0c6ce8ed 100644 --- a/lib/libpthread/uthread/uthread_recvfrom.c +++ b/lib/libpthread/uthread/uthread_recvfrom.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_recvfrom.c,v 1.4 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_recvfrom.c,v 1.3 1999/02/16 16:40:00 deraadt Exp $ + * $FreeBSD: uthread_recvfrom.c,v 1.5 1999/08/28 00:03:44 peter Exp $ */ #include <errno.h> #include <sys/types.h> @@ -40,8 +41,7 @@ #include "pthread_private.h" ssize_t -recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, - socklen_t *from_len) +recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr * from, socklen_t *from_len) { int ret; diff --git a/lib/libpthread/uthread/uthread_recvmsg.c b/lib/libpthread/uthread/uthread_recvmsg.c index 0b99b11c78d..c92b7a1c420 100644 --- a/lib/libpthread/uthread/uthread_recvmsg.c +++ b/lib/libpthread/uthread/uthread_recvmsg.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_recvmsg.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_recvmsg.c,v 1.2 1999/01/06 05:29:25 d Exp $ + * $FreeBSD: uthread_recvmsg.c,v 1.4 1999/08/28 00:03:44 peter Exp $ */ #include <errno.h> #include <sys/types.h> diff --git a/lib/libpthread/uthread/uthread_resume_np.c b/lib/libpthread/uthread/uthread_resume_np.c index e4be286bde6..8816f76e4c8 100644 --- a/lib/libpthread/uthread/uthread_resume_np.c +++ b/lib/libpthread/uthread/uthread_resume_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_resume_np.c,v 1.4 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_resume_np.c,v 1.3 1999/05/26 00:18:25 d Exp $ + * $FreeBSD: uthread_resume_np.c,v 1.7 1999/08/28 00:03:44 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -47,20 +48,19 @@ pthread_resume_np(pthread_t thread) /* The thread exists. Is it suspended? */ if (thread->state != PS_SUSPENDED) { /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues + * from access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Allow the thread to run. */ PTHREAD_NEW_STATE(thread,PS_RUNNING); /* - * Reenable preemption and yield if a scheduling - * signal occurred while in the critical region. + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } } return(ret); diff --git a/lib/libpthread/uthread/uthread_rwlock.c b/lib/libpthread/uthread/uthread_rwlock.c index e9ca20b00fa..259f1898402 100644 --- a/lib/libpthread/uthread/uthread_rwlock.c +++ b/lib/libpthread/uthread/uthread_rwlock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_rwlock.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /*- * Copyright (c) 1998 Alex Nash * All rights reserved. @@ -23,8 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_rwlock.c,v 1.3 1998/09/07 21:07:59 alex Exp $ - * $OpenBSD: uthread_rwlock.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_rwlock.c,v 1.4 1999/08/28 00:03:45 peter Exp $ */ #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_rwlockattr.c b/lib/libpthread/uthread/uthread_rwlockattr.c index 41a9d89333c..8e7f7a5e1d0 100644 --- a/lib/libpthread/uthread/uthread_rwlockattr.c +++ b/lib/libpthread/uthread/uthread_rwlockattr.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_rwlockattr.c,v 1.3 1999/11/25 07:01:42 d Exp $ */ /*- * Copyright (c) 1998 Alex Nash * All rights reserved. @@ -23,8 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_rwlockattr.c,v 1.2 1998/09/07 19:23:55 alex Exp $ - * $OpenBSD: uthread_rwlockattr.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_rwlockattr.c,v 1.3 1999/08/28 00:03:45 peter Exp $ */ #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_select.c b/lib/libpthread/uthread/uthread_select.c index dd9714e7b3e..a7cd5c3d260 100644 --- a/lib/libpthread/uthread/uthread_select.c +++ b/lib/libpthread/uthread/uthread_select.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_select.c,v 1.4 1999/11/25 07:01:42 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,13 +30,17 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_select.c,v 1.3 1999/05/26 00:18:25 d Exp $ + * $FreeBSD: uthread_select.c,v 1.13 1999/08/30 00:02:08 deischen Exp $ */ #include <unistd.h> #include <errno.h> +#include <poll.h> +#include <stdlib.h> #include <string.h> +#include <sys/param.h> #include <sys/types.h> #include <sys/time.h> +#include <sys/fcntl.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" @@ -44,18 +49,22 @@ int select(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) { - fd_set read_locks, write_locks, rdwr_locks; struct timespec ts; - struct timeval zero_timeout = {0, 0}; - int i, ret = 0, got_all_locks = 1; - int f_wait = 1; - struct pthread_select_data data; + int i, ret = 0, f_wait = 1; + int pfd_index, got_one = 0, fd_count = 0; + struct pthread_poll_data data; if (numfds > _thread_dtablesize) { numfds = _thread_dtablesize; } /* Check if a timeout was specified: */ if (timeout) { + if (timeout->tv_sec < 0 || + timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) { + errno = EINVAL; + return (-1); + } + /* Convert the timeval to a timespec: */ TIMEVAL_TO_TIMESPEC(timeout, &ts); @@ -68,112 +77,129 @@ select(int numfds, fd_set * readfds, fd_set * writefds, _thread_kern_set_timeout(NULL); } - FD_ZERO(&read_locks); - FD_ZERO(&write_locks); - FD_ZERO(&rdwr_locks); - - /* lock readfds */ + /* Count the number of file descriptors to be polled: */ if (readfds || writefds || exceptfds) { for (i = 0; i < numfds; i++) { - if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) { - if (writefds && FD_ISSET(i, writefds)) { - if ((ret = _FD_LOCK(i, FD_RDWR, NULL)) != 0) { - got_all_locks = 0; - break; - } - FD_SET(i, &rdwr_locks); - } else { - if ((ret = _FD_LOCK(i, FD_READ, NULL)) != 0) { - got_all_locks = 0; - break; - } - FD_SET(i, &read_locks); - } - } else { - if (writefds && FD_ISSET(i, writefds)) { - if ((ret = _FD_LOCK(i, FD_WRITE, NULL)) != 0) { - got_all_locks = 0; - break; - } - FD_SET(i, &write_locks); - } + if ((readfds && FD_ISSET(i, readfds)) || + (exceptfds && FD_ISSET(i, exceptfds)) || + (writefds && FD_ISSET(i, writefds))) { + fd_count++; } } } - if (got_all_locks) { - data.nfds = numfds; - FD_ZERO(&data.readfds); - FD_ZERO(&data.writefds); - FD_ZERO(&data.exceptfds); - if (readfds != NULL) { - memcpy(&data.readfds, readfds, sizeof(data.readfds)); - } - if (writefds != NULL) { - memcpy(&data.writefds, writefds, sizeof(data.writefds)); + + /* + * Allocate memory for poll data if it hasn't already been + * allocated or if previously allocated memory is insufficient. + */ + if ((_thread_run->poll_data.fds == NULL) || + (_thread_run->poll_data.nfds < fd_count)) { + data.fds = (struct pollfd *) realloc(_thread_run->poll_data.fds, + sizeof(struct pollfd) * MAX(128, fd_count)); + if (data.fds == NULL) { + errno = ENOMEM; + ret = -1; } - if (exceptfds != NULL) { - memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds)); + else { + /* + * Note that the threads poll data always + * indicates what is allocated, not what is + * currently being polled. + */ + _thread_run->poll_data.fds = data.fds; + _thread_run->poll_data.nfds = MAX(128, fd_count); } - if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0 && f_wait) { - data.nfds = numfds; - FD_ZERO(&data.readfds); - FD_ZERO(&data.writefds); - FD_ZERO(&data.exceptfds); - if (readfds != NULL) { - memcpy(&data.readfds, readfds, sizeof(data.readfds)); + } + if (ret == 0) { + /* Setup the wait data. */ + data.fds = _thread_run->poll_data.fds; + data.nfds = fd_count; + + /* + * Setup the array of pollfds. Optimize this by + * running the loop in reverse and stopping when + * the number of selected file descriptors is reached. + */ + for (i = numfds - 1, pfd_index = fd_count - 1; + (i >= 0) && (pfd_index >= 0); i--) { + data.fds[pfd_index].events = 0; + if (readfds && FD_ISSET(i, readfds)) { + data.fds[pfd_index].events = POLLRDNORM; } - if (writefds != NULL) { - memcpy(&data.writefds, writefds, sizeof(data.writefds)); + if (exceptfds && FD_ISSET(i, exceptfds)) { + data.fds[pfd_index].events |= POLLRDBAND; } - if (exceptfds != NULL) { - memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds)); + if (writefds && FD_ISSET(i, writefds)) { + data.fds[pfd_index].events |= POLLWRNORM; + } + if (data.fds[pfd_index].events != 0) { + /* + * Set the file descriptor to be polled and + * clear revents in case of a timeout which + * leaves fds unchanged: + */ + data.fds[pfd_index].fd = i; + data.fds[pfd_index].revents = 0; + pfd_index--; } - _thread_run->data.select_data = &data; + } + if (((ret = _thread_sys_poll(data.fds, data.nfds, 0)) == 0) && + (f_wait != 0)) { + _thread_run->data.poll_data = &data; _thread_run->interrupted = 0; _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); if (_thread_run->interrupted) { errno = EINTR; + data.nfds = 0; ret = -1; } else ret = data.nfds; } } - /* clean up the locks */ - for (i = 0; i < numfds; i++) - if (FD_ISSET(i, &read_locks)) - _FD_UNLOCK(i, FD_READ); - for (i = 0; i < numfds; i++) - if (FD_ISSET(i, &rdwr_locks)) - _FD_UNLOCK(i, FD_RDWR); - for (i = 0; i < numfds; i++) - if (FD_ISSET(i, &write_locks)) - _FD_UNLOCK(i, FD_WRITE); if (ret >= 0) { - if (readfds != NULL) { - for (i = 0; i < numfds; i++) { - if (FD_ISSET(i, readfds) && - !FD_ISSET(i, &data.readfds)) { - FD_CLR(i, readfds); + numfds = 0; + for (i = 0; i < fd_count; i++) { + /* + * Check the results of the poll and clear + * this file descriptor from the fdset if + * the requested event wasn't ready. + */ + got_one = 0; + if (readfds != NULL) { + if (FD_ISSET(data.fds[i].fd, readfds)) { + if (data.fds[i].revents & (POLLIN | + POLLRDNORM)) + got_one = 1; + else + FD_CLR(data.fds[i].fd, readfds); } } - } - if (writefds != NULL) { - for (i = 0; i < numfds; i++) { - if (FD_ISSET(i, writefds) && - !FD_ISSET(i, &data.writefds)) { - FD_CLR(i, writefds); + if (writefds != NULL) { + if (FD_ISSET(data.fds[i].fd, writefds)) { + if (data.fds[i].revents & (POLLOUT | + POLLWRNORM | POLLWRBAND)) + got_one = 1; + else + FD_CLR(data.fds[i].fd, + writefds); } } - } - if (exceptfds != NULL) { - for (i = 0; i < numfds; i++) { - if (FD_ISSET(i, exceptfds) && - !FD_ISSET(i, &data.exceptfds)) { - FD_CLR(i, exceptfds); + if (exceptfds != NULL) { + if (FD_ISSET(data.fds[i].fd, exceptfds)) { + if (data.fds[i].revents & (POLLRDBAND | + POLLPRI | POLLHUP | POLLERR | + POLLNVAL)) + got_one = 1; + else + FD_CLR(data.fds[i].fd, + exceptfds); } } + if (got_one) + numfds++; } + ret = numfds; } return (ret); diff --git a/lib/libpthread/uthread/uthread_self.c b/lib/libpthread/uthread/uthread_self.c index d9a5b26092b..0ff4f7f3ba6 100644 --- a/lib/libpthread/uthread/uthread_self.c +++ b/lib/libpthread/uthread/uthread_self.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_self.c,v 1.3 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_self.c,v 1.2 1999/01/10 23:10:26 d Exp $ + * $FreeBSD: uthread_self.c,v 1.3 1999/08/28 00:03:46 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libpthread/uthread/uthread_sendmsg.c b/lib/libpthread/uthread/uthread_sendmsg.c index db1b49d2016..36bc6a62439 100644 --- a/lib/libpthread/uthread/uthread_sendmsg.c +++ b/lib/libpthread/uthread/uthread_sendmsg.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sendmsg.c,v 1.3 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sendmsg.c,v 1.2 1999/01/06 05:29:26 d Exp $ + * $FreeBSD: uthread_sendmsg.c,v 1.4 1999/08/28 00:03:46 peter Exp $ */ #include <errno.h> #include <sys/types.h> diff --git a/lib/libpthread/uthread/uthread_sendto.c b/lib/libpthread/uthread/uthread_sendto.c index 8eacbd509d9..b0a8c059a1e 100644 --- a/lib/libpthread/uthread/uthread_sendto.c +++ b/lib/libpthread/uthread/uthread_sendto.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sendto.c,v 1.4 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sendto.c,v 1.3 1999/02/16 16:41:13 millert Exp $ + * $FreeBSD: uthread_sendto.c,v 1.5 1999/08/28 00:03:46 peter Exp $ */ #include <errno.h> #include <sys/types.h> @@ -40,7 +41,7 @@ #include "pthread_private.h" ssize_t -sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t to_len) +sendto(int fd, const void *msg, size_t len, int flags, const struct sockaddr * to, socklen_t to_len) { int ret; diff --git a/lib/libpthread/uthread/uthread_seterrno.c b/lib/libpthread/uthread/uthread_seterrno.c index e63e9ba8d4d..41425e5b134 100644 --- a/lib/libpthread/uthread/uthread_seterrno.c +++ b/lib/libpthread/uthread/uthread_seterrno.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_seterrno.c,v 1.3 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_seterrno.c,v 1.2 1999/01/06 05:29:26 d Exp $ + * $FreeBSD: uthread_seterrno.c,v 1.4 1999/08/28 00:03:46 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> diff --git a/lib/libpthread/uthread/uthread_setprio.c b/lib/libpthread/uthread/uthread_setprio.c index 575eb62da2c..b0be80a20ad 100644 --- a/lib/libpthread/uthread/uthread_setprio.c +++ b/lib/libpthread/uthread/uthread_setprio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_setprio.c,v 1.4 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_setprio.c,v 1.5 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_setprio.c,v 1.6 1999/08/28 00:03:47 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_setschedparam.c b/lib/libpthread/uthread/uthread_setschedparam.c index 0024460c003..26e1b61d017 100644 --- a/lib/libpthread/uthread/uthread_setschedparam.c +++ b/lib/libpthread/uthread/uthread_setschedparam.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_setschedparam.c,v 1.1 1999/05/26 00:18:25 d Exp $ */ +/* $OpenBSD: uthread_setschedparam.c,v 1.2 1999/11/25 07:01:43 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_setschedparam.c,v 1.3 1999/08/28 00:03:47 peter Exp $ */ #include <errno.h> #include <sys/param.h> @@ -51,10 +52,10 @@ pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *p /* Find the thread in the list of active threads: */ else if ((ret = _find_thread(pthread)) == 0) { /* - * Guard against being preempted by a scheduling - * signal: + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); if (param->sched_priority != pthread->base_priority) { /* @@ -62,8 +63,7 @@ pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *p * queue before any adjustments are made to its * active priority: */ - if ((pthread != _thread_run) && - (pthread->state == PS_RUNNING)) { + if ((pthread->flags & PTHREAD_FLAGS_IN_PRIOQ) != 0) { in_readyq = 1; old_prio = pthread->active_priority; PTHREAD_PRIOQ_REMOVE(pthread); @@ -104,10 +104,10 @@ pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *p pthread->attr.sched_policy = policy; /* - * Renable preemption and yield if a scheduling signal - * arrived while in the critical region: + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } return(ret); } diff --git a/lib/libpthread/uthread/uthread_setsockopt.c b/lib/libpthread/uthread/uthread_setsockopt.c index 67be1fe195d..77cda0a65c1 100644 --- a/lib/libpthread/uthread/uthread_setsockopt.c +++ b/lib/libpthread/uthread/uthread_setsockopt.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_setsockopt.c,v 1.4 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_setsockopt.c,v 1.3 1999/02/16 16:40:01 deraadt Exp $ + * $FreeBSD: uthread_setsockopt.c,v 1.5 1999/08/28 00:03:47 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libpthread/uthread/uthread_shutdown.c b/lib/libpthread/uthread/uthread_shutdown.c index 4923d34cec4..991fb2c932d 100644 --- a/lib/libpthread/uthread/uthread_shutdown.c +++ b/lib/libpthread/uthread/uthread_shutdown.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_shutdown.c,v 1.3 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_shutdown.c,v 1.2 1999/01/06 05:29:27 d Exp $ + * $FreeBSD: uthread_shutdown.c,v 1.6 1999/08/28 00:03:48 peter Exp $ */ #include <errno.h> #include <sys/types.h> diff --git a/lib/libpthread/uthread/uthread_sig.c b/lib/libpthread/uthread/uthread_sig.c index 1d32d376fe0..465d5d06e99 100644 --- a/lib/libpthread/uthread/uthread_sig.c +++ b/lib/libpthread/uthread/uthread_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sig.c,v 1.5 1999/05/26 00:18:26 d Exp $ */ +/* $OpenBSD: uthread_sig.c,v 1.6 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -21,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_sig.c,v 1.20 1999/09/29 15:18:39 marcel Exp $ */ #include <signal.h> #include <fcntl.h> @@ -39,115 +40,51 @@ #include <pthread.h> #include "pthread_private.h" -/* - * State change macro for signal handler: - */ -#define PTHREAD_SIG_NEW_STATE(thrd, newstate) { \ - if ((_thread_run->sched_defer_count == 0) && \ - (_thread_kern_in_sched == 0)) { \ - PTHREAD_NEW_STATE(thrd, newstate); \ - } else { \ - _waitingq_check_reqd = 1; \ - PTHREAD_SET_STATE(thrd, newstate); \ - } \ -} - /* Static variables: */ -static int volatile yield_on_unlock_thread = 0; -static spinlock_t thread_link_list_lock = _SPINLOCK_INITIALIZER; - -int _thread_sig_statistics[NSIG]; +static spinlock_t signal_lock = _SPINLOCK_INITIALIZER; +unsigned int pending_sigs[NSIG]; +unsigned int handled_sigs[NSIG]; +int volatile check_pending = 0; -/* Lock the thread list: */ +/* Initialize signal handling facility: */ void -_lock_thread_list() +_thread_sig_init(void) { - /* Lock the thread list: */ - _SPINLOCK(&thread_link_list_lock); -} - -/* Lock the thread list: */ -void -_unlock_thread_list() -{ - /* Unlock the thread list: */ - _SPINUNLOCK(&thread_link_list_lock); - - /* - * Check if a scheduler interrupt occurred while the thread - * list was locked: - */ - if (yield_on_unlock_thread) { - /* Reset the interrupt flag: */ - yield_on_unlock_thread = 0; + int i; - /* This thread has overstayed it's welcome: */ - sched_yield(); + /* Clear pending and handled signal counts: */ + for (i = 1; i < NSIG; i++) { + pending_sigs[i - 1] = 0; + handled_sigs[i - 1] = 0; } + + /* Clear the lock: */ + signal_lock.access_lock = 0; } void _thread_sig_handler(int sig, int code, struct sigcontext * scp) { - char c; - int i; - pthread_t pthread; - - /* - * Record the number of times this signal has been received - */ - _thread_sig_statistics[sig]++; - - /* - * Check if the pthread kernel has unblocked signals (or is about to) - * and was on its way into a _select when the current - * signal interrupted it: - */ - if (_thread_kern_in_select) { - /* Cast the signal number to a character variable: */ - c = sig; - - /* - * Write the signal number to the kernel pipe so that it will - * be ready to read when this signal handler returns. This - * means that the _select call will complete - * immediately. - */ - _thread_sys_write(_thread_kern_pipe[1], &c, 1); - } - - /* Check if the signal requires a dump of thread information: */ - if (sig == SIGINFO) - /* Dump thread information to file: */ - _thread_dump_info(); + char c; + int i; /* Check if an interval timer signal: */ - else if (sig == _SCHED_SIGNAL) { - /* Check if the scheduler interrupt has come at an - * unfortunate time which one of the threads is - * modifying the thread list: - */ - if (_atomic_is_locked(&thread_link_list_lock.access_lock)) + if (sig == _SCHED_SIGNAL) { + if (_thread_kern_in_sched != 0) { /* - * Set a flag so that the thread that has - * the lock yields when it unlocks the - * thread list: + * The scheduler is already running; ignore this + * signal. */ - yield_on_unlock_thread = 1; - + } /* * Check if the scheduler interrupt has come when * the currently running thread has deferred thread - * scheduling. + * signals. */ - else if (_thread_run->sched_defer_count) - _thread_run->yield_on_sched_undefer = 1; + else if (_thread_run->sig_defer_count > 0) + _thread_run->yield_on_sig_undefer = 1; - /* - * Check if the kernel has not been interrupted while - * executing scheduler code: - */ - else if (!_thread_kern_in_sched) { + else { /* * Schedule the next thread. This function is not * expected to return because it will do a longjmp @@ -161,6 +98,72 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) */ PANIC("Returned to signal function from scheduler"); } + } + /* + * Check if the kernel has been interrupted while the scheduler + * is accessing the scheduling queues or if there is a currently + * running thread that has deferred signals. + */ + else if ((_queue_signals != 0) || ((_thread_kern_in_sched == 0) && + (_thread_run->sig_defer_count > 0))) { + /* Cast the signal number to a character variable: */ + c = sig; + + /* + * Write the signal number to the kernel pipe so that it will + * be ready to read when this signal handler returns. + */ + _thread_sys_write(_thread_kern_pipe[1], &c, 1); + + /* Indicate that there are queued signals in the pipe. */ + _sigq_check_reqd = 1; + } + else { + if (_atomic_lock(&signal_lock.access_lock)) { + /* There is another signal handler running: */ + pending_sigs[sig - 1]++; + check_pending = 1; + } + else { + /* It's safe to handle the signal now. */ + _thread_sig_handle(sig, scp); + + /* Reset the pending and handled count back to 0: */ + pending_sigs[sig - 1] = 0; + handled_sigs[sig - 1] = 0; + + signal_lock.access_lock = 0; + } + + /* Enter a loop to process pending signals: */ + while ((check_pending != 0) && + (_atomic_lock(&signal_lock.access_lock) == 0)) { + check_pending = 0; + for (i = 1; i < NSIG; i++) { + if (pending_sigs[i - 1] > handled_sigs[i - 1]) + _thread_sig_handle(i, scp); + } + signal_lock.access_lock = 0; + } + } +} + +void +_thread_sig_handle(int sig, struct sigcontext * scp) +{ + int i; + pthread_t pthread, pthread_next; + + /* Check if the signal requires a dump of thread information: */ + if (sig == SIGINFO) + /* Dump thread information to file: */ + _thread_dump_info(); + + /* Check if an interval timer signal: */ + else if (sig == _SCHED_SIGNAL) { + /* + * This shouldn't ever occur (should this panic?). + */ } else { /* Check if a child has terminated: */ if (sig == SIGCHLD) { @@ -192,10 +195,9 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) * Enter a loop to discard pending SIGCONT * signals: */ - for (pthread = _thread_link_list; - pthread != NULL; - pthread = pthread->nxt) + TAILQ_FOREACH(pthread, &_thread_list, tle) { sigdelset(&pthread->sigpend,SIGCONT); + } } /* @@ -205,11 +207,18 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) * if there are multiple waiters, we'll give it to the * first one we find. */ - TAILQ_FOREACH(pthread, &_waitingq, pqe) { + for (pthread = TAILQ_FIRST(&_waitingq); + pthread != NULL; pthread = pthread_next) { + /* + * Grab the next thread before possibly destroying + * the link entry. + */ + pthread_next = TAILQ_NEXT(pthread, pqe); + if ((pthread->state == PS_SIGWAIT) && sigismember(pthread->data.sigwait, sig)) { /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; @@ -228,18 +237,26 @@ _thread_sig_handler(int sig, int code, struct sigcontext * scp) * Enter a loop to process each thread in the linked * list: */ - for (pthread = _thread_link_list; pthread != NULL; - pthread = pthread->nxt) { + TAILQ_FOREACH(pthread, &_thread_list, tle) { pthread_t pthread_saved = _thread_run; + /* Current thread inside critical region? */ + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count++; + _thread_run = pthread; _thread_signal(pthread,sig); + /* * Dispatch pending signals to the * running thread: */ _dispatch_signals(); _thread_run = pthread_saved; + + /* Current thread inside critical region? */ + if (_thread_run->sig_defer_count > 0) + pthread->sig_defer_count--; } } @@ -292,7 +309,7 @@ _thread_signal(pthread_t pthread, int sig) pthread->interrupted = 1; /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; @@ -304,6 +321,7 @@ _thread_signal(pthread_t pthread, int sig) */ case PS_FDR_WAIT: case PS_FDW_WAIT: + case PS_POLL_WAIT: case PS_SLEEP_WAIT: case PS_SELECT_WAIT: if (sig != SIGCHLD || @@ -311,8 +329,11 @@ _thread_signal(pthread_t pthread, int sig) /* Flag the operation as interrupted: */ pthread->interrupted = 1; + if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) + PTHREAD_WORKQ_REMOVE(pthread); + /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; @@ -327,7 +348,7 @@ _thread_signal(pthread_t pthread, int sig) if (!sigismember(&pthread->sigmask, sig) && _thread_sigact[sig - 1].sa_handler != SIG_DFL) { /* Change the state of the thread to run: */ - PTHREAD_SIG_NEW_STATE(pthread,PS_RUNNING); + PTHREAD_NEW_STATE(pthread,PS_RUNNING); /* Return the signal number: */ pthread->signo = sig; diff --git a/lib/libpthread/uthread/uthread_sigaction.c b/lib/libpthread/uthread/uthread_sigaction.c index 6d709a8803f..de0aaeb7bfe 100644 --- a/lib/libpthread/uthread/uthread_sigaction.c +++ b/lib/libpthread/uthread/uthread_sigaction.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigaction.c,v 1.5 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigaction.c,v 1.4 1999/05/26 00:18:26 d Exp $ + * $FreeBSD: uthread_sigaction.c,v 1.8 1999/08/28 00:03:48 peter Exp $ */ #include <signal.h> #include <errno.h> @@ -78,6 +79,9 @@ sigaction(int sig, const struct sigaction * act, struct sigaction * oact) gact.sa_mask = act->sa_mask; gact.sa_flags = 0; + /* Ensure the scheduling signal is masked: */ + sigaddset(&gact.sa_mask, _SCHED_SIGNAL); + /* * Check if the signal handler is being set to * the default or ignore handlers: diff --git a/lib/libpthread/uthread/uthread_sigaltstack.c b/lib/libpthread/uthread/uthread_sigaltstack.c index 9a1f9614542..fff62da3be2 100644 --- a/lib/libpthread/uthread/uthread_sigaltstack.c +++ b/lib/libpthread/uthread/uthread_sigaltstack.c @@ -1,6 +1,4 @@ -/* - * $OpenBSD: uthread_sigaltstack.c,v 1.1 1998/11/09 03:13:20 d Exp $ - */ +/* $OpenBSD: uthread_sigaltstack.c,v 1.2 1999/11/25 07:01:44 d Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_sigblock.c b/lib/libpthread/uthread/uthread_sigblock.c index 5b317d01472..dd08126ce70 100644 --- a/lib/libpthread/uthread/uthread_sigblock.c +++ b/lib/libpthread/uthread/uthread_sigblock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigblock.c,v 1.3 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigblock.c,v 1.2 1999/01/06 05:29:27 d Exp $ + * $FreeBSD: uthread_sigblock.c,v 1.4 1999/08/28 00:03:49 peter Exp $ */ #include <signal.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_sigmask.c b/lib/libpthread/uthread/uthread_sigmask.c index bdaf30e09f8..6de570535e4 100644 --- a/lib/libpthread/uthread/uthread_sigmask.c +++ b/lib/libpthread/uthread/uthread_sigmask.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigmask.c,v 1.3 1999/11/25 07:01:44 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigmask.c,v 1.2 1999/01/06 05:29:27 d Exp $ + * $FreeBSD: uthread_sigmask.c,v 1.5 1999/09/29 15:18:40 marcel Exp $ */ #include <errno.h> #include <signal.h> diff --git a/lib/libpthread/uthread/uthread_signal.c b/lib/libpthread/uthread/uthread_signal.c index 2e1f3d21f60..bd9b488b3d0 100644 --- a/lib/libpthread/uthread/uthread_signal.c +++ b/lib/libpthread/uthread/uthread_signal.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_signal.c,v 1.4 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_signal.c,v 1.3 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_signal.c,v 1.4 1999/08/28 00:03:49 peter Exp $ */ #include <signal.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_sigpending.c b/lib/libpthread/uthread/uthread_sigpending.c index 2daf3159b59..9921ee5a237 100644 --- a/lib/libpthread/uthread/uthread_sigpending.c +++ b/lib/libpthread/uthread/uthread_sigpending.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sigpending.c,v 1.1 1999/05/26 00:18:26 d Exp $ */ +/* $OpenBSD: uthread_sigpending.c,v 1.2 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1999 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -21,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_sigpending.c,v 1.3 1999/08/28 00:03:50 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_sigprocmask.c b/lib/libpthread/uthread/uthread_sigprocmask.c index c3f0b1dda16..28d4c3b1efe 100644 --- a/lib/libpthread/uthread/uthread_sigprocmask.c +++ b/lib/libpthread/uthread/uthread_sigprocmask.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigprocmask.c,v 1.3 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigprocmask.c,v 1.2 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_sigprocmask.c,v 1.6 1999/09/29 15:18:40 marcel Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_sigsetmask.c b/lib/libpthread/uthread/uthread_sigsetmask.c index 1f416551142..878efe36add 100644 --- a/lib/libpthread/uthread/uthread_sigsetmask.c +++ b/lib/libpthread/uthread/uthread_sigsetmask.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigsetmask.c,v 1.3 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigsetmask.c,v 1.2 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_sigsetmask.c,v 1.4 1999/08/28 00:03:50 peter Exp $ */ #include <signal.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_sigsuspend.c b/lib/libpthread/uthread/uthread_sigsuspend.c index e0035c0fa1a..bd7e2094bd9 100644 --- a/lib/libpthread/uthread/uthread_sigsuspend.c +++ b/lib/libpthread/uthread/uthread_sigsuspend.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigsuspend.c,v 1.4 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigsuspend.c,v 1.3 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_sigsuspend.c,v 1.7 1999/08/28 00:03:50 peter Exp $ */ #include <signal.h> #include <errno.h> diff --git a/lib/libpthread/uthread/uthread_sigwait.c b/lib/libpthread/uthread/uthread_sigwait.c index 00cf99ef20b..84db32d0470 100644 --- a/lib/libpthread/uthread/uthread_sigwait.c +++ b/lib/libpthread/uthread/uthread_sigwait.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_sigwait.c,v 1.7 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_sigwait.c,v 1.6 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_sigwait.c,v 1.10 1999/09/30 14:51:31 marcel Exp $ */ #include <signal.h> #include <errno.h> @@ -42,7 +43,7 @@ sigwait(const sigset_t * set, int *sig) { int ret = 0; int i; - sigset_t tempset; + sigset_t tempset, waitset; struct sigaction act; /* This is a cancellation point: */ @@ -55,17 +56,23 @@ sigwait(const sigset_t * set, int *sig) act.sa_flags = SA_RESTART; act.sa_mask = *set; + /* Ensure the scheduling signal is masked: */ + sigaddset(&act.sa_mask, _SCHED_SIGNAL); + /* - * These signals can't be waited on. + * Initialize the set of signals that will be waited on: */ - sigdelset(&act.sa_mask, SIGKILL); - sigdelset(&act.sa_mask, SIGSTOP); - sigdelset(&act.sa_mask, _SCHED_SIGNAL); - sigdelset(&act.sa_mask, SIGCHLD); - sigdelset(&act.sa_mask, SIGINFO); + waitset = *set; + + /* These signals can't be waited on. */ + sigdelset(&waitset, SIGKILL); + sigdelset(&waitset, SIGSTOP); + sigdelset(&waitset, _SCHED_SIGNAL); + sigdelset(&waitset, SIGCHLD); + sigdelset(&waitset, SIGINFO); /* Check to see if a pending signal is in the wait mask. */ - if ((tempset = (_thread_run->sigpend & act.sa_mask))) { + if (tempset = (_thread_run->sigpend & waitset)) { /* Enter a loop to find a pending signal: */ for (i = 1; i < NSIG; i++) { if (sigismember (&tempset, i)) @@ -80,6 +87,7 @@ sigwait(const sigset_t * set, int *sig) /* No longer in a cancellation point: */ _thread_leave_cancellation_point(); + return (0); } @@ -87,17 +95,17 @@ sigwait(const sigset_t * set, int *sig) * Enter a loop to find the signals that are SIG_DFL. For * these signals we must install a dummy signal handler in * order for the kernel to pass them in to us. POSIX says - * that the application must explicitly install a dummy + * that the _application_ must explicitly install a dummy * handler for signals that are SIG_IGN in order to sigwait * on them. Note that SIG_IGN signals are left in the * mask because a subsequent sigaction could enable an * ignored signal. */ for (i = 1; i < NSIG; i++) { - if (sigismember(&act.sa_mask, i)) { - if (_thread_sigact[i - 1].sa_handler == SIG_DFL) - if (_thread_sys_sigaction(i,&act,NULL) != 0) - ret = -1; + if (sigismember(&waitset, i) && + (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { + if (_thread_sys_sigaction(i,&act,NULL) != 0) + ret = -1; } } if (ret == 0) { @@ -107,7 +115,7 @@ sigwait(const sigset_t * set, int *sig) * mask is independent of the threads signal mask * and requires separate storage. */ - _thread_run->data.sigwait = &act.sa_mask; + _thread_run->data.sigwait = &waitset; /* Wait for a signal: */ _thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__); @@ -125,7 +133,7 @@ sigwait(const sigset_t * set, int *sig) /* Restore the sigactions: */ act.sa_handler = SIG_DFL; for (i = 1; i < NSIG; i++) { - if (sigismember(&act.sa_mask, i) && + if (sigismember(&waitset, i) && (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { if (_thread_sys_sigaction(i,&act,NULL) != 0) ret = -1; diff --git a/lib/libpthread/uthread/uthread_single_np.c b/lib/libpthread/uthread/uthread_single_np.c index 39c90837653..84208893b16 100644 --- a/lib/libpthread/uthread/uthread_single_np.c +++ b/lib/libpthread/uthread/uthread_single_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_single_np.c,v 1.3 1999/11/25 07:01:45 d Exp $ */ /* * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_single_np.c,v 1.2 1999/01/06 05:29:28 d Exp $ + * $FreeBSD: uthread_single_np.c,v 1.3 1999/08/28 00:03:51 peter Exp $ */ #include <string.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_socket.c b/lib/libpthread/uthread/uthread_socket.c index ea848d3c144..b4a96b8185a 100644 --- a/lib/libpthread/uthread/uthread_socket.c +++ b/lib/libpthread/uthread/uthread_socket.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_socket.c,v 1.3 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_socket.c,v 1.2 1999/01/06 05:29:29 d Exp $ + * $FreeBSD: uthread_socket.c,v 1.5 1999/08/28 00:03:51 peter Exp $ */ #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/libpthread/uthread/uthread_socketpair.c b/lib/libpthread/uthread/uthread_socketpair.c index d78eaad0197..482a3d71b6c 100644 --- a/lib/libpthread/uthread/uthread_socketpair.c +++ b/lib/libpthread/uthread/uthread_socketpair.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_socketpair.c,v 1.3 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,14 +30,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_socketpair.c,v 1.4 1998/04/29 09:59:27 jb Exp $ - * $OpenBSD: uthread_socketpair.c,v 1.2 1998/12/23 22:49:46 d Exp $ + * $FreeBSD: uthread_socketpair.c,v 1.6 1999/08/28 00:03:52 peter Exp $ * */ #include <sys/types.h> #include <sys/socket.h> #include <fcntl.h> -#include <unistd.h> #ifdef _THREAD_SAFE #include <pthread.h> #include "pthread_private.h" diff --git a/lib/libpthread/uthread/uthread_spec.c b/lib/libpthread/uthread/uthread_spec.c index 6a4b9c9c5e4..1ac1df46fe4 100644 --- a/lib/libpthread/uthread/uthread_spec.c +++ b/lib/libpthread/uthread/uthread_spec.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_spec.c,v 1.6 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_spec.c,v 1.5 1999/05/14 22:29:52 alex Exp $ + * $FreeBSD: uthread_spec.c,v 1.13 1999/08/28 00:03:52 peter Exp $ */ #include <signal.h> #include <stdlib.h> @@ -113,7 +114,7 @@ _thread_cleanupspecific(void) _SPINUNLOCK(&key_table[key].lock); /* - * If there is a destructor, call it + * If there is a destructore, call it * with the key table entry unlocked: */ if (destructor) diff --git a/lib/libpthread/uthread/uthread_spinlock.c b/lib/libpthread/uthread/uthread_spinlock.c index 3ea96013bc6..6e7a60706c4 100644 --- a/lib/libpthread/uthread/uthread_spinlock.c +++ b/lib/libpthread/uthread/uthread_spinlock.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_spinlock.c,v 1.6 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_spinlock.c,v 1.5 1999/03/23 05:07:56 jb Exp $ - * $OpenBSD: uthread_spinlock.c,v 1.5 1999/05/26 00:18:26 d Exp $ + * $FreeBSD: uthread_spinlock.c,v 1.7 1999/08/28 00:03:52 peter Exp $ * */ @@ -63,7 +63,7 @@ _spinlock(spinlock_t *lck) } /* The running thread now owns the lock: */ - lck->lock_owner = _thread_run; + lck->lock_owner = (long) _thread_run; } /* @@ -101,7 +101,7 @@ _spinlock_debug(spinlock_t *lck, const char *fname, int lineno) } /* The running thread now owns the lock: */ - lck->lock_owner = _thread_run; + lck->lock_owner = (long) _thread_run; lck->fname = fname; lck->lineno = lineno; } diff --git a/lib/libpthread/uthread/uthread_stack.c b/lib/libpthread/uthread/uthread_stack.c new file mode 100644 index 00000000000..940f295efd3 --- /dev/null +++ b/lib/libpthread/uthread/uthread_stack.c @@ -0,0 +1,97 @@ +/* $OpenBSD: uthread_stack.c,v 1.1 1999/11/25 07:01:46 d Exp $ */ + +/* + * Thread stack allocation. + * + * Stack pointers are assumed to work their way down (backwards) to the + * beginning of the stack storage. The first page of this storage is + * protected using mprotect() so as to generate a SIGSEGV if a thread + * overflows its stack. + */ + +#include <stddef.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/user.h> +#include <sys/mman.h> +#include <pthread.h> +#include <pthread_np.h> +#include "pthread_private.h" + +struct stack * +_thread_stack_alloc(base, size) + void *base; + size_t size; +{ + struct stack *stack; + + /* Maintain a queue of default-sized stacks that we can re-use. */ + if (size == PTHREAD_STACK_DEFAULT) { + if (pthread_mutex_lock(&_gc_mutex) != 0) + PANIC("Cannot lock gc mutex"); + + if ((stack = SLIST_FIRST(&_stackq)) != NULL) { + SLIST_REMOVE_HEAD(&_stackq, qe); + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + return stack; + } + if (pthread_mutex_unlock(&_gc_mutex) != 0) + PANIC("Cannot unlock gc mutex"); + } + + /* Allocate some storage to hold information about the stack: */ + stack = (struct stack *)malloc(sizeof (struct stack)); + if (stack == NULL) + return NULL; + + if (base != NULL) { + /* Use the user's storage */ + stack->base = base; + stack->size = size; + stack->redzone = NULL; + stack->storage = NULL; + return stack; + } + + /* Allocate some storage for the stack, with some overhead: */ + stack->storage = malloc(size + NBPG * 2); + if (stack->storage == NULL) { + free(stack); + return NULL; + } + + /* The red zone is the first physical page of the storage: */ + stack->redzone = (void*)(((int)stack->storage + NBPG - 1) & + ~(NBPG - 1)); + if (mprotect(stack->redzone, NBPG, 0) == -1) + PANIC("Cannot protect stack red zone"); + + /* Find the useful range of the stack. */ + stack->base = stack->redzone + NBPG; + stack->size = size; + + return stack; +} + +void +_thread_stack_free(stack) + struct stack *stack; +{ + /* Cache allocated stacks of default size. */ + if (stack->storage != NULL && stack->size == PTHREAD_STACK_DEFAULT) + SLIST_INSERT_HEAD(&_stackq, stack, qe); + else { + /* Restore storage protection to what malloc expects: */ + if (stack->redzone) + mprotect(stack->redzone, NBPG, PROT_READ|PROT_WRITE); + + /* Free storage */ + if (stack->storage) + free(stack->storage); + + /* Free stack information storage. */ + free(stack); + } +} diff --git a/lib/libpthread/uthread/uthread_suspend_np.c b/lib/libpthread/uthread/uthread_suspend_np.c index daeb60a661a..8c455e0a11d 100644 --- a/lib/libpthread/uthread/uthread_suspend_np.c +++ b/lib/libpthread/uthread/uthread_suspend_np.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_suspend_np.c,v 1.4 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_suspend_np.c,v 1.3 1999/05/26 00:18:26 d Exp $ + * $FreeBSD: uthread_suspend_np.c,v 1.7 1999/08/28 00:03:53 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE @@ -53,20 +54,19 @@ pthread_suspend_np(pthread_t thread) } /* - * Guard against preemption by a scheduling signal. - * A change of thread state modifies the waiting - * and priority queues. + * Defer signals to protect the scheduling queues from + * access by the signal handler: */ - _thread_kern_sched_defer(); + _thread_kern_sig_defer(); /* Suspend the thread. */ PTHREAD_NEW_STATE(thread,PS_SUSPENDED); /* - * Reenable preemption and yield if a scheduling signal - * occurred while in the critical region. + * Undefer and handle pending signals, yielding if + * necessary: */ - _thread_kern_sched_undefer(); + _thread_kern_sig_undefer(); } return(ret); } diff --git a/lib/libpthread/uthread/uthread_switch_np.c b/lib/libpthread/uthread/uthread_switch_np.c index 598edacd2bb..2e7351b9697 100644 --- a/lib/libpthread/uthread/uthread_switch_np.c +++ b/lib/libpthread/uthread/uthread_switch_np.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_switch_np.c,v 1.1 1999/05/26 00:18:26 d Exp $ */ +/* $OpenBSD: uthread_switch_np.c,v 1.2 1999/11/25 07:01:46 d Exp $ */ /* * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>. * All rights reserved. @@ -30,6 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $FreeBSD: uthread_switch_np.c,v 1.3 1999/08/28 00:03:53 peter Exp $ */ #include <errno.h> #ifdef _THREAD_SAFE diff --git a/lib/libpthread/uthread/uthread_vfork.c b/lib/libpthread/uthread/uthread_vfork.c index a3b0ee5bb06..32ac5cd33c1 100644 --- a/lib/libpthread/uthread/uthread_vfork.c +++ b/lib/libpthread/uthread/uthread_vfork.c @@ -1,6 +1,4 @@ -/* - * $OpenBSD: uthread_vfork.c,v 1.1 1998/11/09 03:13:21 d Exp $ - */ +/* $OpenBSD: uthread_vfork.c,v 1.2 1999/11/25 07:01:47 d Exp $ */ #include <unistd.h> #ifdef _THREAD_SAFE @@ -9,4 +7,4 @@ vfork(void) { return (fork()); } -#endif /* _THREAD_SAFE */ +#endif diff --git a/lib/libpthread/uthread/uthread_wait4.c b/lib/libpthread/uthread/uthread_wait4.c index aef609468d4..0c3efa803f2 100644 --- a/lib/libpthread/uthread/uthread_wait4.c +++ b/lib/libpthread/uthread/uthread_wait4.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_wait4.c,v 1.5 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_wait4.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_wait4.c,v 1.5 1999/08/28 00:03:53 peter Exp $ */ #include <errno.h> #include <sys/wait.h> @@ -45,6 +46,8 @@ wait4(pid_t pid, int *istat, int options, struct rusage * rusage) /* This is a cancellation point: */ _thread_enter_cancellation_point(); + _thread_kern_sig_defer(); + /* Perform a non-blocking wait4 syscall: */ while ((ret = _thread_sys_wait4(pid, istat, options | WNOHANG, rusage)) == 0 && (options & WNOHANG) == 0) { /* Reset the interrupted operation flag: */ @@ -61,6 +64,8 @@ wait4(pid_t pid, int *istat, int options, struct rusage * rusage) } } + _thread_kern_sig_undefer(); + /* No longer in a cancellation point: */ _thread_leave_cancellation_point(); diff --git a/lib/libpthread/uthread/uthread_write.c b/lib/libpthread/uthread/uthread_write.c index 7d91092f9ae..cac06ef3bb5 100644 --- a/lib/libpthread/uthread/uthread_write.c +++ b/lib/libpthread/uthread/uthread_write.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_write.c,v 1.5 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_write.c,v 1.10 1998/09/07 21:55:01 alex Exp $ - * $OpenBSD: uthread_write.c,v 1.4 1999/06/09 07:16:17 d Exp $ + * $FreeBSD: uthread_write.c,v 1.12 1999/08/28 00:03:54 peter Exp $ * */ #include <sys/types.h> @@ -51,18 +51,12 @@ write(int fd, const void *buf, size_t nbytes) ssize_t num = 0; ssize_t ret; - /* This is a cancellation point: */ - _thread_enter_cancellation_point(); - /* POSIX says to do just this: */ - if (nbytes == 0) { - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (0); - } + if (nbytes == 0) + ret = 0; /* Lock the file descriptor for write: */ - if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { + else if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) == 0) { /* Get the read/write mode type: */ type = _thread_fd_table[fd]->flags & O_ACCMODE; @@ -70,12 +64,10 @@ write(int fd, const void *buf, size_t nbytes) if (type != O_WRONLY && type != O_RDWR) { /* File is not open for write: */ errno = EBADF; - _FD_UNLOCK(fd, FD_WRITE); - /* No longer in a cancellation point: */ - _thread_leave_cancellation_point(); - return (-1); + ret = -1; } + else { /* Check if file operations are to block */ blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0); @@ -136,7 +128,8 @@ write(int fd, const void *buf, size_t nbytes) /* Return the number of bytes written: */ ret = num; } - _FD_UNLOCK(fd, FD_RDWR); + } + _FD_UNLOCK(fd, FD_WRITE); } /* No longer in a cancellation point: */ diff --git a/lib/libpthread/uthread/uthread_writev.c b/lib/libpthread/uthread/uthread_writev.c index dc280c9145c..411b3bc0238 100644 --- a/lib/libpthread/uthread/uthread_writev.c +++ b/lib/libpthread/uthread/uthread_writev.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_writev.c,v 1.3 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,8 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: uthread_writev.c,v 1.10 1998/06/14 09:36:14 jb Exp $ - * $OpenBSD: uthread_writev.c,v 1.2 1998/12/23 22:49:47 d Exp $ + * $FreeBSD: uthread_writev.c,v 1.12 1999/08/28 00:03:55 peter Exp $ * */ #include <sys/types.h> diff --git a/lib/libpthread/uthread/uthread_yield.c b/lib/libpthread/uthread/uthread_yield.c index 1844be51fcc..0dfaaf14438 100644 --- a/lib/libpthread/uthread/uthread_yield.c +++ b/lib/libpthread/uthread/uthread_yield.c @@ -1,3 +1,4 @@ +/* $OpenBSD: uthread_yield.c,v 1.3 1999/11/25 07:01:47 d Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -20,7 +21,7 @@ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: uthread_yield.c,v 1.2 1999/01/06 05:29:29 d Exp $ + * $FreeBSD: uthread_yield.c,v 1.4 1999/08/28 00:03:55 peter Exp $ */ #ifdef _THREAD_SAFE #include <pthread.h> |