Index: head/lib/libkse/Makefile =================================================================== --- head/lib/libkse/Makefile (revision 174111) +++ head/lib/libkse/Makefile (revision 174112) @@ -1,64 +1,63 @@ # $FreeBSD$ # # All library objects contain FreeBSD revision strings by default; they may be # excluded as a space-saving measure. To produce a library that does # not contain these strings, add -DSTRIP_FBSDID (see ) to CFLAGS # below. Note, there are no IDs for syscall stubs whose sources are generated. # To included legacy CSRG sccsid strings, add -DLIBC_SCCS and -DSYSLIBC_SCCS # (for system call stubs) to CFLAGS below. -DSYSLIBC_SCCS affects just the # system call stubs. .include .if ${DEFAULT_THREAD_LIB} == "libkse" || ${MK_LIBTHR} == "no" LIB=kse .if ${SHLIBDIR} == "/usr/lib" SHLIBDIR= /lib .endif .else SHLIB=kse .endif SHLIB_MAJOR= 3 CFLAGS+=-DPTHREAD_KERNEL CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR}/thread \ -I${.CURDIR}/../../include CFLAGS+=-I${.CURDIR}/arch/${MACHINE_ARCH}/include CFLAGS+=-I${.CURDIR}/sys CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf/${MACHINE_ARCH} CFLAGS+=-fno-builtin -CFLAGS+=-fno-strict-aliasing # Uncomment this if you want libkse to contain debug information for # thread locking. CFLAGS+=-D_LOCK_DEBUG -WARNS?=2 +WARNS?=3 # Uncomment this if you want to build a 1:1 threading mode library # however it is no longer strictly conformed to POSIX # CFLAGS+=-DSYSTEM_SCOPE_ONLY # Enable extra internal consistancy checks. CFLAGS+=-D_PTHREADS_INVARIANTS -Wall VERSION_MAP=${.CURDIR}/kse.map PRECIOUSLIB= .include "${.CURDIR}/arch/${MACHINE_ARCH}/Makefile.inc" .include "${.CURDIR}/support/Makefile.inc" .include "${.CURDIR}/sys/Makefile.inc" .include "${.CURDIR}/thread/Makefile.inc" .if ${DEFAULT_THREAD_LIB} == "libkse" || ${MK_LIBTHR} == "no" SYMLINKS+=lib${LIB}.a ${LIBDIR}/libpthread.a .if !defined(NO_PIC) SYMLINKS+=lib${LIB}.so ${LIBDIR}/libpthread.so .endif .if ${MK_PROFILE} != "no" SYMLINKS+=lib${LIB}_p.a ${LIBDIR}/libpthread_p.a .endif .endif .include Index: head/lib/libkse/arch/amd64/include/atomic_ops.h =================================================================== --- head/lib/libkse/arch/amd64/include/atomic_ops.h (revision 174111) +++ head/lib/libkse/arch/amd64/include/atomic_ops.h (revision 174112) @@ -1,57 +1,57 @@ /*- * Copyright (c) 2001 Daniel Eischen * 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. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ #ifndef _ATOMIC_OPS_H_ #define _ATOMIC_OPS_H_ /* * Atomic swap: * Atomic (tmp = *dst, *dst = val), then *res = tmp * * void atomic_swap64(intptr_t *dst, intptr_t val, intptr_t *res); */ static inline void -atomic_swap64(intptr_t *dst, intptr_t val, intptr_t *res) +atomic_swap64(volatile intptr_t *dst, intptr_t val, intptr_t *res) { __asm __volatile( "xchgq %2, %1; movq %2, %0" : "=m" (*res) : "m" (*dst), "r" (val) : "memory"); } static inline void -atomic_swap_int(int *dst, int val, int *res) +atomic_swap_int(volatile int *dst, int val, int *res) { __asm __volatile( "xchgl %2, %1; movl %2, %0" : "=m" (*res) : "m" (*dst), "r" (val) : "memory"); } #define atomic_swap_ptr(d, v, r) \ - atomic_swap64((intptr_t *)(d), (intptr_t)(v), (intptr_t *)(r)) + atomic_swap64((volatile intptr_t *)(d), (intptr_t)(v), (intptr_t *)(r)) #endif Index: head/lib/libkse/arch/amd64/include/pthread_md.h =================================================================== --- head/lib/libkse/arch/amd64/include/pthread_md.h (revision 174111) +++ head/lib/libkse/arch/amd64/include/pthread_md.h (revision 174112) @@ -1,268 +1,268 @@ /*- * Copyright (C) 2003 David Xu * Copyright (c) 2001 Daniel Eischen * 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. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ /* * Machine-dependent thread prototypes/definitions for the thread kernel. */ #ifndef _PTHREAD_MD_H_ #define _PTHREAD_MD_H_ #include #include #include #include #include #define KSE_STACKSIZE 16384 #define DTV_OFFSET offsetof(struct tcb, tcb_dtv) #define THR_GETCONTEXT(ucp) \ (void)_amd64_save_context(&(ucp)->uc_mcontext) #define THR_SETCONTEXT(ucp) \ (void)_amd64_restore_context(&(ucp)->uc_mcontext, 0, NULL) #define PER_KSE #undef PER_THREAD struct kse; struct pthread; struct tdv; /* * %fs points to a struct kcb. */ struct kcb { struct tcb *kcb_curtcb; struct kcb *kcb_self; /* self reference */ struct kse *kcb_kse; struct kse_mailbox kcb_kmbx; }; struct tcb { struct tcb *tcb_self; /* required by rtld */ void *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; void *tcb_spare[1]; /* align tcb_tmbx to 16 bytes */ struct kse_thr_mailbox tcb_tmbx; }; /* * Evaluates to the byte offset of the per-kse variable name. */ #define __kcb_offset(name) __offsetof(struct kcb, name) /* * Evaluates to the type of the per-kse variable name. */ #define __kcb_type(name) __typeof(((struct kcb *)0)->name) /* * Evaluates to the value of the per-kse variable name. */ #define KCB_GET64(name) ({ \ __kcb_type(name) __result; \ \ u_long __i; \ __asm __volatile("movq %%fs:%1, %0" \ : "=r" (__i) \ : "m" (*(u_long *)(__kcb_offset(name)))); \ __result = (__kcb_type(name))__i; \ \ __result; \ }) /* * Sets the value of the per-kse variable name to value val. */ #define KCB_SET64(name, val) ({ \ __kcb_type(name) __val = (val); \ \ u_long __i; \ __i = (u_long)__val; \ __asm __volatile("movq %1,%%fs:%0" \ : "=m" (*(u_long *)(__kcb_offset(name))) \ : "r" (__i)); \ }) static __inline u_long __kcb_readandclear64(volatile u_long *addr) { u_long result; __asm __volatile ( " xorq %0, %0;" " xchgq %%fs:%1, %0;" "# __kcb_readandclear64" : "=&r" (result) : "m" (*addr)); return (result); } #define KCB_READANDCLEAR64(name) ({ \ __kcb_type(name) __result; \ \ __result = (__kcb_type(name)) \ __kcb_readandclear64((u_long *)__kcb_offset(name)); \ __result; \ }) #define _kcb_curkcb() KCB_GET64(kcb_self) #define _kcb_curtcb() KCB_GET64(kcb_curtcb) #define _kcb_curkse() ((struct kse *)KCB_GET64(kcb_kmbx.km_udata)) #define _kcb_get_tmbx() KCB_GET64(kcb_kmbx.km_curthread) #define _kcb_set_tmbx(value) KCB_SET64(kcb_kmbx.km_curthread, (void *)value) #define _kcb_readandclear_tmbx() KCB_READANDCLEAR64(kcb_kmbx.km_curthread) /* * The constructors. */ struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *tcb); struct kcb *_kcb_ctor(struct kse *); void _kcb_dtor(struct kcb *); /* Called from the KSE to set its private data. */ static __inline void _kcb_set(struct kcb *kcb) { amd64_set_fsbase(kcb); } /* Get the current kcb. */ static __inline struct kcb * _kcb_get(void) { return (_kcb_curkcb()); } static __inline struct kse_thr_mailbox * _kcb_critical_enter(void) { struct kse_thr_mailbox *crit; crit = _kcb_readandclear_tmbx(); return (crit); } static __inline void _kcb_critical_leave(struct kse_thr_mailbox *crit) { _kcb_set_tmbx(crit); } static __inline int _kcb_in_critical(void) { return (_kcb_get_tmbx() == NULL); } static __inline void _tcb_set(struct kcb *kcb, struct tcb *tcb) { kcb->kcb_curtcb = tcb; } static __inline struct tcb * _tcb_get(void) { return (_kcb_curtcb()); } static __inline struct pthread * _get_curthread(void) { struct tcb *tcb; tcb = _kcb_curtcb(); if (tcb != NULL) return (tcb->tcb_thread); else return (NULL); } static __inline struct kse * _get_curkse(void) { return ((struct kse *)_kcb_curkse()); } void _amd64_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, size_t stacksz); int _amd64_restore_context(mcontext_t *mc, intptr_t val, intptr_t *loc); int _amd64_save_context(mcontext_t *mc); static __inline int _thread_enter_uts(struct tcb *tcb, struct kcb *kcb) { int ret; ret = _amd64_save_context(&tcb->tcb_tmbx.tm_context.uc_mcontext); if (ret == 0) { _amd64_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, kcb->kcb_kmbx.km_stack.ss_sp, kcb->kcb_kmbx.km_stack.ss_size); /* We should not reach here. */ return (-1); } else if (ret < 0) return (-1); return (0); } static __inline int _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) { extern int _libkse_debug; if ((kcb == NULL) || (tcb == NULL)) return (-1); kcb->kcb_curtcb = tcb; if (_libkse_debug == 0) { tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; if (setmbox != 0) _amd64_restore_context( &tcb->tcb_tmbx.tm_context.uc_mcontext, (intptr_t)&tcb->tcb_tmbx, - (intptr_t *)&kcb->kcb_kmbx.km_curthread); + (intptr_t *)(void *)&kcb->kcb_kmbx.km_curthread); else _amd64_restore_context( &tcb->tcb_tmbx.tm_context.uc_mcontext, 0, NULL); /* We should not reach here. */ } else { if (setmbox) kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); else kse_switchin(&tcb->tcb_tmbx, 0); } return (-1); } #endif Index: head/lib/libkse/arch/arm/include/atomic_ops.h =================================================================== --- head/lib/libkse/arch/arm/include/atomic_ops.h (revision 174111) +++ head/lib/libkse/arch/arm/include/atomic_ops.h (revision 174112) @@ -1,53 +1,53 @@ /*- * Copyright (c) 2001 Daniel Eischen * 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. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ #ifndef _ATOMIC_OPS_H_ #define _ATOMIC_OPS_H_ #include #include "thr_private.h" /* * Atomic swap: * Atomic (tmp = *dst, *dst = val), then *res = tmp * * void atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res); */ static inline void -atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res) +atomic_swap32(volatile intptr_t *dst, intptr_t val, intptr_t *res) { *res = __swp(val, dst); } #define atomic_swap_ptr(d, v, r) \ - atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r) + atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r) #define atomic_swap_int(d, v, r) \ - atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r) + atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r) #endif Index: head/lib/libkse/arch/i386/include/atomic_ops.h =================================================================== --- head/lib/libkse/arch/i386/include/atomic_ops.h (revision 174111) +++ head/lib/libkse/arch/i386/include/atomic_ops.h (revision 174112) @@ -1,51 +1,51 @@ /*- * Copyright (c) 2001 Daniel Eischen * 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. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ #ifndef _ATOMIC_OPS_H_ #define _ATOMIC_OPS_H_ /* * Atomic swap: * Atomic (tmp = *dst, *dst = val), then *res = tmp * * void atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res); */ static inline void -atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res) +atomic_swap32(volatile intptr_t *dst, intptr_t val, intptr_t *res) { __asm __volatile( "xchgl %2, %1; movl %2, %0" : "=m" (*res) : "m" (*dst), "r" (val) : "memory"); } #define atomic_swap_ptr(d, v, r) \ - atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r) + atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r) #define atomic_swap_int(d, v, r) \ - atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r) + atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r) #endif Index: head/lib/libkse/arch/i386/include/pthread_md.h =================================================================== --- head/lib/libkse/arch/i386/include/pthread_md.h (revision 174111) +++ head/lib/libkse/arch/i386/include/pthread_md.h (revision 174112) @@ -1,264 +1,264 @@ /*- * Copyright (c) 2002 Daniel Eischen . * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ /* * Machine-dependent thread prototypes/definitions for the thread kernel. */ #ifndef _PTHREAD_MD_H_ #define _PTHREAD_MD_H_ #include #include #include #include #include extern int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); extern int _thr_getcontext(mcontext_t *); #define KSE_STACKSIZE 16384 #define DTV_OFFSET offsetof(struct tcb, tcb_dtv) #define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) #define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) #define PER_KSE #undef PER_THREAD struct kse; struct pthread; /* * %gs points to a struct kcb. */ struct kcb { struct tcb *kcb_curtcb; struct kcb *kcb_self; /* self reference */ struct kse *kcb_kse; struct kse_mailbox kcb_kmbx; }; struct tcb { struct tcb *tcb_self; /* required by rtld */ void *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; void *tcb_spare; /* align tcb_tmbx to 16 bytes */ struct kse_thr_mailbox tcb_tmbx; }; /* * Evaluates to the byte offset of the per-kse variable name. */ #define __kcb_offset(name) __offsetof(struct kcb, name) /* * Evaluates to the type of the per-kse variable name. */ #define __kcb_type(name) __typeof(((struct kcb *)0)->name) /* * Evaluates to the value of the per-kse variable name. */ #define KCB_GET32(name) ({ \ __kcb_type(name) __result; \ \ u_int __i; \ __asm __volatile("movl %%gs:%1, %0" \ : "=r" (__i) \ : "m" (*(u_int *)(__kcb_offset(name)))); \ __result = (__kcb_type(name))__i; \ \ __result; \ }) /* * Sets the value of the per-kse variable name to value val. */ #define KCB_SET32(name, val) ({ \ __kcb_type(name) __val = (val); \ \ u_int __i; \ __i = (u_int)__val; \ __asm __volatile("movl %1,%%gs:%0" \ : "=m" (*(u_int *)(__kcb_offset(name))) \ : "r" (__i)); \ }) static __inline u_long __kcb_readandclear32(volatile u_long *addr) { u_long result; __asm __volatile ( " xorl %0, %0;" " xchgl %%gs:%1, %0;" "# __kcb_readandclear32" : "=&r" (result) : "m" (*addr)); return (result); } #define KCB_READANDCLEAR32(name) ({ \ __kcb_type(name) __result; \ \ __result = (__kcb_type(name)) \ __kcb_readandclear32((u_long *)__kcb_offset(name)); \ __result; \ }) #define _kcb_curkcb() KCB_GET32(kcb_self) #define _kcb_curtcb() KCB_GET32(kcb_curtcb) #define _kcb_curkse() ((struct kse *)KCB_GET32(kcb_kmbx.km_udata)) #define _kcb_get_tmbx() KCB_GET32(kcb_kmbx.km_curthread) #define _kcb_set_tmbx(value) KCB_SET32(kcb_kmbx.km_curthread, (void *)value) #define _kcb_readandclear_tmbx() KCB_READANDCLEAR32(kcb_kmbx.km_curthread) /* * The constructors. */ struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *tcb); struct kcb *_kcb_ctor(struct kse *); void _kcb_dtor(struct kcb *); /* Called from the KSE to set its private data. */ static __inline void _kcb_set(struct kcb *kcb) { i386_set_gsbase(kcb); } /* Get the current kcb. */ static __inline struct kcb * _kcb_get(void) { return (_kcb_curkcb()); } static __inline struct kse_thr_mailbox * _kcb_critical_enter(void) { struct kse_thr_mailbox *crit; crit = _kcb_readandclear_tmbx(); return (crit); } static __inline void _kcb_critical_leave(struct kse_thr_mailbox *crit) { _kcb_set_tmbx(crit); } static __inline int _kcb_in_critical(void) { return (_kcb_get_tmbx() == NULL); } static __inline void _tcb_set(struct kcb *kcb, struct tcb *tcb) { kcb->kcb_curtcb = tcb; } static __inline struct tcb * _tcb_get(void) { return (_kcb_curtcb()); } static __inline struct pthread * _get_curthread(void) { struct tcb *tcb; tcb = _kcb_curtcb(); if (tcb != NULL) return (tcb->tcb_thread); else return (NULL); } static __inline struct kse * _get_curkse(void) { return ((struct kse *)_kcb_curkse()); } void _i386_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack, size_t stacksz); static __inline int _thread_enter_uts(struct tcb *tcb, struct kcb *kcb) { int ret; ret = _thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext); if (ret == 0) { _i386_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, kcb->kcb_kmbx.km_stack.ss_sp, kcb->kcb_kmbx.km_stack.ss_size); /* We should not reach here. */ return (-1); } else if (ret < 0) return (-1); return (0); } static __inline int _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) { extern int _libkse_debug; if ((kcb == NULL) || (tcb == NULL)) return (-1); kcb->kcb_curtcb = tcb; if (_libkse_debug == 0) { tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; if (setmbox != 0) _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, (intptr_t)&tcb->tcb_tmbx, - (intptr_t *)&kcb->kcb_kmbx.km_curthread); + (intptr_t *)(void *)&kcb->kcb_kmbx.km_curthread); else _thr_setcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext, 0, NULL); } else { if (setmbox) kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); else kse_switchin(&tcb->tcb_tmbx, 0); } /* We should not reach here. */ return (-1); } #endif Index: head/lib/libkse/arch/ia64/include/atomic_ops.h =================================================================== --- head/lib/libkse/arch/ia64/include/atomic_ops.h (revision 174111) +++ head/lib/libkse/arch/ia64/include/atomic_ops.h (revision 174112) @@ -1,47 +1,47 @@ /* * Copyright (c) 2003 Marcel Moolenaar * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ */ #ifndef _ATOMIC_OPS_H_ #define _ATOMIC_OPS_H_ static inline void -atomic_swap_int(int *dst, int val, int *res) +atomic_swap_int(volatile int *dst, int val, int *res) { __asm("xchg4 %0=[%2],%1" : "=r"(*res) : "r"(val), "r"(dst)); } static inline void -atomic_swap_long(long *dst, long val, long *res) +atomic_swap_long(volatile long *dst, long val, long *res) { __asm("xchg8 %0=[%2],%1" : "=r"(*res) : "r"(val), "r"(dst)); } #define atomic_swap_ptr(d,v,r) \ - atomic_swap_long((long*)d, (long)v, (long*)r) + atomic_swap_long((volatile long *)d, (long)v, (long *)r) #endif /* _ATOMIC_OPS_H_ */ Index: head/lib/libkse/arch/powerpc/include/atomic_ops.h =================================================================== --- head/lib/libkse/arch/powerpc/include/atomic_ops.h (revision 174111) +++ head/lib/libkse/arch/powerpc/include/atomic_ops.h (revision 174112) @@ -1,62 +1,62 @@ /* * Copyright 2004 by Peter Grehan. 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ */ #ifndef _ATOMIC_OPS_H_ #define _ATOMIC_OPS_H_ /* * Atomic swap: * Atomic (tmp = *dst, *dst = val), then *res = tmp * * void atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res); */ static inline void -atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res) +atomic_swap32(volatile intptr_t *dst, intptr_t val, intptr_t *res) { int tmp; tmp = 0; /* should be a better way to quieten cc1... */ #ifdef __GNUC__ __asm __volatile( "1: lwarx %0, 0, %4\n" /* load with reservation */ " stwcx. %3, 0, %4\n" /* attempt to store val */ " bne- 1b\n" /* interrupted? retry */ " stw %0, %1\n" /* else, *dst -> *res */ : "=&r" (tmp), "=m" (*res), "+m" (*dst) : "r" (val), "r" (dst) : "cc", "memory"); #endif } #define atomic_swap_ptr(d, v, r) \ - atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r) + atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r) #define atomic_swap_int(d, v, r) \ - atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r) + atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r) #endif Index: head/lib/libkse/arch/powerpc/include/pthread_md.h =================================================================== --- head/lib/libkse/arch/powerpc/include/pthread_md.h (revision 174111) +++ head/lib/libkse/arch/powerpc/include/pthread_md.h (revision 174112) @@ -1,292 +1,292 @@ /* * Copyright 2004 by Peter Grehan. * Copyright 2006 Marcel Moolenaar * 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ */ /* * Machine-dependent thread prototypes/definitions for the thread kernel. */ #ifndef _PTHREAD_MD_H_ #define _PTHREAD_MD_H_ #include #include #include extern void _ppc32_enter_uts(struct kse_mailbox *, kse_func_t, void *, size_t); extern int _ppc32_setcontext(mcontext_t *, intptr_t, intptr_t *); extern int _ppc32_getcontext(mcontext_t *); #define KSE_STACKSIZE 16384 #define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_dtv) #define THR_GETCONTEXT(ucp) _ppc32_getcontext(&(ucp)->uc_mcontext) #define THR_SETCONTEXT(ucp) _ppc32_setcontext(&(ucp)->uc_mcontext, 0, NULL) #define PER_THREAD struct kcb; struct kse; struct pthread; struct tcb; /* * %r2 points to the following. */ struct ppc32_tp { void *tp_dtv; /* dynamic thread vector */ uint32_t _reserved_; double tp_tls[0]; /* static TLS */ }; struct tcb { struct kse_thr_mailbox tcb_tmbx; struct pthread *tcb_thread; struct kcb *tcb_curkcb; long tcb_isfake; long tcb_spare[3]; struct ppc32_tp tcb_tp; }; struct kcb { struct kse_mailbox kcb_kmbx; struct kse *kcb_kse; struct tcb *kcb_curtcb; struct tcb kcb_faketcb; }; /* * From the PowerPC32 TLS spec: * * "r2 is the thread pointer, and points 0x7000 past the end of the * thread control block." Or, 0x7008 past the start of the 8-byte tcb */ #define TP_OFFSET 0x7008 static __inline char * ppc_get_tp() { register char *r2 __asm__("%r2"); return (r2 - TP_OFFSET); } static __inline void ppc_set_tp(char *tp) { register char *r2 __asm__("%r2"); __asm __volatile("mr %0,%1" : "=r"(r2) : "r"(tp + TP_OFFSET)); } static __inline struct tcb * ppc_get_tcb() { return ((struct tcb *)(ppc_get_tp() - offsetof(struct tcb, tcb_tp))); } static __inline void ppc_set_tcb(struct tcb *tcb) { ppc_set_tp((char*)&tcb->tcb_tp); } /* * The kcb and tcb constructors. */ struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); /* Called from the KSE to set its private data. */ static __inline void _kcb_set(struct kcb *kcb) { /* There is no thread yet; use the fake tcb. */ ppc_set_tcb(&kcb->kcb_faketcb); } /* * Get the current kcb. * * This can only be called while in a critical region; don't * worry about having the kcb changed out from under us. */ static __inline struct kcb * _kcb_get(void) { return (ppc_get_tcb()->tcb_curkcb); } /* * Enter a critical region. * * Read and clear km_curthread in the kse mailbox. */ static __inline struct kse_thr_mailbox * _kcb_critical_enter(void) { struct kse_thr_mailbox *crit; struct tcb *tcb; uint32_t flags; tcb = ppc_get_tcb(); if (tcb->tcb_isfake != 0) { /* * We already are in a critical region since * there is no current thread. */ crit = NULL; } else { flags = tcb->tcb_tmbx.tm_flags; tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; crit = tcb->tcb_curkcb->kcb_kmbx.km_curthread; tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL; tcb->tcb_tmbx.tm_flags = flags; } return (crit); } static __inline void _kcb_critical_leave(struct kse_thr_mailbox *crit) { struct tcb *tcb; tcb = ppc_get_tcb(); /* No need to do anything if this is a fake tcb. */ if (tcb->tcb_isfake == 0) tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit; } static __inline int _kcb_in_critical(void) { struct tcb *tcb; uint32_t flags; int ret; tcb = ppc_get_tcb(); if (tcb->tcb_isfake != 0) { /* * We are in a critical region since there is no * current thread. */ ret = 1; } else { flags = tcb->tcb_tmbx.tm_flags; tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; ret = (tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL); tcb->tcb_tmbx.tm_flags = flags; } return (ret); } static __inline void _tcb_set(struct kcb *kcb, struct tcb *tcb) { if (tcb == NULL) tcb = &kcb->kcb_faketcb; kcb->kcb_curtcb = tcb; tcb->tcb_curkcb = kcb; ppc_set_tcb(tcb); } static __inline struct tcb * _tcb_get(void) { return (ppc_get_tcb()); } static __inline struct pthread * _get_curthread(void) { return (ppc_get_tcb()->tcb_thread); } /* * Get the current kse. * * Like _kcb_get(), this can only be called while in a critical region. */ static __inline struct kse * _get_curkse(void) { return (ppc_get_tcb()->tcb_curkcb->kcb_kse); } static __inline int _thread_enter_uts(struct tcb *tcb, struct kcb *kcb) { if (_ppc32_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) { /* Make the fake tcb the current thread. */ kcb->kcb_curtcb = &kcb->kcb_faketcb; ppc_set_tcb(&kcb->kcb_faketcb); _ppc32_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func, kcb->kcb_kmbx.km_stack.ss_sp, kcb->kcb_kmbx.km_stack.ss_size - 32); /* We should not reach here. */ return (-1); } return (0); } static __inline int _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) { mcontext_t *mc; extern int _libkse_debug; _tcb_set(kcb, tcb); mc = &tcb->tcb_tmbx.tm_context.uc_mcontext; /* * A full context needs a system call to restore, so use * kse_switchin. Otherwise, the partial context can be * restored with _ppc32_setcontext */ if (mc->mc_vers != _MC_VERSION_KSE && _libkse_debug != 0) { if (setmbox) kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); else kse_switchin(&tcb->tcb_tmbx, 0); } else { tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; if (setmbox) _ppc32_setcontext(mc, (intptr_t)&tcb->tcb_tmbx, - (intptr_t *)&kcb->kcb_kmbx.km_curthread); + (intptr_t *)(void *)&kcb->kcb_kmbx.km_curthread); else _ppc32_setcontext(mc, 0, NULL); } /* We should not reach here. */ return (-1); } #endif /* _PTHREAD_MD_H_ */ Index: head/lib/libkse/arch/sparc64/include/atomic_ops.h =================================================================== --- head/lib/libkse/arch/sparc64/include/atomic_ops.h (revision 174111) +++ head/lib/libkse/arch/sparc64/include/atomic_ops.h (revision 174112) @@ -1,75 +1,75 @@ /*- * Copyright (c) 2003 Jake Burkholder * 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. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ #ifndef _ATOMIC_OPS_H_ #define _ATOMIC_OPS_H_ #include /* * Atomic swap: * Atomic (tmp = *dst, *dst = val), then *res = tmp * * void atomic_swap_long(long *dst, long val, long *res); */ static __inline void -atomic_swap_long(long *dst, long val, long *res) +atomic_swap_long(volatile long *dst, long val, long *res) { long tmp; long r; tmp = *dst; for (;;) { r = atomic_cas_64(dst, tmp, val); if (r == tmp) break; tmp = r; } *res = tmp; } static __inline void -atomic_swap_int(int *dst, int val, int *res) +atomic_swap_int(volatile int *dst, int val, int *res) { int tmp; int r; tmp = *dst; for (;;) { r = atomic_cas_32(dst, tmp, val); if (r == tmp) break; tmp = r; } *res = tmp; } #define atomic_swap_ptr(dst, val, res) \ - atomic_swap_long((long *)dst, (long)val, (long *)res) + atomic_swap_long((volatile long *)dst, (long)val, (long *)res) #endif Index: head/lib/libkse/arch/sparc64/include/pthread_md.h =================================================================== --- head/lib/libkse/arch/sparc64/include/pthread_md.h (revision 174111) +++ head/lib/libkse/arch/sparc64/include/pthread_md.h (revision 174112) @@ -1,254 +1,254 @@ /*- * Copyright (c) 2003 Jake Burkholder . * Copyright (c) 2003 Marcel Moolenaar * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ */ /* * Machine-dependent thread prototypes/definitions for the thread kernel. */ #ifndef _PTHREAD_MD_H_ #define _PTHREAD_MD_H_ #include #include #include #define KSE_STACKSIZE 16384 #define DTV_OFFSET offsetof(struct tcb, tcb_tp.tp_tdv) int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *); int _thr_getcontext(mcontext_t *); #define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext) #define THR_SETCONTEXT(ucp) _thr_setcontext(&(ucp)->uc_mcontext, 0, NULL) #define PER_THREAD struct kcb; struct kse; struct pthread; struct tcb; struct tdv; /* We don't know what this is yet? */ /* * %g6 points to one of these. We define the static TLS as an array * of long double to enforce 16-byte alignment of the TLS memory. * * XXX - Both static and dynamic allocation of any of these structures * will result in a valid, well-aligned thread pointer??? */ struct sparc64_tp { struct tdv *tp_tdv; /* dynamic TLS */ uint64_t _reserved_; long double tp_tls[0]; /* static TLS */ }; struct tcb { struct pthread *tcb_thread; void *tcb_addr; /* allocated tcb address */ struct kcb *tcb_curkcb; uint64_t tcb_isfake; uint64_t tcb_spare[4]; struct kse_thr_mailbox tcb_tmbx; /* needs 64-byte alignment */ struct sparc64_tp tcb_tp; } __aligned(64); struct kcb { struct kse_mailbox kcb_kmbx; struct tcb kcb_faketcb; struct tcb *kcb_curtcb; struct kse *kcb_kse; }; register struct sparc64_tp *_tp __asm("%g6"); #define _tcb ((struct tcb*)((char*)(_tp) - offsetof(struct tcb, tcb_tp))) /* * The kcb and tcb constructors. */ struct tcb *_tcb_ctor(struct pthread *, int); void _tcb_dtor(struct tcb *); struct kcb *_kcb_ctor(struct kse *kse); void _kcb_dtor(struct kcb *); /* Called from the KSE to set its private data. */ static __inline void _kcb_set(struct kcb *kcb) { /* There is no thread yet; use the fake tcb. */ _tp = &kcb->kcb_faketcb.tcb_tp; } /* * Get the current kcb. * * This can only be called while in a critical region; don't * worry about having the kcb changed out from under us. */ static __inline struct kcb * _kcb_get(void) { return (_tcb->tcb_curkcb); } /* * Enter a critical region. * * Read and clear km_curthread in the kse mailbox. */ static __inline struct kse_thr_mailbox * _kcb_critical_enter(void) { struct kse_thr_mailbox *crit; uint32_t flags; if (_tcb->tcb_isfake != 0) { /* * We already are in a critical region since * there is no current thread. */ crit = NULL; } else { flags = _tcb->tcb_tmbx.tm_flags; _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; crit = _tcb->tcb_curkcb->kcb_kmbx.km_curthread; _tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL; _tcb->tcb_tmbx.tm_flags = flags; } return (crit); } static __inline void _kcb_critical_leave(struct kse_thr_mailbox *crit) { /* No need to do anything if this is a fake tcb. */ if (_tcb->tcb_isfake == 0) _tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit; } static __inline int _kcb_in_critical(void) { uint32_t flags; int ret; if (_tcb->tcb_isfake != 0) { /* * We are in a critical region since there is no * current thread. */ ret = 1; } else { flags = _tcb->tcb_tmbx.tm_flags; _tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL; ret = (_tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL); _tcb->tcb_tmbx.tm_flags = flags; } return (ret); } static __inline void _tcb_set(struct kcb *kcb, struct tcb *tcb) { if (tcb == NULL) tcb = &kcb->kcb_faketcb; kcb->kcb_curtcb = tcb; tcb->tcb_curkcb = kcb; _tp = &tcb->tcb_tp; } static __inline struct tcb * _tcb_get(void) { return (_tcb); } static __inline struct pthread * _get_curthread(void) { return (_tcb->tcb_thread); } /* * Get the current kse. * * Like _kcb_get(), this can only be called while in a critical region. */ static __inline struct kse * _get_curkse(void) { return (_tcb->tcb_curkcb->kcb_kse); } void _sparc64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack, size_t stacksz); static __inline int _thread_enter_uts(struct tcb *tcb, struct kcb *kcb) { if (_thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) { /* Make the fake tcb the current thread. */ kcb->kcb_curtcb = &kcb->kcb_faketcb; _tp = &kcb->kcb_faketcb.tcb_tp; _sparc64_enter_uts(kcb->kcb_kmbx.km_func, &kcb->kcb_kmbx, kcb->kcb_kmbx.km_stack.ss_sp, kcb->kcb_kmbx.km_stack.ss_size); /* We should not reach here. */ return (-1); } return (0); } static __inline int _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox) { extern int _libkse_debug; mcontext_t *mc; _tcb_set(kcb, tcb); mc = &tcb->tcb_tmbx.tm_context.uc_mcontext; if (_libkse_debug == 0) { tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp; if (setmbox) _thr_setcontext(mc, (intptr_t)&tcb->tcb_tmbx, - (intptr_t *)&kcb->kcb_kmbx.km_curthread); + (intptr_t *)(void *)&kcb->kcb_kmbx.km_curthread); else _thr_setcontext(mc, 0, NULL); } else { if (setmbox) kse_switchin(&tcb->tcb_tmbx, KSE_SWITCHIN_SETTMBX); else kse_switchin(&tcb->tcb_tmbx, 0); } /* We should not reach here. */ return (-1); } #endif /* _PTHREAD_MD_H_ */ Index: head/lib/libkse/sys/lock.c =================================================================== --- head/lib/libkse/sys/lock.c (revision 174111) +++ head/lib/libkse/sys/lock.c (revision 174112) @@ -1,352 +1,354 @@ /*- * Copyright (c) 2001, 2003 Daniel Eischen . * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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$ */ #include #include #include #include #include "atomic_ops.h" #include "lock.h" #ifdef _LOCK_DEBUG #define LCK_ASSERT(e) assert(e) #else #define LCK_ASSERT(e) #endif #define MAX_SPINS 500 void _lock_destroy(struct lock *lck) { if ((lck != NULL) && (lck->l_head != NULL)) { free(lck->l_head); lck->l_head = NULL; lck->l_tail = NULL; } } int _lock_init(struct lock *lck, enum lock_type ltype, lock_handler_t *waitfunc, lock_handler_t *wakeupfunc, void *(calloc_cb)(size_t, size_t)) { if (lck == NULL) return (-1); else if ((lck->l_head = calloc_cb(1, sizeof(struct lockreq))) == NULL) return (-1); else { lck->l_type = ltype; lck->l_wait = waitfunc; lck->l_wakeup = wakeupfunc; lck->l_head->lr_locked = 0; lck->l_head->lr_watcher = NULL; lck->l_head->lr_owner = NULL; lck->l_head->lr_active = 1; lck->l_tail = lck->l_head; } return (0); } int _lock_reinit(struct lock *lck, enum lock_type ltype, lock_handler_t *waitfunc, lock_handler_t *wakeupfunc) { if (lck == NULL) return (-1); else if (lck->l_head == NULL) return (_lock_init(lck, ltype, waitfunc, wakeupfunc, calloc)); else { lck->l_head->lr_locked = 0; lck->l_head->lr_watcher = NULL; lck->l_head->lr_owner = NULL; lck->l_head->lr_active = 1; lck->l_tail = lck->l_head; } return (0); } int _lockuser_init(struct lockuser *lu, void *priv) { if (lu == NULL) return (-1); else if ((lu->lu_myreq == NULL) && ((lu->lu_myreq = malloc(sizeof(struct lockreq))) == NULL)) return (-1); else { lu->lu_myreq->lr_locked = 1; lu->lu_myreq->lr_watcher = NULL; lu->lu_myreq->lr_owner = lu; lu->lu_myreq->lr_active = 0; lu->lu_watchreq = NULL; lu->lu_priority = 0; lu->lu_private = priv; lu->lu_private2 = NULL; } return (0); } int _lockuser_reinit(struct lockuser *lu, void *priv) { if (lu == NULL) return (-1); /* * All lockusers keep their watch request and drop their * own (lu_myreq) request. Their own request is either * some other lockuser's watch request or is the head of * the lock. */ lu->lu_myreq = lu->lu_watchreq; if (lu->lu_myreq == NULL) return (_lockuser_init(lu, priv)); else { lu->lu_myreq->lr_locked = 1; lu->lu_myreq->lr_watcher = NULL; lu->lu_myreq->lr_owner = lu; lu->lu_myreq->lr_active = 0; lu->lu_watchreq = NULL; lu->lu_priority = 0; lu->lu_private = priv; lu->lu_private2 = NULL; } return (0); } void _lockuser_destroy(struct lockuser *lu) { if ((lu != NULL) && (lu->lu_myreq != NULL)) free(lu->lu_myreq); } /* * Acquire a lock waiting (spin or sleep) for it to become available. */ void _lock_acquire(struct lock *lck, struct lockuser *lu, int prio) { int i; int lval; /** * XXX - We probably want to remove these checks to optimize * performance. It is also a bug if any one of the * checks fail, so it's probably better to just let it * SEGV and fix it. */ #if 0 if (lck == NULL || lu == NULL || lck->l_head == NULL) return; #endif if ((lck->l_type & LCK_PRIORITY) != 0) { LCK_ASSERT(lu->lu_myreq->lr_locked == 1); LCK_ASSERT(lu->lu_myreq->lr_watcher == NULL); LCK_ASSERT(lu->lu_myreq->lr_owner == lu); LCK_ASSERT(lu->lu_watchreq == NULL); lu->lu_priority = prio; } /* * Atomically swap the head of the lock request with * this request. */ - atomic_swap_ptr(&lck->l_head, lu->lu_myreq, &lu->lu_watchreq); + atomic_swap_ptr((void *)&lck->l_head, lu->lu_myreq, + (void *)&lu->lu_watchreq); if (lu->lu_watchreq->lr_locked != 0) { atomic_store_rel_ptr - ((volatile uintptr_t *)&lu->lu_watchreq->lr_watcher, + ((volatile uintptr_t *)(void *)&lu->lu_watchreq->lr_watcher, (uintptr_t)lu); if ((lck->l_wait == NULL) || ((lck->l_type & LCK_ADAPTIVE) == 0)) { while (lu->lu_watchreq->lr_locked != 0) ; /* spin, then yield? */ } else { /* * Spin for a bit before invoking the wait function. * * We should be a little smarter here. If we're * running on a single processor, then the lock * owner got preempted and spinning will accomplish * nothing but waste time. If we're running on * multiple processors, the owner could be running * on another CPU and we might acquire the lock if * we spin for a bit. * * The other thing to keep in mind is that threads * acquiring these locks are considered to be in * critical regions; they will not be preempted by * the _UTS_ until they release the lock. It is * therefore safe to assume that if a lock can't * be acquired, it is currently held by a thread * running in another KSE. */ for (i = 0; i < MAX_SPINS; i++) { if (lu->lu_watchreq->lr_locked == 0) return; if (lu->lu_watchreq->lr_active == 0) break; } - atomic_swap_int((int *)&lu->lu_watchreq->lr_locked, + atomic_swap_int(&lu->lu_watchreq->lr_locked, 2, &lval); if (lval == 0) lu->lu_watchreq->lr_locked = 0; else lck->l_wait(lck, lu); } } lu->lu_myreq->lr_active = 1; } /* * Release a lock. */ void _lock_release(struct lock *lck, struct lockuser *lu) { struct lockuser *lu_tmp, *lu_h; struct lockreq *myreq; int prio_h; int lval; /** * XXX - We probably want to remove these checks to optimize * performance. It is also a bug if any one of the * checks fail, so it's probably better to just let it * SEGV and fix it. */ #if 0 if ((lck == NULL) || (lu == NULL)) return; #endif if ((lck->l_type & LCK_PRIORITY) != 0) { prio_h = 0; lu_h = NULL; /* Update tail if our request is last. */ if (lu->lu_watchreq->lr_owner == NULL) { - atomic_store_rel_ptr((volatile uintptr_t *)&lck->l_tail, + atomic_store_rel_ptr((volatile uintptr_t *) + (void *)&lck->l_tail, (uintptr_t)lu->lu_myreq); - atomic_store_rel_ptr - ((volatile uintptr_t *)&lu->lu_myreq->lr_owner, + atomic_store_rel_ptr((volatile uintptr_t *) + (void *)&lu->lu_myreq->lr_owner, (uintptr_t)NULL); } else { /* Remove ourselves from the list. */ atomic_store_rel_ptr((volatile uintptr_t *) - &lu->lu_myreq->lr_owner, + (void *)&lu->lu_myreq->lr_owner, (uintptr_t)lu->lu_watchreq->lr_owner); atomic_store_rel_ptr((volatile uintptr_t *) - &lu->lu_watchreq->lr_owner->lu_myreq, + (void *)&lu->lu_watchreq->lr_owner->lu_myreq, (uintptr_t)lu->lu_myreq); } /* * The watch request now becomes our own because we've * traded away our previous request. Save our previous * request so that we can grant the lock. */ myreq = lu->lu_myreq; lu->lu_myreq = lu->lu_watchreq; lu->lu_watchreq = NULL; lu->lu_myreq->lr_locked = 1; lu->lu_myreq->lr_owner = lu; lu->lu_myreq->lr_watcher = NULL; /* * Traverse the list of lock requests in reverse order * looking for the user with the highest priority. */ for (lu_tmp = lck->l_tail->lr_watcher; lu_tmp != NULL; lu_tmp = lu_tmp->lu_myreq->lr_watcher) { if (lu_tmp->lu_priority > prio_h) { lu_h = lu_tmp; prio_h = lu_tmp->lu_priority; } } if (lu_h != NULL) { /* Give the lock to the highest priority user. */ if (lck->l_wakeup != NULL) { atomic_swap_int( - (int *)&lu_h->lu_watchreq->lr_locked, + &lu_h->lu_watchreq->lr_locked, 0, &lval); if (lval == 2) /* Notify the sleeper */ lck->l_wakeup(lck, lu_h->lu_myreq->lr_watcher); } else atomic_store_rel_int( &lu_h->lu_watchreq->lr_locked, 0); } else { if (lck->l_wakeup != NULL) { - atomic_swap_int((int *)&myreq->lr_locked, + atomic_swap_int(&myreq->lr_locked, 0, &lval); if (lval == 2) /* Notify the sleeper */ lck->l_wakeup(lck, myreq->lr_watcher); } else /* Give the lock to the previous request. */ atomic_store_rel_int(&myreq->lr_locked, 0); } } else { /* * The watch request now becomes our own because we've * traded away our previous request. Save our previous * request so that we can grant the lock. */ myreq = lu->lu_myreq; lu->lu_myreq = lu->lu_watchreq; lu->lu_watchreq = NULL; lu->lu_myreq->lr_locked = 1; if (lck->l_wakeup) { - atomic_swap_int((int *)&myreq->lr_locked, 0, &lval); + atomic_swap_int(&myreq->lr_locked, 0, &lval); if (lval == 2) /* Notify the sleeper */ lck->l_wakeup(lck, myreq->lr_watcher); } else /* Give the lock to the previous request. */ atomic_store_rel_int(&myreq->lr_locked, 0); } lu->lu_myreq->lr_active = 0; } void -_lock_grant(struct lock *lck /* unused */, struct lockuser *lu) +_lock_grant(struct lock *lck __unused /* unused */, struct lockuser *lu) { atomic_store_rel_int(&lu->lu_watchreq->lr_locked, 3); } void _lockuser_setactive(struct lockuser *lu, int active) { lu->lu_myreq->lr_active = active; } Index: head/lib/libkse/sys/thr_error.c =================================================================== --- head/lib/libkse/sys/thr_error.c (revision 174111) +++ head/lib/libkse/sys/thr_error.c (revision 174112) @@ -1,61 +1,62 @@ /* * Copyright (c) 1995 John Birrell . * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu * 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 * and Chris Provenzano. * 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. * * $FreeBSD$ */ +#include #include #include "libc_private.h" #include "thr_private.h" #undef errno extern int errno; LT10_COMPAT_DEFAULT(__error); int * __error(void) { struct pthread *curthread; if (__isthreaded == 0) return (&errno); else if (_kse_in_critical()) return &(_get_curkse()->k_error); else { curthread = _get_curthread(); if ((curthread == NULL) || (curthread == _thr_initial)) return (&errno); else return (&curthread->error); } } Index: head/lib/libkse/thread/thr_accept.c =================================================================== --- head/lib/libkse/thread/thr_accept.c (revision 174111) +++ head/lib/libkse/thread/thr_accept.c (revision 174112) @@ -1,52 +1,55 @@ /* * Copyright (c) 2003 Daniel Eischen . * 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. 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 THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "thr_private.h" LT10_COMPAT_PRIVATE(__accept); LT10_COMPAT_DEFAULT(accept); +int __accept(int s, struct sockaddr *addr, socklen_t *addrlen); + + __weak_reference(__accept, accept); int __accept(int s, struct sockaddr *addr, socklen_t *addrlen) { struct pthread *curthread; int ret; curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_accept(s, addr, addrlen); _thr_cancel_leave(curthread, ret == -1); return (ret); } Index: head/lib/libkse/thread/thr_aio_suspend.c =================================================================== --- head/lib/libkse/thread/thr_aio_suspend.c (revision 174111) +++ head/lib/libkse/thread/thr_aio_suspend.c (revision 174112) @@ -1,54 +1,59 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ #include #include #include "thr_private.h" LT10_COMPAT_PRIVATE(_aio_suspend); LT10_COMPAT_DEFAULT(aio_suspend); + +int +_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct + timespec *timeout); + __weak_reference(_aio_suspend, aio_suspend); int _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct timespec *timeout) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __sys_aio_suspend(iocbs, niocb, timeout); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_atfork.c =================================================================== --- head/lib/libkse/thread/thr_atfork.c (revision 174111) +++ head/lib/libkse/thread/thr_atfork.c (revision 174112) @@ -1,59 +1,61 @@ /* * Copyright (c) 2003 Daniel Eischen * 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. 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 THE AUTHOR 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$ */ +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_atfork); LT10_COMPAT_DEFAULT(pthread_atfork); __weak_reference(_pthread_atfork, pthread_atfork); int _pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { struct pthread_atfork *af; if (_thr_initial == NULL) _libpthread_init(NULL); if ((af = malloc(sizeof(struct pthread_atfork))) == NULL) return (ENOMEM); af->prepare = prepare; af->parent = parent; af->child = child; _pthread_mutex_lock(&_thr_atfork_mutex); TAILQ_INSERT_TAIL(&_thr_atfork_list, af, qe); _pthread_mutex_unlock(&_thr_atfork_mutex); return (0); } Index: head/lib/libkse/thread/thr_attr_destroy.c =================================================================== --- head/lib/libkse/thread/thr_attr_destroy.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_destroy.c (revision 174112) @@ -1,62 +1,64 @@ /* * Copyright (c) 1996 John Birrell . * 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. 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 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$ */ +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_destroy); LT10_COMPAT_DEFAULT(pthread_attr_destroy); __weak_reference(_pthread_attr_destroy, pthread_attr_destroy); int _pthread_attr_destroy(pthread_attr_t *attr) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL) /* Invalid argument: */ ret = EINVAL; else { /* Free the memory allocated to the attribute object: */ free(*attr); /* * Leave the attribute pointer NULL now that the memory * has been freed: */ *attr = NULL; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_get_np.c =================================================================== --- head/lib/libkse/thread/thr_attr_get_np.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_get_np.c (revision 174112) @@ -1,57 +1,60 @@ /* * Copyright (c) 2002,2003 Alexey Zelkin * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_get_np); LT10_COMPAT_DEFAULT(pthread_attr_get_np); __weak_reference(_pthread_attr_get_np, pthread_attr_get_np); int _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) { struct pthread *curthread; struct pthread_attr attr; int ret; if (pid == NULL || dst == NULL || *dst == NULL) return (EINVAL); curthread = _get_curthread(); if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) return (ret); attr = pid->attr; _thr_ref_delete(curthread, pid); memcpy(*dst, &attr, sizeof(struct pthread_attr)); return (0); } Index: head/lib/libkse/thread/thr_attr_getdetachstate.c =================================================================== --- head/lib/libkse/thread/thr_attr_getdetachstate.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getdetachstate.c (revision 174112) @@ -1,59 +1,61 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getdetachstate); LT10_COMPAT_DEFAULT(pthread_attr_getdetachstate); __weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); int _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || detachstate == NULL) ret = EINVAL; else { /* Check if the detached flag is set: */ if ((*attr)->flags & PTHREAD_DETACHED) /* Return detached: */ *detachstate = PTHREAD_CREATE_DETACHED; else /* Return joinable: */ *detachstate = PTHREAD_CREATE_JOINABLE; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_getguardsize.c =================================================================== --- head/lib/libkse/thread/thr_attr_getguardsize.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getguardsize.c (revision 174112) @@ -1,55 +1,57 @@ /* * Copyright (C) 2001 Jason Evans . * 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(s), this list of conditions and the following disclaimer * unmodified other than the allowable addition of one or more * copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getguardsize); LT10_COMPAT_DEFAULT(pthread_attr_getguardsize); __weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); int _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || guardsize == NULL) ret = EINVAL; else { /* Return the guard size: */ *guardsize = (*attr)->guardsize_attr; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_getinheritsched.c =================================================================== --- head/lib/libkse/thread/thr_attr_getinheritsched.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getinheritsched.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getinheritsched); LT10_COMPAT_DEFAULT(pthread_attr_getinheritsched); __weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); int _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else *sched_inherit = (*attr)->sched_inherit; return(ret); } Index: head/lib/libkse/thread/thr_attr_getschedparam.c =================================================================== --- head/lib/libkse/thread/thr_attr_getschedparam.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getschedparam.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getschedparam); LT10_COMPAT_DEFAULT(pthread_attr_getschedparam); __weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); int _pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) { int ret = 0; if ((attr == NULL) || (*attr == NULL) || (param == NULL)) ret = EINVAL; else param->sched_priority = (*attr)->prio; return(ret); } Index: head/lib/libkse/thread/thr_attr_getschedpolicy.c =================================================================== --- head/lib/libkse/thread/thr_attr_getschedpolicy.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getschedpolicy.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getschedpolicy); LT10_COMPAT_DEFAULT(pthread_attr_getschedpolicy); __weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); int _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) { int ret = 0; if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) ret = EINVAL; else *policy = (*attr)->sched_policy; return(ret); } Index: head/lib/libkse/thread/thr_attr_getscope.c =================================================================== --- head/lib/libkse/thread/thr_attr_getscope.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getscope.c (revision 174112) @@ -1,57 +1,60 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getscope); LT10_COMPAT_DEFAULT(pthread_attr_getscope); __weak_reference(_pthread_attr_getscope, pthread_attr_getscope); int _pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) { int ret = 0; if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) /* Return an invalid argument: */ ret = EINVAL; else *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; return(ret); } Index: head/lib/libkse/thread/thr_attr_getstack.c =================================================================== --- head/lib/libkse/thread/thr_attr_getstack.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getstack.c (revision 174112) @@ -1,62 +1,65 @@ /* * Copyright (c) 2003 Craig Rodrigues . * 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 Craig Rodrigues. * 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 CRAIG RODRIGUES 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getstack); LT10_COMPAT_DEFAULT(pthread_attr_getstack); __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); int _pthread_attr_getstack(const pthread_attr_t * __restrict attr, void ** __restrict stackaddr, size_t * __restrict stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL || stacksize == NULL ) ret = EINVAL; else { /* Return the stack address and size */ *stackaddr = (*attr)->stackaddr_attr; *stacksize = (*attr)->stacksize_attr; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_getstackaddr.c =================================================================== --- head/lib/libkse/thread/thr_attr_getstackaddr.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getstackaddr.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getstackaddr); LT10_COMPAT_DEFAULT(pthread_attr_getstackaddr); __weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); int _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL) ret = EINVAL; else { /* Return the stack address: */ *stackaddr = (*attr)->stackaddr_attr; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_getstacksize.c =================================================================== --- head/lib/libkse/thread/thr_attr_getstacksize.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_getstacksize.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_getstacksize); LT10_COMPAT_DEFAULT(pthread_attr_getstacksize); __weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); int _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stacksize == NULL) ret = EINVAL; else { /* Return the stack size: */ *stacksize = (*attr)->stacksize_attr; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_init.c =================================================================== --- head/lib/libkse/thread/thr_attr_init.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_init.c (revision 174112) @@ -1,64 +1,67 @@ /* * Copyright (c) 1996 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_init); LT10_COMPAT_DEFAULT(pthread_attr_init); __weak_reference(_pthread_attr_init, pthread_attr_init); int _pthread_attr_init(pthread_attr_t *attr) { int ret; pthread_attr_t pattr; /* Allocate memory for the attribute object: */ if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) /* Insufficient memory: */ ret = ENOMEM; else { /* Initialise the attribute object with the defaults: */ memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); pattr->guardsize_attr = _thr_guard_default; pattr->stacksize_attr = _thr_stack_default; /* Return a pointer to the attribute object: */ *attr = pattr; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_setcreatesuspend_np.c =================================================================== --- head/lib/libkse/thread/thr_attr_setcreatesuspend_np.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setcreatesuspend_np.c (revision 174112) @@ -1,52 +1,57 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setcreatesuspend_np); LT10_COMPAT_DEFAULT(pthread_attr_setcreatesuspend_np); + +int _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr); __weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); int _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) { int ret; if (attr == NULL || *attr == NULL) { ret = EINVAL; } else { (*attr)->suspend = THR_CREATE_SUSPENDED; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_setdetachstate.c =================================================================== --- head/lib/libkse/thread/thr_attr_setdetachstate.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setdetachstate.c (revision 174112) @@ -1,61 +1,64 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setdetachstate); LT10_COMPAT_DEFAULT(pthread_attr_setdetachstate); __weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); int _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || (detachstate != PTHREAD_CREATE_DETACHED && detachstate != PTHREAD_CREATE_JOINABLE)) ret = EINVAL; else { /* Check if detached state: */ if (detachstate == PTHREAD_CREATE_DETACHED) /* Set the detached flag: */ (*attr)->flags |= PTHREAD_DETACHED; else /* Reset the detached flag: */ (*attr)->flags &= ~PTHREAD_DETACHED; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_setguardsize.c =================================================================== --- head/lib/libkse/thread/thr_attr_setguardsize.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setguardsize.c (revision 174112) @@ -1,56 +1,58 @@ /* * Copyright (C) 2001 Jason Evans . * 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(s), this list of conditions and the following disclaimer * unmodified other than the allowable addition of one or more * copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setguardsize); LT10_COMPAT_DEFAULT(pthread_attr_setguardsize); __weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); int _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) { int ret; /* Check for invalid arguments. */ if (attr == NULL || *attr == NULL) ret = EINVAL; else { /* Save the stack size. */ (*attr)->guardsize_attr = guardsize; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_setinheritsched.c =================================================================== --- head/lib/libkse/thread/thr_attr_setinheritsched.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setinheritsched.c (revision 174112) @@ -1,57 +1,60 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setinheritsched); LT10_COMPAT_DEFAULT(pthread_attr_setinheritsched); __weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); int _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else if (sched_inherit != PTHREAD_INHERIT_SCHED && sched_inherit != PTHREAD_EXPLICIT_SCHED) ret = ENOTSUP; else (*attr)->sched_inherit = sched_inherit; return(ret); } Index: head/lib/libkse/thread/thr_attr_setschedparam.c =================================================================== --- head/lib/libkse/thread/thr_attr_setschedparam.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setschedparam.c (revision 174112) @@ -1,60 +1,63 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setschedparam); LT10_COMPAT_DEFAULT(pthread_attr_setschedparam); __weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); int _pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else if (param == NULL) { ret = ENOTSUP; } else if ((param->sched_priority < THR_MIN_PRIORITY) || (param->sched_priority > THR_MAX_PRIORITY)) { /* Return an unsupported value error. */ ret = ENOTSUP; } else (*attr)->prio = param->sched_priority; return(ret); } Index: head/lib/libkse/thread/thr_attr_setschedpolicy.c =================================================================== --- head/lib/libkse/thread/thr_attr_setschedpolicy.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setschedpolicy.c (revision 174112) @@ -1,56 +1,59 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setschedpolicy); LT10_COMPAT_DEFAULT(pthread_attr_setschedpolicy); __weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); int _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { ret = ENOTSUP; } else (*attr)->sched_policy = policy; return(ret); } Index: head/lib/libkse/thread/thr_attr_setscope.c =================================================================== --- head/lib/libkse/thread/thr_attr_setscope.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setscope.c (revision 174112) @@ -1,60 +1,63 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setscope); LT10_COMPAT_DEFAULT(pthread_attr_setscope); __weak_reference(_pthread_attr_setscope, pthread_attr_setscope); int _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) { /* Return an invalid argument: */ ret = EINVAL; } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && (contentionscope != PTHREAD_SCOPE_SYSTEM)) { ret = EINVAL; } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { (*attr)->flags |= contentionscope; } else { (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; } return (ret); } Index: head/lib/libkse/thread/thr_attr_setstack.c =================================================================== --- head/lib/libkse/thread/thr_attr_setstack.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setstack.c (revision 174112) @@ -1,61 +1,64 @@ /* * Copyright (c) 2003 Craig Rodrigues . * 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 Craig Rodrigues. * 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 CRAIG RODRIGUES 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setstack); LT10_COMPAT_DEFAULT(pthread_attr_setstack); __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); int _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL || stacksize < PTHREAD_STACK_MIN ) ret = EINVAL; else { /* Save the stack address and stack size */ (*attr)->stackaddr_attr = stackaddr; (*attr)->stacksize_attr = stacksize; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_setstackaddr.c =================================================================== --- head/lib/libkse/thread/thr_attr_setstackaddr.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setstackaddr.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setstackaddr); LT10_COMPAT_DEFAULT(pthread_attr_setstackaddr); __weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); int _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL) ret = EINVAL; else { /* Save the stack address: */ (*attr)->stackaddr_attr = stackaddr; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_attr_setstacksize.c =================================================================== --- head/lib/libkse/thread/thr_attr_setstacksize.c (revision 174111) +++ head/lib/libkse/thread/thr_attr_setstacksize.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (c) 1996 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_attr_setstacksize); LT10_COMPAT_DEFAULT(pthread_attr_setstacksize); __weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); int _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) ret = EINVAL; else { /* Save the stack size: */ (*attr)->stacksize_attr = stacksize; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_barrier.c =================================================================== --- head/lib/libkse/thread/thr_barrier.c (revision 174111) +++ head/lib/libkse/thread/thr_barrier.c (revision 174112) @@ -1,129 +1,129 @@ /*- * Copyright (c) 2003 David Xu * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ +#include "namespace.h" #include #include -#include "namespace.h" #include #include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_barrier_init); LT10_COMPAT_DEFAULT(pthread_barrier_init); LT10_COMPAT_PRIVATE(_pthread_barrier_wait); LT10_COMPAT_DEFAULT(pthread_barrier_wait); LT10_COMPAT_PRIVATE(_pthread_barrier_destroy); LT10_COMPAT_DEFAULT(pthread_barrier_destroy); __weak_reference(_pthread_barrier_init, pthread_barrier_init); __weak_reference(_pthread_barrier_wait, pthread_barrier_wait); __weak_reference(_pthread_barrier_destroy, pthread_barrier_destroy); int _pthread_barrier_destroy(pthread_barrier_t *barrier) { pthread_barrier_t bar; int ret, ret2; if (barrier == NULL || *barrier == NULL) return (EINVAL); bar = *barrier; if (bar->b_waiters > 0) return (EBUSY); *barrier = NULL; ret = _pthread_mutex_destroy(&bar->b_lock); ret2 = _pthread_cond_destroy(&bar->b_cond); free(bar); return (ret ? ret : ret2); } int _pthread_barrier_init(pthread_barrier_t *barrier, - const pthread_barrierattr_t *attr, unsigned count) + const pthread_barrierattr_t *attr __unused, unsigned count) { pthread_barrier_t bar; int ret; if (barrier == NULL || count <= 0) return (EINVAL); bar = malloc(sizeof(struct pthread_barrier)); if (bar == NULL) return (ENOMEM); if ((ret = _pthread_mutex_init(&bar->b_lock, NULL)) != 0) { free(bar); return (ret); } if ((ret = _pthread_cond_init(&bar->b_cond, NULL)) != 0) { _pthread_mutex_destroy(&bar->b_lock); free(bar); return (ret); } bar->b_waiters = 0; bar->b_count = count; bar->b_generation = 0; *barrier = bar; return (0); } int _pthread_barrier_wait(pthread_barrier_t *barrier) { int ret, gen; pthread_barrier_t bar; if (barrier == NULL || *barrier == NULL) return (EINVAL); bar = *barrier; if ((ret = _pthread_mutex_lock(&bar->b_lock)) != 0) return (ret); if (++bar->b_waiters == bar->b_count) { /* Current thread is lastest thread */ bar->b_generation++; bar->b_waiters = 0; ret = _pthread_cond_broadcast(&bar->b_cond); if (ret == 0) ret = PTHREAD_BARRIER_SERIAL_THREAD; } else { gen = bar->b_generation; do { ret = _pthread_cond_wait( &bar->b_cond, &bar->b_lock); /* test generation to avoid bogus wakeup */ } while (ret == 0 && gen == bar->b_generation); } _pthread_mutex_unlock(&bar->b_lock); return (ret); } Index: head/lib/libkse/thread/thr_barrierattr.c =================================================================== --- head/lib/libkse/thread/thr_barrierattr.c (revision 174111) +++ head/lib/libkse/thread/thr_barrierattr.c (revision 174112) @@ -1,102 +1,104 @@ /* * Copyright (c) 2003 David Xu . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_barrierattr_destroy); LT10_COMPAT_DEFAULT(pthread_barrierattr_destroy); LT10_COMPAT_PRIVATE(_pthread_barrierattr_init); LT10_COMPAT_DEFAULT(pthread_barrierattr_init); LT10_COMPAT_PRIVATE(_pthread_barrierattr_setpshared); LT10_COMPAT_DEFAULT(pthread_barrierattr_setpshared); LT10_COMPAT_PRIVATE(_pthread_barrierattr_getpshared); LT10_COMPAT_DEFAULT(pthread_barrierattr_getpshared); __weak_reference(_pthread_barrierattr_destroy, pthread_barrierattr_destroy); __weak_reference(_pthread_barrierattr_init, pthread_barrierattr_init); __weak_reference(_pthread_barrierattr_setpshared, pthread_barrierattr_setpshared); __weak_reference(_pthread_barrierattr_getpshared, pthread_barrierattr_getpshared); int _pthread_barrierattr_destroy(pthread_barrierattr_t *attr) { if (attr == NULL || *attr == NULL) return (EINVAL); free(*attr); return (0); } int _pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, int *pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); *pshared = (*attr)->pshared; return (0); } int _pthread_barrierattr_init(pthread_barrierattr_t *attr) { if (attr == NULL) return (EINVAL); if ((*attr = malloc(sizeof(struct pthread_barrierattr))) == NULL) return (ENOMEM); (*attr)->pshared = PTHREAD_PROCESS_PRIVATE; return (0); } int _pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); /* Only PTHREAD_PROCESS_PRIVATE is supported. */ if (pshared != PTHREAD_PROCESS_PRIVATE) return (EINVAL); (*attr)->pshared = pshared; return (0); } Index: head/lib/libkse/thread/thr_cancel.c =================================================================== --- head/lib/libkse/thread/thr_cancel.c (revision 174111) +++ head/lib/libkse/thread/thr_cancel.c (revision 174112) @@ -1,311 +1,313 @@ /* * David Leonard , 1999. Public domain. * $FreeBSD$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_cancel); LT10_COMPAT_DEFAULT(pthread_cancel); LT10_COMPAT_PRIVATE(_pthread_setcancelstate); LT10_COMPAT_DEFAULT(pthread_setcancelstate); LT10_COMPAT_PRIVATE(_pthread_setcanceltype); LT10_COMPAT_DEFAULT(pthread_setcanceltype); LT10_COMPAT_PRIVATE(_pthread_testcancel); LT10_COMPAT_DEFAULT(pthread_testcancel); __weak_reference(_pthread_cancel, pthread_cancel); __weak_reference(_pthread_setcancelstate, pthread_setcancelstate); __weak_reference(_pthread_setcanceltype, pthread_setcanceltype); __weak_reference(_pthread_testcancel, pthread_testcancel); static inline int checkcancel(struct pthread *curthread) { if ((curthread->cancelflags & THR_CANCELLING) != 0) { /* * It is possible for this thread to be swapped out * while performing cancellation; do not allow it * to be cancelled again. */ if ((curthread->flags & THR_FLAGS_EXITING) != 0) { /* * This may happen once, but after this, it * shouldn't happen again. */ curthread->cancelflags &= ~THR_CANCELLING; return (0); } if ((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) { curthread->cancelflags &= ~THR_CANCELLING; return (1); } } return (0); } static inline void testcancel(struct pthread *curthread) { if (checkcancel(curthread) != 0) { /* Unlock before exiting: */ THR_THREAD_UNLOCK(curthread, curthread); _thr_exit_cleanup(); - pthread_exit(PTHREAD_CANCELED); + _pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } } int _pthread_cancel(pthread_t pthread) { struct pthread *curthread = _get_curthread(); struct pthread *joinee = NULL; struct kse_mailbox *kmbx = NULL; int ret; if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0)) == 0) { /* * Take the thread's lock while we change the cancel flags. */ THR_THREAD_LOCK(curthread, pthread); THR_SCHED_LOCK(curthread, pthread); if (pthread->flags & THR_FLAGS_EXITING) { THR_SCHED_UNLOCK(curthread, pthread); THR_THREAD_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); return (ESRCH); } if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) || (((pthread->cancelflags & THR_AT_CANCEL_POINT) == 0) && ((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0))) /* Just mark it for cancellation: */ pthread->cancelflags |= THR_CANCELLING; else { /* * Check if we need to kick it back into the * run queue: */ switch (pthread->state) { case PS_RUNNING: /* No need to resume: */ pthread->cancelflags |= THR_CANCELLING; break; case PS_LOCKWAIT: /* * These can't be removed from the queue. * Just mark it as cancelling and tell it * to yield once it leaves the critical * region. */ pthread->cancelflags |= THR_CANCELLING; pthread->critical_yield = 1; break; case PS_SLEEP_WAIT: case PS_SIGSUSPEND: case PS_SIGWAIT: /* Interrupt and resume: */ pthread->interrupted = 1; pthread->cancelflags |= THR_CANCELLING; kmbx = _thr_setrunnable_unlocked(pthread); break; case PS_JOIN: /* Disconnect the thread from the joinee: */ joinee = pthread->join_status.thread; pthread->join_status.thread = NULL; pthread->cancelflags |= THR_CANCELLING; kmbx = _thr_setrunnable_unlocked(pthread); if ((joinee != NULL) && (pthread->kseg == joinee->kseg)) { /* Remove the joiner from the joinee. */ joinee->joiner = NULL; joinee = NULL; } break; case PS_SUSPENDED: case PS_MUTEX_WAIT: case PS_COND_WAIT: /* * Threads in these states may be in queues. * In order to preserve queue integrity, the * cancelled thread must remove itself from the * queue. Mark the thread as interrupted and * needing cancellation, and set the state to * running. When the thread resumes, it will * remove itself from the queue and call the * cancellation completion routine. */ pthread->interrupted = 1; pthread->cancelflags |= THR_CANCEL_NEEDED; kmbx = _thr_setrunnable_unlocked(pthread); pthread->continuation = _thr_finish_cancellation; break; case PS_DEAD: case PS_DEADLOCK: case PS_STATE_MAX: /* Ignore - only here to silence -Wall: */ break; } if ((pthread->cancelflags & THR_AT_CANCEL_POINT) && (pthread->blocked != 0 || pthread->attr.flags & PTHREAD_SCOPE_SYSTEM)) kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_INTERRUPT, 0); } /* * Release the thread's lock and remove the * reference: */ THR_SCHED_UNLOCK(curthread, pthread); THR_THREAD_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); if (kmbx != NULL) kse_wakeup(kmbx); if ((joinee != NULL) && (_thr_ref_add(curthread, joinee, /* include dead */1) == 0)) { /* Remove the joiner from the joinee. */ THR_SCHED_LOCK(curthread, joinee); joinee->joiner = NULL; THR_SCHED_UNLOCK(curthread, joinee); _thr_ref_delete(curthread, joinee); } } return (ret); } int _pthread_setcancelstate(int state, int *oldstate) { struct pthread *curthread = _get_curthread(); int ostate; int ret; int need_exit = 0; /* Take the thread's lock while fiddling with the state: */ THR_THREAD_LOCK(curthread, curthread); ostate = curthread->cancelflags & PTHREAD_CANCEL_DISABLE; switch (state) { case PTHREAD_CANCEL_ENABLE: curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE; if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0) need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DISABLE: curthread->cancelflags |= PTHREAD_CANCEL_DISABLE; ret = 0; break; default: ret = EINVAL; } THR_THREAD_UNLOCK(curthread, curthread); if (need_exit != 0) { _thr_exit_cleanup(); - pthread_exit(PTHREAD_CANCELED); + _pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } if (ret == 0 && oldstate != NULL) *oldstate = ostate; return (ret); } int _pthread_setcanceltype(int type, int *oldtype) { struct pthread *curthread = _get_curthread(); int otype; int ret; int need_exit = 0; /* Take the thread's lock while fiddling with the state: */ THR_THREAD_LOCK(curthread, curthread); otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS; switch (type) { case PTHREAD_CANCEL_ASYNCHRONOUS: curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS; need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DEFERRED: curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS; ret = 0; break; default: ret = EINVAL; } THR_THREAD_UNLOCK(curthread, curthread); if (need_exit != 0) { _thr_exit_cleanup(); - pthread_exit(PTHREAD_CANCELED); + _pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } if (ret == 0 && oldtype != NULL) *oldtype = otype; return (ret); } void _pthread_testcancel(void) { struct pthread *curthread = _get_curthread(); THR_THREAD_LOCK(curthread, curthread); testcancel(curthread); THR_THREAD_UNLOCK(curthread, curthread); } void _thr_cancel_enter(struct pthread *thread) { /* Look for a cancellation before we block: */ THR_THREAD_LOCK(thread, thread); testcancel(thread); thread->cancelflags |= THR_AT_CANCEL_POINT; THR_THREAD_UNLOCK(thread, thread); } void _thr_cancel_leave(struct pthread *thread, int check) { THR_THREAD_LOCK(thread, thread); thread->cancelflags &= ~THR_AT_CANCEL_POINT; /* Look for a cancellation after we unblock: */ if (check) testcancel(thread); THR_THREAD_UNLOCK(thread, thread); } void -_thr_finish_cancellation(void *arg) +_thr_finish_cancellation(void *arg __unused) { struct pthread *curthread = _get_curthread(); curthread->continuation = NULL; curthread->interrupted = 0; THR_THREAD_LOCK(curthread, curthread); if ((curthread->cancelflags & THR_CANCEL_NEEDED) != 0) { curthread->cancelflags &= ~THR_CANCEL_NEEDED; THR_THREAD_UNLOCK(curthread, curthread); _thr_exit_cleanup(); - pthread_exit(PTHREAD_CANCELED); + _pthread_exit(PTHREAD_CANCELED); } THR_THREAD_UNLOCK(curthread, curthread); } Index: head/lib/libkse/thread/thr_clean.c =================================================================== --- head/lib/libkse/thread/thr_clean.c (revision 174111) +++ head/lib/libkse/thread/thr_clean.c (revision 174112) @@ -1,76 +1,79 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_cleanup_push); LT10_COMPAT_DEFAULT(pthread_cleanup_push); LT10_COMPAT_PRIVATE(_pthread_cleanup_pop); LT10_COMPAT_DEFAULT(pthread_cleanup_pop); __weak_reference(_pthread_cleanup_push, pthread_cleanup_push); __weak_reference(_pthread_cleanup_pop, pthread_cleanup_pop); void _pthread_cleanup_push(void (*routine) (void *), void *routine_arg) { struct pthread *curthread = _get_curthread(); struct pthread_cleanup *new; if ((new = (struct pthread_cleanup *) malloc(sizeof(struct pthread_cleanup))) != NULL) { new->routine = routine; new->routine_arg = routine_arg; new->onstack = 0; new->next = curthread->cleanup; curthread->cleanup = new; } } void _pthread_cleanup_pop(int execute) { struct pthread *curthread = _get_curthread(); struct pthread_cleanup *old; if ((old = curthread->cleanup) != NULL) { curthread->cleanup = old->next; if (execute) { old->routine(old->routine_arg); } if (old->onstack == 0) free(old); } } Index: head/lib/libkse/thread/thr_close.c =================================================================== --- head/lib/libkse/thread/thr_close.c (revision 174111) +++ head/lib/libkse/thread/thr_close.c (revision 174112) @@ -1,55 +1,60 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__close); LT10_COMPAT_DEFAULT(close); + +int __close(int fd); __weak_reference(__close, close); int __close(int fd) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __sys_close(fd); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_concurrency.c =================================================================== --- head/lib/libkse/thread/thr_concurrency.c (revision 174111) +++ head/lib/libkse/thread/thr_concurrency.c (revision 174112) @@ -1,177 +1,180 @@ /* * Copyright (c) 2003 Daniel M. Eischen * Copyright (c) 2003 Sergey Osokin . * 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. 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 THE AUTHORS 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_getconcurrency); LT10_COMPAT_DEFAULT(pthread_getconcurrency); LT10_COMPAT_PRIVATE(_pthread_setconcurrency); LT10_COMPAT_DEFAULT(pthread_setconcurrency); /*#define DEBUG_CONCURRENCY */ #ifdef DEBUG_CONCURRENCY #define DBG_MSG stdout_debug #else #define DBG_MSG(x...) #endif static int level = 0; __weak_reference(_pthread_getconcurrency, pthread_getconcurrency); __weak_reference(_pthread_setconcurrency, pthread_setconcurrency); int _pthread_getconcurrency(void) { return (level); } int _pthread_setconcurrency(int new_level) { int ret; if (new_level < 0) ret = EINVAL; else if (new_level == level) ret = 0; else if (new_level == 0) { level = 0; ret = 0; } else if ((_kse_isthreaded() == 0) && (_kse_setthreaded(1) != 0)) { DBG_MSG("Can't enable threading.\n"); ret = EAGAIN; } else { ret = _thr_setconcurrency(new_level); if (ret == 0) level = new_level; } return (ret); } int _thr_setconcurrency(int new_level) { struct pthread *curthread; struct kse *newkse, *kse; kse_critical_t crit; int kse_count; int i; int ret; /* * Turn on threaded mode, if failed, it is unnecessary to * do further work. */ if (_kse_isthreaded() == 0 && _kse_setthreaded(1)) return (EAGAIN); ret = 0; curthread = _get_curthread(); /* Race condition, but so what. */ kse_count = _kse_initial->k_kseg->kg_ksecount; if (new_level > kse_count) { for (i = kse_count; i < new_level; i++) { newkse = _kse_alloc(curthread, 0); if (newkse == NULL) { DBG_MSG("Can't alloc new KSE.\n"); ret = EAGAIN; break; } newkse->k_kseg = _kse_initial->k_kseg; newkse->k_schedq = _kse_initial->k_schedq; newkse->k_curthread = NULL; crit = _kse_critical_enter(); KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg); TAILQ_INSERT_TAIL(&newkse->k_kseg->kg_kseq, newkse, k_kgqe); newkse->k_kseg->kg_ksecount++; newkse->k_flags |= KF_STARTED; KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg); if (kse_create(&newkse->k_kcb->kcb_kmbx, 0) != 0) { KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg); TAILQ_REMOVE(&newkse->k_kseg->kg_kseq, newkse, k_kgqe); newkse->k_kseg->kg_ksecount--; KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg); _kse_critical_leave(crit); _kse_free(curthread, newkse); DBG_MSG("kse_create syscall failed.\n"); ret = EAGAIN; break; } else { _kse_critical_leave(crit); } } } else if (new_level < kse_count) { kse_count = 0; crit = _kse_critical_enter(); KSE_SCHED_LOCK(curthread->kse, _kse_initial->k_kseg); /* Count the number of active KSEs */ TAILQ_FOREACH(kse, &_kse_initial->k_kseg->kg_kseq, k_kgqe) { if ((kse->k_flags & KF_TERMINATED) == 0) kse_count++; } /* Reduce the number of active KSEs appropriately. */ kse = TAILQ_FIRST(&_kse_initial->k_kseg->kg_kseq); while ((kse != NULL) && (kse_count > new_level)) { if ((kse != _kse_initial) && ((kse->k_flags & KF_TERMINATED) == 0)) { kse->k_flags |= KF_TERMINATED; kse_count--; /* Wakup the KSE in case it is idle. */ kse_wakeup(&kse->k_kcb->kcb_kmbx); } kse = TAILQ_NEXT(kse, k_kgqe); } KSE_SCHED_UNLOCK(curthread->kse, _kse_initial->k_kseg); _kse_critical_leave(crit); } return (ret); } int _thr_setmaxconcurrency(void) { int vcpu; size_t len; int ret; len = sizeof(vcpu); ret = sysctlbyname("kern.threads.virtual_cpu", &vcpu, &len, NULL, 0); if (ret == 0 && vcpu > 0) ret = _thr_setconcurrency(vcpu); return (ret); } Index: head/lib/libkse/thread/thr_cond.c =================================================================== --- head/lib/libkse/thread/thr_cond.c (revision 174111) +++ head/lib/libkse/thread/thr_cond.c (revision 174112) @@ -1,844 +1,851 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__pthread_cond_wait); LT10_COMPAT_PRIVATE(_pthread_cond_wait); LT10_COMPAT_DEFAULT(pthread_cond_wait); LT10_COMPAT_PRIVATE(__pthread_cond_timedwait); LT10_COMPAT_PRIVATE(_pthread_cond_timedwait); LT10_COMPAT_DEFAULT(pthread_cond_timedwait); LT10_COMPAT_PRIVATE(_pthread_cond_init); LT10_COMPAT_DEFAULT(pthread_cond_init); LT10_COMPAT_PRIVATE(_pthread_cond_destroy); LT10_COMPAT_DEFAULT(pthread_cond_destroy); LT10_COMPAT_PRIVATE(_pthread_cond_signal); LT10_COMPAT_DEFAULT(pthread_cond_signal); LT10_COMPAT_PRIVATE(_pthread_cond_broadcast); LT10_COMPAT_DEFAULT(pthread_cond_broadcast); #define THR_IN_CONDQ(thr) (((thr)->sflags & THR_FLAGS_IN_SYNCQ) != 0) #define THR_CONDQ_SET(thr) (thr)->sflags |= THR_FLAGS_IN_SYNCQ #define THR_CONDQ_CLEAR(thr) (thr)->sflags &= ~THR_FLAGS_IN_SYNCQ /* * Prototypes */ static inline struct pthread *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); static void cond_wait_backout(void *); static inline void check_continuation(struct pthread *, struct pthread_cond *, pthread_mutex_t *); +int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime); + /* * Double underscore versions are cancellation points. Single underscore * versions are not and are provided for libc internal usage (which * shouldn't introduce cancellation points). */ __weak_reference(__pthread_cond_wait, pthread_cond_wait); __weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait); __weak_reference(_pthread_cond_init, pthread_cond_init); __weak_reference(_pthread_cond_destroy, pthread_cond_destroy); __weak_reference(_pthread_cond_signal, pthread_cond_signal); __weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast); int _pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) { enum pthread_cond_type type; pthread_cond_t pcond; int flags; int rval = 0; if (cond == NULL) rval = EINVAL; else { /* * Check if a pointer to a condition variable attribute * structure was passed by the caller: */ if (cond_attr != NULL && *cond_attr != NULL) { /* Default to a fast condition variable: */ type = (*cond_attr)->c_type; flags = (*cond_attr)->c_flags; } else { /* Default to a fast condition variable: */ type = COND_TYPE_FAST; flags = 0; } /* Process according to condition variable type: */ switch (type) { /* Fast condition variable: */ case COND_TYPE_FAST: /* Nothing to do here. */ break; /* Trap invalid condition variable types: */ default: /* Return an invalid argument error: */ rval = EINVAL; break; } /* Check for no errors: */ if (rval == 0) { if ((pcond = (pthread_cond_t) malloc(sizeof(struct pthread_cond))) == NULL) { rval = ENOMEM; } else if (_lock_init(&pcond->c_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) { free(pcond); rval = ENOMEM; } else { /* * Initialise the condition variable * structure: */ TAILQ_INIT(&pcond->c_queue); pcond->c_flags = COND_FLAGS_INITED; pcond->c_type = type; pcond->c_mutex = NULL; pcond->c_seqno = 0; *cond = pcond; } } } /* Return the completion status: */ return (rval); } int _pthread_cond_destroy(pthread_cond_t *cond) { struct pthread_cond *cv; struct pthread *curthread = _get_curthread(); int rval = 0; if (cond == NULL || *cond == NULL) rval = EINVAL; else { /* Lock the condition variable structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); /* * NULL the caller's pointer now that the condition * variable has been destroyed: */ cv = *cond; *cond = NULL; /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &cv->c_lock); /* Free the cond lock structure: */ _lock_destroy(&cv->c_lock); /* * Free the memory allocated for the condition * variable structure: */ free(cv); } /* Return the completion status: */ return (rval); } int _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { struct pthread *curthread = _get_curthread(); int rval = 0; int done = 0; int mutex_locked = 1; int seqno; if (cond == NULL) return (EINVAL); /* * If the condition variable is statically initialized, * perform the dynamic initialization: */ if (*cond == NULL && - (rval = pthread_cond_init(cond, NULL)) != 0) + (rval = _pthread_cond_init(cond, NULL)) != 0) return (rval); if (!_kse_isthreaded()) _kse_setthreaded(1); /* * Enter a loop waiting for a condition signal or broadcast * to wake up this thread. A loop is needed in case the waiting * thread is interrupted by a signal to execute a signal handler. * It is not (currently) possible to remain in the waiting queue * while running a handler. Instead, the thread is interrupted * and backed out of the waiting queue prior to executing the * signal handler. */ /* Lock the condition variable structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); seqno = (*cond)->c_seqno; do { /* * If the condvar was statically allocated, properly * initialize the tail queue. */ if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { TAILQ_INIT(&(*cond)->c_queue); (*cond)->c_flags |= COND_FLAGS_INITED; } /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ case COND_TYPE_FAST: if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && ((*cond)->c_mutex != *mutex))) { /* Return invalid argument error: */ rval = EINVAL; } else { /* Reset the timeout and interrupted flags: */ curthread->timeout = 0; curthread->interrupted = 0; /* * Queue the running thread for the condition * variable: */ cond_queue_enq(*cond, curthread); /* Wait forever: */ curthread->wakeup_time.tv_sec = -1; /* Unlock the mutex: */ if (mutex_locked && ((rval = _mutex_cv_unlock(mutex)) != 0)) { /* * Cannot unlock the mutex, so remove * the running thread from the condition * variable queue: */ cond_queue_remove(*cond, curthread); } else { /* Remember the mutex: */ (*cond)->c_mutex = *mutex; /* * Don't unlock the mutex the next * time through the loop (if the * thread has to be requeued after * handling a signal). */ mutex_locked = 0; /* * This thread is active and is in a * critical region (holding the cv * lock); we should be able to safely * set the state. */ THR_SCHED_LOCK(curthread, curthread); THR_SET_STATE(curthread, PS_COND_WAIT); /* Remember the CV: */ curthread->data.cond = *cond; curthread->sigbackout = cond_wait_backout; THR_SCHED_UNLOCK(curthread, curthread); /* Unlock the CV structure: */ THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); /* Schedule the next thread: */ _thr_sched_switch(curthread); /* * XXX - This really isn't a good check * since there can be more than one * thread waiting on the CV. Signals * sent to threads waiting on mutexes * or CVs should really be deferred * until the threads are no longer * waiting, but POSIX says that signals * should be sent "as soon as possible". */ done = (seqno != (*cond)->c_seqno); if (done && !THR_IN_CONDQ(curthread)) { /* * The thread is dequeued, so * it is safe to clear these. */ curthread->data.cond = NULL; curthread->sigbackout = NULL; check_continuation(curthread, NULL, mutex); return (_mutex_cv_lock(mutex)); } /* Relock the CV structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); /* * Clear these after taking the lock to * prevent a race condition where a * signal can arrive before dequeueing * the thread. */ curthread->data.cond = NULL; curthread->sigbackout = NULL; done = (seqno != (*cond)->c_seqno); if (THR_IN_CONDQ(curthread)) { cond_queue_remove(*cond, curthread); /* Check for no more waiters: */ if (TAILQ_EMPTY(&(*cond)->c_queue)) (*cond)->c_mutex = NULL; } } } break; /* Trap invalid condition variable types: */ default: /* Return an invalid argument error: */ rval = EINVAL; break; } check_continuation(curthread, *cond, mutex_locked ? NULL : mutex); } while ((done == 0) && (rval == 0)); /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); if (mutex_locked == 0) _mutex_cv_lock(mutex); /* Return the completion status: */ return (rval); } __strong_reference(_pthread_cond_wait, _thr_cond_wait); int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = _pthread_cond_wait(cond, mutex); _thr_cancel_leave(curthread, 1); return (ret); } int _pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec * abstime) { struct pthread *curthread = _get_curthread(); int rval = 0; int done = 0; int mutex_locked = 1; int seqno; THR_ASSERT(curthread->locklevel == 0, "cv_timedwait: locklevel is not zero!"); if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return (EINVAL); /* * If the condition variable is statically initialized, perform dynamic * initialization. */ - if (*cond == NULL && (rval = pthread_cond_init(cond, NULL)) != 0) + if (*cond == NULL && (rval = _pthread_cond_init(cond, NULL)) != 0) return (rval); if (!_kse_isthreaded()) _kse_setthreaded(1); /* * Enter a loop waiting for a condition signal or broadcast * to wake up this thread. A loop is needed in case the waiting * thread is interrupted by a signal to execute a signal handler. * It is not (currently) possible to remain in the waiting queue * while running a handler. Instead, the thread is interrupted * and backed out of the waiting queue prior to executing the * signal handler. */ /* Lock the condition variable structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); seqno = (*cond)->c_seqno; do { /* * If the condvar was statically allocated, properly * initialize the tail queue. */ if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) { TAILQ_INIT(&(*cond)->c_queue); (*cond)->c_flags |= COND_FLAGS_INITED; } /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ case COND_TYPE_FAST: if ((mutex == NULL) || (((*cond)->c_mutex != NULL) && ((*cond)->c_mutex != *mutex))) { /* Return invalid argument error: */ rval = EINVAL; } else { /* Reset the timeout and interrupted flags: */ curthread->timeout = 0; curthread->interrupted = 0; /* * Queue the running thread for the condition * variable: */ cond_queue_enq(*cond, curthread); /* Unlock the mutex: */ if (mutex_locked && ((rval = _mutex_cv_unlock(mutex)) != 0)) { /* * Cannot unlock the mutex; remove the * running thread from the condition * variable queue: */ cond_queue_remove(*cond, curthread); } else { /* Remember the mutex: */ (*cond)->c_mutex = *mutex; /* * Don't unlock the mutex the next * time through the loop (if the * thread has to be requeued after * handling a signal). */ mutex_locked = 0; /* * This thread is active and is in a * critical region (holding the cv * lock); we should be able to safely * set the state. */ THR_SCHED_LOCK(curthread, curthread); /* Set the wakeup time: */ curthread->wakeup_time.tv_sec = abstime->tv_sec; curthread->wakeup_time.tv_nsec = abstime->tv_nsec; THR_SET_STATE(curthread, PS_COND_WAIT); /* Remember the CV: */ curthread->data.cond = *cond; curthread->sigbackout = cond_wait_backout; THR_SCHED_UNLOCK(curthread, curthread); /* Unlock the CV structure: */ THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); /* Schedule the next thread: */ _thr_sched_switch(curthread); /* * XXX - This really isn't a good check * since there can be more than one * thread waiting on the CV. Signals * sent to threads waiting on mutexes * or CVs should really be deferred * until the threads are no longer * waiting, but POSIX says that signals * should be sent "as soon as possible". */ done = (seqno != (*cond)->c_seqno); if (done && !THR_IN_CONDQ(curthread)) { /* * The thread is dequeued, so * it is safe to clear these. */ curthread->data.cond = NULL; curthread->sigbackout = NULL; check_continuation(curthread, NULL, mutex); return (_mutex_cv_lock(mutex)); } /* Relock the CV structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); /* * Clear these after taking the lock to * prevent a race condition where a * signal can arrive before dequeueing * the thread. */ curthread->data.cond = NULL; curthread->sigbackout = NULL; done = (seqno != (*cond)->c_seqno); if (THR_IN_CONDQ(curthread)) { cond_queue_remove(*cond, curthread); /* Check for no more waiters: */ if (TAILQ_EMPTY(&(*cond)->c_queue)) (*cond)->c_mutex = NULL; } if (curthread->timeout != 0) { /* The wait timedout. */ rval = ETIMEDOUT; } } } break; /* Trap invalid condition variable types: */ default: /* Return an invalid argument error: */ rval = EINVAL; break; } check_continuation(curthread, *cond, mutex_locked ? NULL : mutex); } while ((done == 0) && (rval == 0)); /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); if (mutex_locked == 0) _mutex_cv_lock(mutex); /* Return the completion status: */ return (rval); } int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = _pthread_cond_timedwait(cond, mutex, abstime); _thr_cancel_leave(curthread, 1); return (ret); } int _pthread_cond_signal(pthread_cond_t * cond) { struct pthread *curthread = _get_curthread(); struct pthread *pthread; struct kse_mailbox *kmbx; int rval = 0; THR_ASSERT(curthread->locklevel == 0, "cv_timedwait: locklevel is not zero!"); if (cond == NULL) rval = EINVAL; /* * If the condition variable is statically initialized, perform dynamic * initialization. */ - else if (*cond != NULL || (rval = pthread_cond_init(cond, NULL)) == 0) { + else if (*cond != NULL || (rval = _pthread_cond_init(cond, NULL)) == 0) { /* Lock the condition variable structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ case COND_TYPE_FAST: /* Increment the sequence number: */ (*cond)->c_seqno++; /* * Wakeups have to be done with the CV lock held; * otherwise there is a race condition where the * thread can timeout, run on another KSE, and enter * another blocking state (including blocking on a CV). */ if ((pthread = TAILQ_FIRST(&(*cond)->c_queue)) != NULL) { THR_SCHED_LOCK(curthread, pthread); cond_queue_remove(*cond, pthread); pthread->sigbackout = NULL; if ((pthread->kseg == curthread->kseg) && (pthread->active_priority > curthread->active_priority)) curthread->critical_yield = 1; kmbx = _thr_setrunnable_unlocked(pthread); THR_SCHED_UNLOCK(curthread, pthread); if (kmbx != NULL) kse_wakeup(kmbx); } /* Check for no more waiters: */ if (TAILQ_EMPTY(&(*cond)->c_queue)) (*cond)->c_mutex = NULL; break; /* Trap invalid condition variable types: */ default: /* Return an invalid argument error: */ rval = EINVAL; break; } /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); } /* Return the completion status: */ return (rval); } __strong_reference(_pthread_cond_signal, _thr_cond_signal); int _pthread_cond_broadcast(pthread_cond_t * cond) { struct pthread *curthread = _get_curthread(); struct pthread *pthread; struct kse_mailbox *kmbx; int rval = 0; THR_ASSERT(curthread->locklevel == 0, "cv_timedwait: locklevel is not zero!"); if (cond == NULL) rval = EINVAL; /* * If the condition variable is statically initialized, perform dynamic * initialization. */ - else if (*cond != NULL || (rval = pthread_cond_init(cond, NULL)) == 0) { + else if (*cond != NULL || (rval = _pthread_cond_init(cond, NULL)) == 0) { /* Lock the condition variable structure: */ THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); /* Process according to condition variable type: */ switch ((*cond)->c_type) { /* Fast condition variable: */ case COND_TYPE_FAST: /* Increment the sequence number: */ (*cond)->c_seqno++; /* * Enter a loop to bring all threads off the * condition queue: */ while ((pthread = TAILQ_FIRST(&(*cond)->c_queue)) != NULL) { THR_SCHED_LOCK(curthread, pthread); cond_queue_remove(*cond, pthread); pthread->sigbackout = NULL; if ((pthread->kseg == curthread->kseg) && (pthread->active_priority > curthread->active_priority)) curthread->critical_yield = 1; kmbx = _thr_setrunnable_unlocked(pthread); THR_SCHED_UNLOCK(curthread, pthread); if (kmbx != NULL) kse_wakeup(kmbx); } /* There are no more waiting threads: */ (*cond)->c_mutex = NULL; break; /* Trap invalid condition variable types: */ default: /* Return an invalid argument error: */ rval = EINVAL; break; } /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); } /* Return the completion status: */ return (rval); } __strong_reference(_pthread_cond_broadcast, _thr_cond_broadcast); static inline void check_continuation(struct pthread *curthread, struct pthread_cond *cond, pthread_mutex_t *mutex) { if ((curthread->interrupted != 0) && (curthread->continuation != NULL)) { if (cond != NULL) /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &cond->c_lock); /* * Note that even though this thread may have been * canceled, POSIX requires that the mutex be * reaquired prior to cancellation. */ if (mutex != NULL) _mutex_cv_lock(mutex); curthread->continuation((void *) curthread); PANIC("continuation returned in pthread_cond_wait.\n"); } } static void cond_wait_backout(void *arg) { struct pthread *curthread = (struct pthread *)arg; pthread_cond_t cond; cond = curthread->data.cond; if (cond != NULL) { /* Lock the condition variable structure: */ THR_LOCK_ACQUIRE(curthread, &cond->c_lock); /* Process according to condition variable type: */ switch (cond->c_type) { /* Fast condition variable: */ case COND_TYPE_FAST: cond_queue_remove(cond, curthread); /* Check for no more waiters: */ if (TAILQ_EMPTY(&cond->c_queue)) cond->c_mutex = NULL; break; default: break; } /* Unlock the condition variable structure: */ THR_LOCK_RELEASE(curthread, &cond->c_lock); } /* No need to call this again. */ curthread->sigbackout = NULL; } /* * Dequeue a waiting thread from the head of a condition queue in * descending priority order. */ static inline struct pthread * cond_queue_deq(pthread_cond_t cond) { struct pthread *pthread; while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) { TAILQ_REMOVE(&cond->c_queue, pthread, sqe); THR_CONDQ_CLEAR(pthread); if ((pthread->timeout == 0) && (pthread->interrupted == 0)) /* * Only exit the loop when we find a thread * that hasn't timed out or been canceled; * those threads are already running and don't * need their run state changed. */ break; } return (pthread); } /* * Remove a waiting thread from a condition queue in descending priority * order. */ static inline void cond_queue_remove(pthread_cond_t cond, struct pthread *pthread) { /* * Because pthread_cond_timedwait() can timeout as well * as be signaled by another thread, it is necessary to * guard against removing the thread from the queue if * it isn't in the queue. */ if (THR_IN_CONDQ(pthread)) { TAILQ_REMOVE(&cond->c_queue, pthread, sqe); THR_CONDQ_CLEAR(pthread); } } /* * Enqueue a waiting thread to a condition queue in descending priority * order. */ static inline void cond_queue_enq(pthread_cond_t cond, struct pthread *pthread) { struct pthread *tid = TAILQ_LAST(&cond->c_queue, cond_head); THR_ASSERT(!THR_IN_SYNCQ(pthread), "cond_queue_enq: thread already queued!"); /* * For the common case of all threads having equal priority, * we perform a quick check against the priority of the thread * at the tail of the queue. */ if ((tid == NULL) || (pthread->active_priority <= tid->active_priority)) TAILQ_INSERT_TAIL(&cond->c_queue, pthread, sqe); else { tid = TAILQ_FIRST(&cond->c_queue); while (pthread->active_priority <= tid->active_priority) tid = TAILQ_NEXT(tid, sqe); TAILQ_INSERT_BEFORE(tid, pthread, sqe); } THR_CONDQ_SET(pthread); pthread->data.cond = cond; } Index: head/lib/libkse/thread/thr_condattr_destroy.c =================================================================== --- head/lib/libkse/thread/thr_condattr_destroy.c (revision 174111) +++ head/lib/libkse/thread/thr_condattr_destroy.c (revision 174112) @@ -1,53 +1,56 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_condattr_destroy); LT10_COMPAT_DEFAULT(pthread_condattr_destroy); __weak_reference(_pthread_condattr_destroy, pthread_condattr_destroy); int _pthread_condattr_destroy(pthread_condattr_t *attr) { int ret; if (attr == NULL || *attr == NULL) { ret = EINVAL; } else { free(*attr); *attr = NULL; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_condattr_init.c =================================================================== --- head/lib/libkse/thread/thr_condattr_init.c (revision 174111) +++ head/lib/libkse/thread/thr_condattr_init.c (revision 174112) @@ -1,58 +1,61 @@ /* * Copyright (c) 1997 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_condattr_init); LT10_COMPAT_DEFAULT(pthread_condattr_init); __weak_reference(_pthread_condattr_init, pthread_condattr_init); int _pthread_condattr_init(pthread_condattr_t *attr) { int ret; pthread_condattr_t pattr; if ((pattr = (pthread_condattr_t) malloc(sizeof(struct pthread_cond_attr))) == NULL) { ret = ENOMEM; } else { memcpy(pattr, &_pthread_condattr_default, sizeof(struct pthread_cond_attr)); *attr = pattr; ret = 0; } return (ret); } Index: head/lib/libkse/thread/thr_condattr_pshared.c =================================================================== --- head/lib/libkse/thread/thr_condattr_pshared.c (revision 174111) +++ head/lib/libkse/thread/thr_condattr_pshared.c (revision 174112) @@ -1,56 +1,59 @@ /* * Copyright (c) 2005 David Xu * 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 unmodified, 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ * */ #include #include "thr_private.h" +int _pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared); +int _pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared); + __weak_reference(_pthread_condattr_getpshared, pthread_condattr_getpshared); __weak_reference(_pthread_condattr_setpshared, pthread_condattr_setpshared); int _pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); pshared = PTHREAD_PROCESS_PRIVATE; return (0); } int _pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); if (pshared != PTHREAD_PROCESS_PRIVATE) return (EINVAL); return (0); } Index: head/lib/libkse/thread/thr_connect.c =================================================================== --- head/lib/libkse/thread/thr_connect.c (revision 174111) +++ head/lib/libkse/thread/thr_connect.c (revision 174112) @@ -1,52 +1,54 @@ /* * Copyright (c) 2003 Daniel Eischen . * 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. 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 THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "thr_private.h" LT10_COMPAT_PRIVATE(__connect); LT10_COMPAT_DEFAULT(connect); +int __connect(int fd, const struct sockaddr *name, socklen_t namelen); + __weak_reference(__connect, connect); int __connect(int fd, const struct sockaddr *name, socklen_t namelen) { struct pthread *curthread; int ret; curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_connect(fd, name, namelen); _thr_cancel_leave(curthread, ret == -1); return (ret); } Index: head/lib/libkse/thread/thr_creat.c =================================================================== --- head/lib/libkse/thread/thr_creat.c (revision 174111) +++ head/lib/libkse/thread/thr_creat.c (revision 174112) @@ -1,58 +1,62 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(___creat); LT10_COMPAT_DEFAULT(creat); extern int __creat(const char *, mode_t); + +int ___creat(const char *path, mode_t mode); __weak_reference(___creat, creat); int ___creat(const char *path, mode_t mode) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __creat(path, mode); /* * To avoid possible file handle leak, * only check cancellation point if it is failure */ _thr_cancel_leave(curthread, (ret == -1)); return ret; } Index: head/lib/libkse/thread/thr_create.c =================================================================== --- head/lib/libkse/thread/thr_create.c (revision 174111) +++ head/lib/libkse/thread/thr_create.c (revision 174112) @@ -1,345 +1,348 @@ /* * Copyright (c) 2003 Daniel M. Eischen * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" #include "libc_private.h" LT10_COMPAT_PRIVATE(_pthread_create); LT10_COMPAT_DEFAULT(pthread_create); static void free_thread(struct pthread *curthread, struct pthread *thread); static int create_stack(struct pthread_attr *pattr); static void free_stack(struct pthread_attr *pattr); static void thread_start(struct pthread *curthread, void *(*start_routine) (void *), void *arg); __weak_reference(_pthread_create, pthread_create); /* * Some notes on new thread creation and first time initializion * to enable multi-threading. * * There are basically two things that need to be done. * * 1) The internal library variables must be initialized. * 2) Upcalls need to be enabled to allow multiple threads * to be run. * * The first may be done as a result of other pthread functions * being called. When _thr_initial is null, _libpthread_init is * called to initialize the internal variables; this also creates * or sets the initial thread. It'd be nice to automatically * have _libpthread_init called on program execution so we don't * have to have checks throughout the library. * * The second part is only triggered by the creation of the first * thread (other than the initial/main thread). If the thread * being created is a scope system thread, then a new KSE/KSEG * pair needs to be allocated. Also, if upcalls haven't been * enabled on the initial thread's KSE, they must be now that * there is more than one thread; this could be delayed until * the initial KSEG has more than one thread. */ int _pthread_create(pthread_t * thread, const pthread_attr_t * attr, void *(*start_routine) (void *), void *arg) { struct pthread *curthread, *new_thread; struct kse *kse = NULL; struct kse_group *kseg = NULL; kse_critical_t crit; int ret = 0; if (_thr_initial == NULL) _libpthread_init(NULL); /* * Turn on threaded mode, if failed, it is unnecessary to * do further work. */ if (_kse_isthreaded() == 0 && _kse_setthreaded(1)) { return (EAGAIN); } curthread = _get_curthread(); /* * Allocate memory for the thread structure. * Some functions use malloc, so don't put it * in a critical region. */ if ((new_thread = _thr_alloc(curthread)) == NULL) { /* Insufficient memory to create a thread: */ ret = EAGAIN; } else { /* Check if default thread attributes are required: */ if (attr == NULL || *attr == NULL) /* Use the default thread attributes: */ new_thread->attr = _pthread_attr_default; else { new_thread->attr = *(*attr); if ((*attr)->sched_inherit == PTHREAD_INHERIT_SCHED) { /* inherit scheduling contention scop */ if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; else new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM; /* * scheduling policy and scheduling parameters will be * inherited in following code. */ } } if (_thread_scope_system > 0) new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; else if ((_thread_scope_system < 0) && (thread != &_thr_sig_daemon)) new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM; if (create_stack(&new_thread->attr) != 0) { /* Insufficient memory to create a stack: */ ret = EAGAIN; _thr_free(curthread, new_thread); } else if (((new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0) && (((kse = _kse_alloc(curthread, 1)) == NULL) || ((kseg = _kseg_alloc(curthread)) == NULL))) { /* Insufficient memory to create a new KSE/KSEG: */ ret = EAGAIN; if (kse != NULL) { kse->k_kcb->kcb_kmbx.km_flags |= KMF_DONE; _kse_free(curthread, kse); } free_stack(&new_thread->attr); _thr_free(curthread, new_thread); } else { if (kseg != NULL) { /* Add the KSE to the KSEG's list of KSEs. */ TAILQ_INSERT_HEAD(&kseg->kg_kseq, kse, k_kgqe); kseg->kg_ksecount = 1; kse->k_kseg = kseg; kse->k_schedq = &kseg->kg_schedq; } /* * Write a magic value to the thread structure * to help identify valid ones: */ new_thread->magic = THR_MAGIC; new_thread->slice_usec = -1; new_thread->start_routine = start_routine; new_thread->arg = arg; new_thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED; /* No thread is wanting to join to this one: */ new_thread->joiner = NULL; /* * Initialize the machine context. * Enter a critical region to get consistent context. */ crit = _kse_critical_enter(); THR_GETCONTEXT(&new_thread->tcb->tcb_tmbx.tm_context); /* Initialize the thread for signals: */ new_thread->sigmask = curthread->sigmask; _kse_critical_leave(crit); new_thread->tcb->tcb_tmbx.tm_udata = new_thread; new_thread->tcb->tcb_tmbx.tm_context.uc_sigmask = new_thread->sigmask; new_thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_size = new_thread->attr.stacksize_attr; new_thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_sp = new_thread->attr.stackaddr_attr; makecontext(&new_thread->tcb->tcb_tmbx.tm_context, (void (*)(void))thread_start, 3, new_thread, start_routine, arg); /* * Check if this thread is to inherit the scheduling * attributes from its parent: */ if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) { /* * Copy the scheduling attributes. * Lock the scheduling lock to get consistent * scheduling parameters. */ THR_SCHED_LOCK(curthread, curthread); new_thread->base_priority = curthread->base_priority & ~THR_SIGNAL_PRIORITY; new_thread->attr.prio = curthread->base_priority & ~THR_SIGNAL_PRIORITY; new_thread->attr.sched_policy = curthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, curthread); } 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->active_priority = new_thread->base_priority; new_thread->inherited_priority = 0; /* Initialize the mutex queue: */ TAILQ_INIT(&new_thread->mutexq); /* Initialise hooks in the thread structure: */ new_thread->specific = NULL; new_thread->specific_data_count = 0; new_thread->cleanup = NULL; new_thread->flags = 0; new_thread->tlflags = 0; new_thread->sigbackout = NULL; new_thread->continuation = NULL; new_thread->wakeup_time.tv_sec = -1; new_thread->lock_switch = 0; sigemptyset(&new_thread->sigpend); new_thread->check_pending = 0; new_thread->locklevel = 0; new_thread->rdlock_count = 0; new_thread->sigstk.ss_sp = 0; new_thread->sigstk.ss_size = 0; new_thread->sigstk.ss_flags = SS_DISABLE; new_thread->oldsigmask = NULL; if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) { new_thread->state = PS_SUSPENDED; new_thread->flags = THR_FLAGS_SUSPENDED; } else new_thread->state = PS_RUNNING; /* * System scope threads have their own kse and * kseg. Process scope threads are all hung * off the main process kseg. */ if ((new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM) == 0) { new_thread->kseg = _kse_initial->k_kseg; new_thread->kse = _kse_initial; } else { kse->k_curthread = NULL; kse->k_kseg->kg_flags |= KGF_SINGLE_THREAD; new_thread->kse = kse; new_thread->kseg = kse->k_kseg; kse->k_kcb->kcb_kmbx.km_udata = kse; kse->k_kcb->kcb_kmbx.km_curthread = NULL; } /* * Schedule the new thread starting a new KSEG/KSE * pair if necessary. */ ret = _thr_schedule_add(curthread, new_thread); if (ret != 0) free_thread(curthread, new_thread); else { /* Return a pointer to the thread structure: */ (*thread) = new_thread; } } } /* Return the status: */ return (ret); } static void free_thread(struct pthread *curthread, struct pthread *thread) { free_stack(&thread->attr); if ((thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0) { /* Free the KSE and KSEG. */ _kseg_free(thread->kseg); _kse_free(curthread, thread->kse); } _thr_free(curthread, thread); } static int create_stack(struct pthread_attr *pattr) { int ret; /* Check if a stack was specified in the thread attributes: */ if ((pattr->stackaddr_attr) != NULL) { pattr->guardsize_attr = 0; pattr->flags |= THR_STACK_USER; ret = 0; } else ret = _thr_stack_alloc(pattr); return (ret); } static void free_stack(struct pthread_attr *pattr) { struct kse *curkse; kse_critical_t crit; if ((pattr->flags & THR_STACK_USER) == 0) { crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); /* Stack routines don't use malloc/free. */ _thr_stack_free(pattr); KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); } } static void -thread_start(struct pthread *curthread, void *(*start_routine) (void *), +thread_start(struct pthread *curthread __unused, void *(*start_routine) (void *), void *arg) { /* Run the current thread's start routine with argument: */ - pthread_exit(start_routine(arg)); + _pthread_exit(start_routine(arg)); /* This point should never be reached. */ PANIC("Thread has resumed after exit"); } Index: head/lib/libkse/thread/thr_detach.c =================================================================== --- head/lib/libkse/thread/thr_detach.c (revision 174111) +++ head/lib/libkse/thread/thr_detach.c (revision 174112) @@ -1,117 +1,119 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_detach); LT10_COMPAT_DEFAULT(pthread_detach); __weak_reference(_pthread_detach, pthread_detach); int _pthread_detach(pthread_t pthread) { struct pthread *curthread = _get_curthread(); struct kse_mailbox *kmbx = NULL; struct pthread *joiner; int rval = 0; /* Check for invalid calling parameters: */ if (pthread == NULL || pthread->magic != THR_MAGIC) /* Return an invalid argument error: */ rval = EINVAL; else if ((rval = _thr_ref_add(curthread, pthread, /*include dead*/1)) != 0) { /* Return an error: */ } /* Check if the thread is already detached: */ else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) { /* Return an error: */ _thr_ref_delete(curthread, pthread); rval = EINVAL; } else { /* Lock the detached thread: */ THR_SCHED_LOCK(curthread, pthread); /* Flag the thread as detached: */ pthread->attr.flags |= PTHREAD_DETACHED; /* Retrieve any joining thread and remove it: */ joiner = pthread->joiner; if ((joiner != NULL) && (joiner->kseg == pthread->kseg)) { /* * We already own the scheduler lock for the joiner. * Take advantage of that and make the joiner runnable. */ if (joiner->join_status.thread == pthread) { /* * Set the return value for the woken thread: */ joiner->join_status.error = ESRCH; joiner->join_status.ret = NULL; joiner->join_status.thread = NULL; kmbx = _thr_setrunnable_unlocked(joiner); } joiner = NULL; } THR_SCHED_UNLOCK(curthread, pthread); /* See if there is a thread waiting in pthread_join(): */ if ((joiner != NULL) && (_thr_ref_add(curthread, joiner, 0) == 0)) { /* Lock the joiner before fiddling with it. */ THR_SCHED_LOCK(curthread, joiner); if (joiner->join_status.thread == pthread) { /* * Set the return value for the woken thread: */ joiner->join_status.error = ESRCH; joiner->join_status.ret = NULL; joiner->join_status.thread = NULL; kmbx = _thr_setrunnable_unlocked(joiner); } THR_SCHED_UNLOCK(curthread, joiner); _thr_ref_delete(curthread, joiner); } _thr_ref_delete(curthread, pthread); if (kmbx != NULL) kse_wakeup(kmbx); } /* Return the completion status: */ return (rval); } Index: head/lib/libkse/thread/thr_equal.c =================================================================== --- head/lib/libkse/thread/thr_equal.c (revision 174111) +++ head/lib/libkse/thread/thr_equal.c (revision 174112) @@ -1,44 +1,47 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_equal); LT10_COMPAT_DEFAULT(pthread_equal); __weak_reference(_pthread_equal, pthread_equal); int _pthread_equal(pthread_t t1, pthread_t t2) { /* Compare the two thread pointers: */ return (t1 == t2); } Index: head/lib/libkse/thread/thr_execve.c =================================================================== --- head/lib/libkse/thread/thr_execve.c (revision 174111) +++ head/lib/libkse/thread/thr_execve.c (revision 174112) @@ -1,66 +1,68 @@ /* * Copyright (C) 2004 Daniel Eischen * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_execve); LT10_COMPAT_DEFAULT(execve); __weak_reference(_execve, execve); int _execve(const char *name, char *const *argv, char *const *envp) { struct kse_execve_args args; struct pthread *curthread = _get_curthread(); int ret; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) ret = __sys_execve(name, argv, envp); else { /* * When exec'ing, set the kernel signal mask to the thread's * signal mask to satisfy POSIX requirements. */ args.sigmask = curthread->sigmask; args.sigpend = curthread->sigpend; args.path = (char *)name; args.argv = (char **)argv; args.envp = (char **)envp; args.reserved = NULL; ret = kse_thr_interrupt(NULL, KSE_INTR_EXECVE, (long)&args); } return (ret); } Index: head/lib/libkse/thread/thr_exit.c =================================================================== --- head/lib/libkse/thread/thr_exit.c (revision 174111) +++ head/lib/libkse/thread/thr_exit.c (revision 174112) @@ -1,159 +1,162 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_exit); LT10_COMPAT_DEFAULT(pthread_exit); void _pthread_exit(void *status); __weak_reference(_pthread_exit, pthread_exit); void -_thr_exit(char *fname, int lineno, char *msg) +_thr_exit(const char *fname, int lineno, const char *msg) { /* Write an error message to the standard error file descriptor: */ _thread_printf(2, "Fatal error '%s' at line %d in file %s (errno = %d)\n", msg, lineno, fname, errno); abort(); } /* * Only called when a thread is cancelled. It may be more useful * to call it from pthread_exit() if other ways of asynchronous or * abnormal thread termination can be found. */ void _thr_exit_cleanup(void) { struct pthread *curthread = _get_curthread(); /* * POSIX states that cancellation/termination of a thread should * not release any visible resources (such as mutexes) and that * it is the applications responsibility. Resources that are * internal to the threads library, including file and fd locks, * are not visible to the application and need to be released. */ /* Unlock all private mutexes: */ _mutex_unlock_private(curthread); /* * This still isn't quite correct because we don't account * for held spinlocks (see libc/stdlib/malloc.c). */ } void _pthread_exit(void *status) { struct pthread *curthread = _get_curthread(); kse_critical_t crit; struct kse *curkse; /* Check if this thread is already in the process of exiting: */ if ((curthread->flags & THR_FLAGS_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!", curthread); PANIC(msg); } /* * Flag this thread as exiting. Threads should now be prevented * from joining to this thread. */ THR_SCHED_LOCK(curthread, curthread); curthread->flags |= THR_FLAGS_EXITING; THR_SCHED_UNLOCK(curthread, curthread); /* * To avoid signal-lost problem, if signals had already been * delivered to us, handle it. we have already set EXITING flag * so no new signals should be delivered to us. * XXX this is not enough if signal was delivered just before * thread called sigprocmask and masked it! in this case, we * might have to re-post the signal by kill() if the signal * is targeting process (not for a specified thread). * Kernel has same signal-lost problem, a signal may be delivered * to a thread which is on the way to call sigprocmask or thr_exit()! */ if (curthread->check_pending) _thr_sig_check_pending(curthread); /* Save the return value: */ curthread->ret = status; while (curthread->cleanup != NULL) { - pthread_cleanup_pop(1); + _pthread_cleanup_pop(1); } if (curthread->attr.cleanup_attr != NULL) { curthread->attr.cleanup_attr(curthread->attr.arg_attr); } /* Check if there is thread specific data: */ if (curthread->specific != NULL) { /* Run the thread-specific data destructors: */ _thread_cleanupspecific(); } if (!_kse_isthreaded()) exit(0); crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); /* Use thread_list_lock */ _thread_active_threads--; if ((_thread_scope_system <= 0 && _thread_active_threads == 1) || (_thread_scope_system > 0 && _thread_active_threads == 0)) { KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); exit(0); /* Never reach! */ } KSE_LOCK_RELEASE(curkse, &_thread_list_lock); /* This thread will never be re-scheduled. */ KSE_LOCK(curkse); THR_SET_STATE(curthread, PS_DEAD); _thr_sched_switch_unlocked(curthread); /* Never reach! */ /* This point should not be reached. */ PANIC("Dead thread has resumed"); } Index: head/lib/libkse/thread/thr_fcntl.c =================================================================== --- head/lib/libkse/thread/thr_fcntl.c (revision 174111) +++ head/lib/libkse/thread/thr_fcntl.c (revision 174112) @@ -1,78 +1,81 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ -#include + #include "namespace.h" +#include #include -#include "un-namespace.h" #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__fcntl); LT10_COMPAT_DEFAULT(fcntl); + +int __fcntl(int fd, int cmd,...); __weak_reference(__fcntl, fcntl); int __fcntl(int fd, int cmd,...) { struct pthread *curthread = _get_curthread(); int ret, check = 1; va_list ap; _thr_cancel_enter(curthread); va_start(ap, cmd); switch (cmd) { case F_DUPFD: ret = __sys_fcntl(fd, cmd, va_arg(ap, int)); /* * To avoid possible file handle leak, * only check cancellation point if it is failure */ check = (ret == -1); break; case F_SETFD: case F_SETFL: ret = __sys_fcntl(fd, cmd, va_arg(ap, int)); break; case F_GETFD: case F_GETFL: ret = __sys_fcntl(fd, cmd); break; default: ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); } va_end(ap); _thr_cancel_leave(curthread, check); return (ret); } Index: head/lib/libkse/thread/thr_find_thread.c =================================================================== --- head/lib/libkse/thread/thr_find_thread.c (revision 174111) +++ head/lib/libkse/thread/thr_find_thread.c (revision 174112) @@ -1,95 +1,98 @@ /* * Copyright (c) 2003 Daniel Eischen * Copyright (c) 1998 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" /* * Find a thread in the linked list of active threads and add a reference * to it. Threads with positive reference counts will not be deallocated * until all references are released. */ int _thr_ref_add(struct pthread *curthread, struct pthread *thread, int include_dead) { kse_critical_t crit; struct pthread *pthread; struct kse *curkse; if (thread == NULL) /* Invalid thread: */ return (EINVAL); crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); pthread = _thr_hash_find(thread); if (pthread) { if ((include_dead == 0) && ((pthread->state == PS_DEAD) || ((pthread->state == PS_DEADLOCK) || ((pthread->flags & THR_FLAGS_EXITING) != 0)))) pthread = NULL; else { pthread->refcount++; if (curthread != NULL) curthread->critical_count++; } } KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); /* Return zero if the thread exists: */ return ((pthread != NULL) ? 0 : ESRCH); } void _thr_ref_delete(struct pthread *curthread, struct pthread *thread) { kse_critical_t crit; struct kse *curkse; if (thread != NULL) { crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); thread->refcount--; if (curthread != NULL) curthread->critical_count--; if ((thread->refcount == 0) && (thread->tlflags & TLFLAGS_GC_SAFE) != 0) THR_GCLIST_ADD(thread); KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); } } Index: head/lib/libkse/thread/thr_fork.c =================================================================== --- head/lib/libkse/thread/thr_fork.c (revision 174111) +++ head/lib/libkse/thread/thr_fork.c (revision 174112) @@ -1,128 +1,133 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include #include +#include "un-namespace.h" #include "libc_private.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_fork); LT10_COMPAT_DEFAULT(fork); + +pid_t _fork(void); __weak_reference(_fork, fork); pid_t _fork(void) { sigset_t sigset, oldset; struct pthread *curthread; struct pthread_atfork *af; pid_t ret; int errsave; curthread = _get_curthread(); if (!_kse_isthreaded()) { SIGFILLSET(sigset); __sys_sigprocmask(SIG_SETMASK, &sigset, &oldset); ret = __sys_fork(); if (ret == 0) /* Child */ __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); else __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); return (ret); } /* * Masks all signals until we reach a safe point in * _kse_single_thread, and the signal masks will be * restored in that function, for M:N thread, all * signals were already masked in kernel atomically, * we only need to do this for bound thread. */ if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { SIGFILLSET(sigset); __sys_sigprocmask(SIG_SETMASK, &sigset, &oldset); } _pthread_mutex_lock(&_thr_atfork_mutex); /* Run down atfork prepare handlers. */ TAILQ_FOREACH_REVERSE(af, &_thr_atfork_list, atfork_head, qe) { if (af->prepare != NULL) af->prepare(); } /* Fork a new process: */ if (_kse_isthreaded() != 0) { _malloc_prefork(); } if ((ret = __sys_fork()) == 0) { /* Child process */ errsave = errno; /* Kernel signal mask is restored in _kse_single_thread */ _kse_single_thread(curthread); /* Run down atfork child handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { if (af->child != NULL) af->child(); } _thr_mutex_reinit(&_thr_atfork_mutex); } else { if (_kse_isthreaded() != 0) { _malloc_postfork(); } errsave = errno; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); } /* Run down atfork parent handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { if (af->parent != NULL) af->parent(); } _pthread_mutex_unlock(&_thr_atfork_mutex); } errno = errsave; /* Return the process ID: */ return (ret); } Index: head/lib/libkse/thread/thr_fsync.c =================================================================== --- head/lib/libkse/thread/thr_fsync.c (revision 174111) +++ head/lib/libkse/thread/thr_fsync.c (revision 174112) @@ -1,51 +1,56 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__fsync); LT10_COMPAT_DEFAULT(fsync); + +int __fsync(int fd); __weak_reference(__fsync, fsync); int __fsync(int fd) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __sys_fsync(fd); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_getschedparam.c =================================================================== --- head/lib/libkse/thread/thr_getschedparam.c (revision 174111) +++ head/lib/libkse/thread/thr_getschedparam.c (revision 174112) @@ -1,78 +1,81 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_getschedparam); LT10_COMPAT_DEFAULT(pthread_getschedparam); __weak_reference(_pthread_getschedparam, pthread_getschedparam); int _pthread_getschedparam(pthread_t pthread, int *policy, struct sched_param *param) { struct pthread *curthread = _get_curthread(); int ret, tmp; if ((param == NULL) || (policy == NULL)) /* Return an invalid argument error: */ ret = EINVAL; else if (pthread == curthread) { /* * Avoid searching the thread list when it is the current * thread. */ THR_SCHED_LOCK(curthread, curthread); param->sched_priority = THR_BASE_PRIORITY(pthread->base_priority); tmp = pthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, curthread); *policy = tmp; ret = 0; } /* Find the thread in the list of active threads. */ else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0)) == 0) { THR_SCHED_LOCK(curthread, pthread); param->sched_priority = THR_BASE_PRIORITY(pthread->base_priority); tmp = pthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); *policy = tmp; } return (ret); } Index: head/lib/libkse/thread/thr_info.c =================================================================== --- head/lib/libkse/thread/thr_info.c (revision 174111) +++ head/lib/libkse/thread/thr_info.c (revision 174112) @@ -1,244 +1,248 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" #ifndef NELEMENTS #define NELEMENTS(arr) (sizeof(arr) / sizeof(arr[0])) #endif LT10_COMPAT_PRIVATE(_pthread_set_name_np); LT10_COMPAT_DEFAULT(pthread_set_name_np); static void dump_thread(int fd, pthread_t pthread, int long_version); +void _pthread_set_name_np(pthread_t thread, char *name); __weak_reference(_pthread_set_name_np, pthread_set_name_np); struct s_thread_info { enum pthread_state state; - char *name; + const char *name; }; /* Static variables: */ static const struct s_thread_info thread_info[] = { {PS_RUNNING , "Running"}, {PS_LOCKWAIT , "Waiting on an internal lock"}, {PS_MUTEX_WAIT , "Waiting on a mutex"}, {PS_COND_WAIT , "Waiting on a condition variable"}, {PS_SLEEP_WAIT , "Sleeping"}, {PS_SIGSUSPEND , "Suspended, waiting for a signal"}, {PS_SIGWAIT , "Waiting for a signal"}, {PS_JOIN , "Waiting to join"}, {PS_SUSPENDED , "Suspended"}, {PS_DEAD , "Dead"}, {PS_DEADLOCK , "Deadlocked"}, {PS_STATE_MAX , "Not a real state!"} }; void _thread_dump_info(void) { - char s[512], tmpfile[128]; + char s[512], tempfile[128]; pthread_t pthread; int fd, i; for (i = 0; i < 100000; i++) { - snprintf(tmpfile, sizeof(tmpfile), "/tmp/pthread.dump.%u.%i", + snprintf(tempfile, sizeof(tempfile), "/tmp/pthread.dump.%u.%i", getpid(), i); /* Open the dump file for append and create it if necessary: */ - if ((fd = __sys_open(tmpfile, O_RDWR | O_CREAT | O_EXCL, + if ((fd = __sys_open(tempfile, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { /* Can't open the dump file. */ if (errno == EEXIST) continue; /* * We only need to continue in case of * EEXIT error. Most other error * codes means that we will fail all * the times. */ return; } else { break; } } if (i==100000) { /* all 100000 possibilities are in use :( */ return; } else { /* Dump the active threads. */ strcpy(s, "\n\n========\nACTIVE THREADS\n\n"); __sys_write(fd, s, strlen(s)); /* Enter a loop to report each thread in the global list: */ TAILQ_FOREACH(pthread, &_thread_list, tle) { if (pthread->state != PS_DEAD) dump_thread(fd, pthread, /*long_verson*/ 1); } /* * Dump the ready threads. * XXX - We can't easily do this because the run queues * are per-KSEG. */ strcpy(s, "\n\n========\nREADY THREADS - unimplemented\n\n"); __sys_write(fd, s, strlen(s)); /* * Dump the waiting threads. * XXX - We can't easily do this because the wait queues * are per-KSEG. */ strcpy(s, "\n\n========\nWAITING THREADS - unimplemented\n\n"); __sys_write(fd, s, strlen(s)); /* Close the dump file. */ __sys_close(fd); } } static void dump_thread(int fd, pthread_t pthread, int long_version) { struct pthread *curthread = _get_curthread(); char s[512]; int i; /* Find the state: */ - for (i = 0; i < NELEMENTS(thread_info) - 1; i++) + for (i = 0; i < (int)NELEMENTS(thread_info) - 1; i++) if (thread_info[i].state == pthread->state) break; /* Output a record for the thread: */ snprintf(s, sizeof(s), "--------------------\n" "Thread %p (%s), scope %s, prio %3d, blocked %s, state %s [%s:%d]\n", pthread, (pthread->name == NULL) ? "" : pthread->name, pthread->attr.flags & PTHREAD_SCOPE_SYSTEM ? "system" : "process", pthread->active_priority, (pthread->blocked != 0) ? "yes" : "no", thread_info[i].name, pthread->fname, pthread->lineno); __sys_write(fd, s, strlen(s)); if (long_version != 0) { /* Check if this is the running thread: */ if (pthread == curthread) { /* Output a record for the running thread: */ strcpy(s, "This is the running thread\n"); __sys_write(fd, s, strlen(s)); } /* Check if this is the initial thread: */ if (pthread == _thr_initial) { /* Output a record for the initial thread: */ strcpy(s, "This is the initial thread\n"); __sys_write(fd, s, strlen(s)); } /* Process according to thread state: */ switch (pthread->state) { case PS_SIGWAIT: snprintf(s, sizeof(s), "sigmask (hi) "); __sys_write(fd, s, strlen(s)); for (i = _SIG_WORDS - 1; i >= 0; i--) { snprintf(s, sizeof(s), "%08x ", pthread->sigmask.__bits[i]); __sys_write(fd, s, strlen(s)); } snprintf(s, sizeof(s), "(lo)\n"); __sys_write(fd, s, strlen(s)); snprintf(s, sizeof(s), "waitset (hi) "); __sys_write(fd, s, strlen(s)); for (i = _SIG_WORDS - 1; i >= 0; i--) { snprintf(s, sizeof(s), "%08x ", pthread->data.sigwait->waitset->__bits[i]); __sys_write(fd, s, strlen(s)); } snprintf(s, sizeof(s), "(lo)\n"); __sys_write(fd, s, strlen(s)); break; /* * Trap other states that are not explicitly * coded to dump information: */ default: snprintf(s, sizeof(s), "sigmask (hi) "); __sys_write(fd, s, strlen(s)); for (i = _SIG_WORDS - 1; i >= 0; i--) { snprintf(s, sizeof(s), "%08x ", pthread->sigmask.__bits[i]); __sys_write(fd, s, strlen(s)); } snprintf(s, sizeof(s), "(lo)\n"); __sys_write(fd, s, strlen(s)); break; } } } /* Set the thread name for debug: */ void _pthread_set_name_np(pthread_t thread, char *name) { struct pthread *curthread = _get_curthread(); char *new_name; char *prev_name; int ret; new_name = strdup(name); /* Add a reference to the target thread. */ if (_thr_ref_add(curthread, thread, 0) != 0) { free(new_name); ret = ESRCH; } else { THR_THREAD_LOCK(curthread, thread); prev_name = thread->name; thread->name = new_name; THR_THREAD_UNLOCK(curthread, thread); _thr_ref_delete(curthread, thread); if (prev_name != NULL) { /* Free space for previous name. */ free(prev_name); } ret = 0; } #if 0 /* XXX - Should return error code. */ return (ret); #endif } Index: head/lib/libkse/thread/thr_init.c =================================================================== --- head/lib/libkse/thread/thr_init.c (revision 174111) +++ head/lib/libkse/thread/thr_init.c (revision 174112) @@ -1,530 +1,531 @@ /* * Copyright (c) 2003 Daniel M. Eischen * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ /* Allocate space for global thread variables here: */ #define GLOBAL_PTHREAD_PRIVATE #include "namespace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "un-namespace.h" #include "libc_private.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_libkse_debug); LT10_COMPAT_PRIVATE(_thread_activated); LT10_COMPAT_PRIVATE(_thread_active_threads); LT10_COMPAT_PRIVATE(_thread_list); int __pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); int __pthread_mutex_lock(pthread_mutex_t *); int __pthread_mutex_trylock(pthread_mutex_t *); void _thread_init_hack(void); extern int _thread_state_running; static void init_private(void); static void init_main_thread(struct pthread *thread); /* * All weak references used within libc should be in this table. * This is so that static libraries will work. */ static void *references[] = { &_accept, &_bind, &_close, &_connect, &_dup, &_dup2, &_execve, &_fcntl, &_flock, &_flockfile, &_fstat, &_fstatfs, &_fsync, &_funlockfile, &_getdirentries, &_getlogin, &_getpeername, &_getsockname, &_getsockopt, &_ioctl, &_kevent, &_listen, &_nanosleep, &_open, &_pthread_getspecific, &_pthread_key_create, &_pthread_key_delete, &_pthread_mutex_destroy, &_pthread_mutex_init, &_pthread_mutex_lock, &_pthread_mutex_trylock, &_pthread_mutex_unlock, &_pthread_mutexattr_init, &_pthread_mutexattr_destroy, &_pthread_mutexattr_settype, &_pthread_once, &_pthread_setspecific, &_read, &_readv, &_recvfrom, &_recvmsg, &_select, &_sendmsg, &_sendto, &_setsockopt, &_sigaction, &_sigprocmask, &_sigsuspend, &_socket, &_socketpair, &_thread_init_hack, &_wait4, &_write, &_writev }; /* * These are needed when linking statically. All references within * libgcc (and in the future libc) to these routines are weak, but * if they are not (strongly) referenced by the application or other * libraries, then the actual functions will not be loaded. */ static void *libgcc_references[] = { &_pthread_once, &_pthread_key_create, &_pthread_key_delete, &_pthread_getspecific, &_pthread_setspecific, &_pthread_mutex_init, &_pthread_mutex_destroy, &_pthread_mutex_lock, &_pthread_mutex_trylock, &_pthread_mutex_unlock }; #define DUAL_ENTRY(entry) \ (pthread_func_t)entry, (pthread_func_t)entry static pthread_func_t jmp_table[][2] = { {DUAL_ENTRY(_pthread_atfork)}, /* PJT_ATFORK */ {DUAL_ENTRY(_pthread_attr_destroy)}, /* PJT_ATTR_DESTROY */ {DUAL_ENTRY(_pthread_attr_getdetachstate)}, /* PJT_ATTR_GETDETACHSTATE */ {DUAL_ENTRY(_pthread_attr_getguardsize)}, /* PJT_ATTR_GETGUARDSIZE */ {DUAL_ENTRY(_pthread_attr_getinheritsched)}, /* PJT_ATTR_GETINHERITSCHED */ {DUAL_ENTRY(_pthread_attr_getschedparam)}, /* PJT_ATTR_GETSCHEDPARAM */ {DUAL_ENTRY(_pthread_attr_getschedpolicy)}, /* PJT_ATTR_GETSCHEDPOLICY */ {DUAL_ENTRY(_pthread_attr_getscope)}, /* PJT_ATTR_GETSCOPE */ {DUAL_ENTRY(_pthread_attr_getstackaddr)}, /* PJT_ATTR_GETSTACKADDR */ {DUAL_ENTRY(_pthread_attr_getstacksize)}, /* PJT_ATTR_GETSTACKSIZE */ {DUAL_ENTRY(_pthread_attr_init)}, /* PJT_ATTR_INIT */ {DUAL_ENTRY(_pthread_attr_setdetachstate)}, /* PJT_ATTR_SETDETACHSTATE */ {DUAL_ENTRY(_pthread_attr_setguardsize)}, /* PJT_ATTR_SETGUARDSIZE */ {DUAL_ENTRY(_pthread_attr_setinheritsched)}, /* PJT_ATTR_SETINHERITSCHED */ {DUAL_ENTRY(_pthread_attr_setschedparam)}, /* PJT_ATTR_SETSCHEDPARAM */ {DUAL_ENTRY(_pthread_attr_setschedpolicy)}, /* PJT_ATTR_SETSCHEDPOLICY */ {DUAL_ENTRY(_pthread_attr_setscope)}, /* PJT_ATTR_SETSCOPE */ {DUAL_ENTRY(_pthread_attr_setstackaddr)}, /* PJT_ATTR_SETSTACKADDR */ {DUAL_ENTRY(_pthread_attr_setstacksize)}, /* PJT_ATTR_SETSTACKSIZE */ {DUAL_ENTRY(_pthread_cancel)}, /* PJT_CANCEL */ {DUAL_ENTRY(_pthread_cleanup_pop)}, /* PJT_CLEANUP_POP */ {DUAL_ENTRY(_pthread_cleanup_push)}, /* PJT_CLEANUP_PUSH */ {DUAL_ENTRY(_pthread_cond_broadcast)}, /* PJT_COND_BROADCAST */ {DUAL_ENTRY(_pthread_cond_destroy)}, /* PJT_COND_DESTROY */ {DUAL_ENTRY(_pthread_cond_init)}, /* PJT_COND_INIT */ {DUAL_ENTRY(_pthread_cond_signal)}, /* PJT_COND_SIGNAL */ {DUAL_ENTRY(_pthread_cond_timedwait)}, /* PJT_COND_TIMEDWAIT */ {(pthread_func_t)__pthread_cond_wait, (pthread_func_t)_pthread_cond_wait}, /* PJT_COND_WAIT */ {DUAL_ENTRY(_pthread_detach)}, /* PJT_DETACH */ {DUAL_ENTRY(_pthread_equal)}, /* PJT_EQUAL */ {DUAL_ENTRY(_pthread_exit)}, /* PJT_EXIT */ {DUAL_ENTRY(_pthread_getspecific)}, /* PJT_GETSPECIFIC */ {DUAL_ENTRY(_pthread_join)}, /* PJT_JOIN */ {DUAL_ENTRY(_pthread_key_create)}, /* PJT_KEY_CREATE */ {DUAL_ENTRY(_pthread_key_delete)}, /* PJT_KEY_DELETE*/ {DUAL_ENTRY(_pthread_kill)}, /* PJT_KILL */ {DUAL_ENTRY(_pthread_main_np)}, /* PJT_MAIN_NP */ {DUAL_ENTRY(_pthread_mutexattr_destroy)}, /* PJT_MUTEXATTR_DESTROY */ {DUAL_ENTRY(_pthread_mutexattr_init)}, /* PJT_MUTEXATTR_INIT */ {DUAL_ENTRY(_pthread_mutexattr_settype)}, /* PJT_MUTEXATTR_SETTYPE */ {DUAL_ENTRY(_pthread_mutex_destroy)}, /* PJT_MUTEX_DESTROY */ {DUAL_ENTRY(_pthread_mutex_init)}, /* PJT_MUTEX_INIT */ {(pthread_func_t)__pthread_mutex_lock, (pthread_func_t)_pthread_mutex_lock}, /* PJT_MUTEX_LOCK */ {(pthread_func_t)__pthread_mutex_trylock, (pthread_func_t)_pthread_mutex_trylock},/* PJT_MUTEX_TRYLOCK */ {DUAL_ENTRY(_pthread_mutex_unlock)}, /* PJT_MUTEX_UNLOCK */ {DUAL_ENTRY(_pthread_once)}, /* PJT_ONCE */ {DUAL_ENTRY(_pthread_rwlock_destroy)}, /* PJT_RWLOCK_DESTROY */ {DUAL_ENTRY(_pthread_rwlock_init)}, /* PJT_RWLOCK_INIT */ {DUAL_ENTRY(_pthread_rwlock_rdlock)}, /* PJT_RWLOCK_RDLOCK */ {DUAL_ENTRY(_pthread_rwlock_tryrdlock)},/* PJT_RWLOCK_TRYRDLOCK */ {DUAL_ENTRY(_pthread_rwlock_trywrlock)},/* PJT_RWLOCK_TRYWRLOCK */ {DUAL_ENTRY(_pthread_rwlock_unlock)}, /* PJT_RWLOCK_UNLOCK */ {DUAL_ENTRY(_pthread_rwlock_wrlock)}, /* PJT_RWLOCK_WRLOCK */ {DUAL_ENTRY(_pthread_self)}, /* PJT_SELF */ {DUAL_ENTRY(_pthread_setcancelstate)}, /* PJT_SETCANCELSTATE */ {DUAL_ENTRY(_pthread_setcanceltype)}, /* PJT_SETCANCELTYPE */ {DUAL_ENTRY(_pthread_setspecific)}, /* PJT_SETSPECIFIC */ {DUAL_ENTRY(_pthread_sigmask)}, /* PJT_SIGMASK */ {DUAL_ENTRY(_pthread_testcancel)} /* PJT_TESTCANCEL */ }; static int init_once = 0; /* * Threaded process initialization. * * This is only called under two conditions: * * 1) Some thread routines have detected that the library hasn't yet * been initialized (_thr_initial == NULL && curthread == NULL), or * * 2) An explicit call to reinitialize after a fork (indicated * by curthread != NULL) */ void _libpthread_init(struct pthread *curthread) { int fd; /* Check if this function has already been called: */ if ((_thr_initial != NULL) && (curthread == NULL)) /* Only initialize the threaded application once. */ return; /* * Make gcc quiescent about {,libgcc_}references not being * referenced: */ if ((references[0] == NULL) || (libgcc_references[0] == NULL)) PANIC("Failed loading mandatory references in _thread_init"); /* Pull debug symbols in for static binary */ _thread_state_running = PS_RUNNING; /* * Check the size of the jump table to make sure it is preset * with the correct number of entries. */ if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2)) PANIC("Thread jump table not properly initialized"); memcpy(__thr_jtable, jmp_table, sizeof(jmp_table)); /* * Check for the special case of this process running as * or in place of init as pid = 1: */ if ((_thr_pid = getpid()) == 1) { /* * Setup a new session for this process which is * assumed to be running as root. */ if (setsid() == -1) PANIC("Can't set session ID"); if (revoke(_PATH_CONSOLE) != 0) PANIC("Can't revoke console"); if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) PANIC("Can't open console"); if (setlogin("root") == -1) PANIC("Can't set login to root"); if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) PANIC("Can't set controlling terminal"); } /* Initialize pthread private data. */ init_private(); _kse_init(); /* Initialize the initial kse and kseg. */ _kse_initial = _kse_alloc(NULL, _thread_scope_system > 0); if (_kse_initial == NULL) PANIC("Can't allocate initial kse."); _kse_initial->k_kseg = _kseg_alloc(NULL); if (_kse_initial->k_kseg == NULL) PANIC("Can't allocate initial kseg."); _kse_initial->k_kseg->kg_flags |= KGF_SINGLE_THREAD; _kse_initial->k_schedq = &_kse_initial->k_kseg->kg_schedq; TAILQ_INSERT_TAIL(&_kse_initial->k_kseg->kg_kseq, _kse_initial, k_kgqe); _kse_initial->k_kseg->kg_ksecount = 1; /* Set the initial thread. */ if (curthread == NULL) { /* Create and initialize the initial thread. */ curthread = _thr_alloc(NULL); if (curthread == NULL) PANIC("Can't allocate initial thread"); _thr_initial = curthread; init_main_thread(curthread); } else { /* * The initial thread is the current thread. It is * assumed that the current thread is already initialized * because it is left over from a fork(). */ _thr_initial = curthread; } _kse_initial->k_kseg->kg_threadcount = 0; _thr_initial->kse = _kse_initial; _thr_initial->kseg = _kse_initial->k_kseg; _thr_initial->active = 1; /* * Add the thread to the thread list and to the KSEG's thread * queue. */ THR_LIST_ADD(_thr_initial); KSEG_THRQ_ADD(_kse_initial->k_kseg, _thr_initial); /* Setup the KSE/thread specific data for the current KSE/thread. */ _thr_initial->kse->k_curthread = _thr_initial; _kcb_set(_thr_initial->kse->k_kcb); _tcb_set(_thr_initial->kse->k_kcb, _thr_initial->tcb); _thr_initial->kse->k_flags |= KF_INITIALIZED; _thr_signal_init(); _kse_critical_leave(&_thr_initial->tcb->tcb_tmbx); /* * activate threaded mode as soon as possible if we are * being debugged */ if (_libkse_debug) _kse_setthreaded(1); } /* * This function and pthread_create() do a lot of the same things. * It'd be nice to consolidate the common stuff in one place. */ static void init_main_thread(struct pthread *thread) { /* Setup the thread attributes. */ thread->attr = _pthread_attr_default; thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; /* * Set up the thread stack. * * Create a red zone below the main stack. All other stacks * are constrained to a maximum size by the parameters * passed to mmap(), but this stack is only limited by * resource limits, so this stack needs an explicitly mapped * red zone to protect the thread stack that is just beyond. */ - if (mmap((void *)_usrstack - _thr_stack_initial - - _thr_guard_default, _thr_guard_default, 0, MAP_ANON, + if (mmap((void *)((uintptr_t)_usrstack - _thr_stack_initial - + _thr_guard_default), _thr_guard_default, 0, MAP_ANON, -1, 0) == MAP_FAILED) PANIC("Cannot allocate red zone for initial thread"); /* * Mark the stack as an application supplied stack so that it * isn't deallocated. * * XXX - I'm not sure it would hurt anything to deallocate * the main thread stack because deallocation doesn't * actually free() it; it just puts it in the free * stack queue for later reuse. */ - thread->attr.stackaddr_attr = (void *)_usrstack - _thr_stack_initial; + thread->attr.stackaddr_attr = (void *)((uintptr_t)_usrstack - + _thr_stack_initial); thread->attr.stacksize_attr = _thr_stack_initial; thread->attr.guardsize_attr = _thr_guard_default; thread->attr.flags |= THR_STACK_USER; /* * Write a magic value to the thread structure * to help identify valid ones: */ thread->magic = THR_MAGIC; thread->slice_usec = -1; thread->cancelflags = PTHREAD_CANCEL_ENABLE | PTHREAD_CANCEL_DEFERRED; thread->name = strdup("initial thread"); /* Initialize the thread for signals: */ SIGEMPTYSET(thread->sigmask); /* * Set up the thread mailbox. The threads saved context * is also in the mailbox. */ thread->tcb->tcb_tmbx.tm_udata = thread; thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_size = thread->attr.stacksize_attr; thread->tcb->tcb_tmbx.tm_context.uc_stack.ss_sp = thread->attr.stackaddr_attr; /* Default the priority of the initial thread: */ thread->base_priority = THR_DEFAULT_PRIORITY; thread->active_priority = THR_DEFAULT_PRIORITY; thread->inherited_priority = 0; /* Initialize the mutex queue: */ TAILQ_INIT(&thread->mutexq); /* Initialize hooks in the thread structure: */ thread->specific = NULL; thread->cleanup = NULL; thread->flags = 0; thread->sigbackout = NULL; thread->continuation = NULL; thread->state = PS_RUNNING; thread->uniqueid = 0; } static void init_private(void) { struct clockinfo clockinfo; size_t len; int mib[2]; /* * Avoid reinitializing some things if they don't need to be, * e.g. after a fork(). */ if (init_once == 0) { /* Find the stack top */ mib[0] = CTL_KERN; mib[1] = KERN_USRSTACK; len = sizeof (_usrstack); if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1) PANIC("Cannot get kern.usrstack from sysctl"); /* 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_usec = 1000000 / clockinfo.stathz; else _clock_res_usec = CLOCK_RES_USEC; _thr_page_size = getpagesize(); _thr_guard_default = _thr_page_size; if (sizeof(void *) == 8) { _thr_stack_default = THR_STACK64_DEFAULT; _thr_stack_initial = THR_STACK64_INITIAL; } else { _thr_stack_default = THR_STACK32_DEFAULT; _thr_stack_initial = THR_STACK32_INITIAL; } _pthread_attr_default.guardsize_attr = _thr_guard_default; _pthread_attr_default.stacksize_attr = _thr_stack_default; TAILQ_INIT(&_thr_atfork_list); init_once = 1; /* Don't do this again. */ } else { /* * Destroy the locks before creating them. We don't * know what state they are in so it is better to just * recreate them. */ _lock_destroy(&_thread_signal_lock); _lock_destroy(&_mutex_static_lock); _lock_destroy(&_rwlock_static_lock); _lock_destroy(&_keytable_lock); } /* Initialize everything else. */ TAILQ_INIT(&_thread_list); TAILQ_INIT(&_thread_gc_list); _pthread_mutex_init(&_thr_atfork_mutex, NULL); /* * Initialize the lock for temporary installation of signal * handlers (to support sigwait() semantics) and for the * process signal mask and pending signal sets. */ if (_lock_init(&_thread_signal_lock, LCK_ADAPTIVE, _kse_lock_wait, _kse_lock_wakeup, calloc) != 0) PANIC("Cannot initialize _thread_signal_lock"); if (_lock_init(&_mutex_static_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) PANIC("Cannot initialize mutex static init lock"); if (_lock_init(&_rwlock_static_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) PANIC("Cannot initialize rwlock static init lock"); if (_lock_init(&_keytable_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) PANIC("Cannot initialize thread specific keytable lock"); _thr_spinlock_init(); /* Clear pending signals and get the process signal mask. */ SIGEMPTYSET(_thr_proc_sigpending); /* Are we in M:N mode (default) or 1:1 mode? */ #ifdef SYSTEM_SCOPE_ONLY _thread_scope_system = 1; #else if (getenv("LIBPTHREAD_SYSTEM_SCOPE") != NULL) _thread_scope_system = 1; else if (getenv("LIBPTHREAD_PROCESS_SCOPE") != NULL) _thread_scope_system = -1; #endif if (getenv("LIBPTHREAD_DEBUG") != NULL) _thr_debug_flags |= DBG_INFO_DUMP; /* * _thread_list_lock and _kse_count are initialized * by _kse_init() */ } Index: head/lib/libkse/thread/thr_join.c =================================================================== --- head/lib/libkse/thread/thr_join.c (revision 174111) +++ head/lib/libkse/thread/thr_join.c (revision 174112) @@ -1,162 +1,165 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_join); LT10_COMPAT_DEFAULT(pthread_join); __weak_reference(_pthread_join, pthread_join); int _pthread_join(pthread_t pthread, void **thread_return) { struct pthread *curthread = _get_curthread(); void *tmp; kse_critical_t crit; int ret = 0; _thr_cancel_enter(curthread); /* Check if the caller has specified an invalid thread: */ if (pthread == NULL || pthread->magic != THR_MAGIC) { /* Invalid thread: */ _thr_cancel_leave(curthread, 1); return (EINVAL); } /* Check if the caller has specified itself: */ if (pthread == curthread) { /* Avoid a deadlock condition: */ _thr_cancel_leave(curthread, 1); return (EDEADLK); } /* * Find the thread in the list of active threads or in the * list of dead threads: */ if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/1)) != 0) { /* Return an error: */ _thr_cancel_leave(curthread, 1); return (ESRCH); } THR_SCHED_LOCK(curthread, pthread); /* Check if this thread has been detached: */ if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) { THR_SCHED_UNLOCK(curthread, pthread); /* Remove the reference and return an error: */ _thr_ref_delete(curthread, pthread); ret = EINVAL; } else { /* Lock the target thread while checking its state. */ if (pthread->state == PS_DEAD) { /* Return the thread's return value: */ tmp = pthread->ret; /* Detach the thread. */ pthread->attr.flags |= PTHREAD_DETACHED; /* Unlock the thread. */ THR_SCHED_UNLOCK(curthread, pthread); /* * Remove the thread from the list of active * threads and add it to the GC list. */ crit = _kse_critical_enter(); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock); THR_LIST_REMOVE(pthread); THR_GCLIST_ADD(pthread); KSE_LOCK_RELEASE(curthread->kse, &_thread_list_lock); _kse_critical_leave(crit); /* Remove the reference. */ _thr_ref_delete(curthread, pthread); if (thread_return != NULL) *thread_return = tmp; } else if (pthread->joiner != NULL) { /* Unlock the thread and remove the reference. */ THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); /* Multiple joiners are not supported. */ ret = ENOTSUP; } else { /* Set the running thread to be the joiner: */ pthread->joiner = curthread; /* Keep track of which thread we're joining to: */ curthread->join_status.thread = pthread; /* Unlock the thread and remove the reference. */ THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); THR_SCHED_LOCK(curthread, curthread); while (curthread->join_status.thread == pthread) { THR_SET_STATE(curthread, PS_JOIN); THR_SCHED_UNLOCK(curthread, curthread); /* Schedule the next thread: */ _thr_sched_switch(curthread); THR_SCHED_LOCK(curthread, curthread); } THR_SCHED_UNLOCK(curthread, curthread); if ((curthread->cancelflags & THR_CANCELLING) && !(curthread->cancelflags & PTHREAD_CANCEL_DISABLE)) { if (_thr_ref_add(curthread, pthread, 1) == 0) { THR_SCHED_LOCK(curthread, pthread); pthread->joiner = NULL; THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); } - pthread_exit(PTHREAD_CANCELED); + _pthread_exit(PTHREAD_CANCELED); } /* * The thread return value and error are set by the * thread we're joining to when it exits or detaches: */ ret = curthread->join_status.error; if ((ret == 0) && (thread_return != NULL)) *thread_return = curthread->join_status.ret; } } _thr_cancel_leave(curthread, 1); /* Return the completion status: */ return (ret); } Index: head/lib/libkse/thread/thr_kill.c =================================================================== --- head/lib/libkse/thread/thr_kill.c (revision 174111) +++ head/lib/libkse/thread/thr_kill.c (revision 174112) @@ -1,66 +1,69 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_kill); LT10_COMPAT_DEFAULT(pthread_kill); __weak_reference(_pthread_kill, pthread_kill); int _pthread_kill(pthread_t pthread, int sig) { struct pthread *curthread = _get_curthread(); int ret; /* Check for invalid signal numbers: */ if (sig < 0 || sig > _SIG_MAXSIG) /* Invalid signal: */ ret = EINVAL; /* * 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 = _thr_ref_add(curthread, pthread, /*include dead*/0)) == 0) { if ((sig > 0) && (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) _thr_sig_send(pthread, sig); _thr_ref_delete(curthread, pthread); } /* Return the completion status: */ return (ret); } Index: head/lib/libkse/thread/thr_main_np.c =================================================================== --- head/lib/libkse/thread/thr_main_np.c (revision 174111) +++ head/lib/libkse/thread/thr_main_np.c (revision 174112) @@ -1,50 +1,52 @@ /* * Copyright (c) 2001 Alfred Perlstein * Author: Alfred Perlstein * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_main_np); LT10_COMPAT_DEFAULT(pthread_main_np); __weak_reference(_pthread_main_np, pthread_main_np); /* * Provide the equivelant to Solaris thr_main() function */ int _pthread_main_np() { if (!_thr_initial) return (-1); else - return (pthread_equal(pthread_self(), _thr_initial) ? 1 : 0); + return (_pthread_equal(_pthread_self(), _thr_initial) ? 1 : 0); } Index: head/lib/libkse/thread/thr_mattr_init.c =================================================================== --- head/lib/libkse/thread/thr_mattr_init.c (revision 174111) +++ head/lib/libkse/thread/thr_mattr_init.c (revision 174112) @@ -1,61 +1,64 @@ /* * Copyright (c) 1996 Jeffrey Hsu . * 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_mutexattr_init); LT10_COMPAT_DEFAULT(pthread_mutexattr_init); __weak_reference(_pthread_mutexattr_init, pthread_mutexattr_init); int _pthread_mutexattr_init(pthread_mutexattr_t *attr) { int ret; pthread_mutexattr_t pattr; if ((pattr = (pthread_mutexattr_t) malloc(sizeof(struct pthread_mutex_attr))) == NULL) { ret = ENOMEM; } else { memcpy(pattr, &_pthread_mutexattr_default, sizeof(struct pthread_mutex_attr)); *attr = pattr; ret = 0; } return (ret); } Index: head/lib/libkse/thread/thr_mattr_kind_np.c =================================================================== --- head/lib/libkse/thread/thr_mattr_kind_np.c (revision 174111) +++ head/lib/libkse/thread/thr_mattr_kind_np.c (revision 174112) @@ -1,103 +1,109 @@ /* * Copyright (c) 1996 Jeffrey Hsu . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_mutexattr_setkind_np); LT10_COMPAT_DEFAULT(pthread_mutexattr_setkind_np); LT10_COMPAT_PRIVATE(_pthread_mutexattr_getkind_np); LT10_COMPAT_DEFAULT(pthread_mutexattr_getkind_np); LT10_COMPAT_PRIVATE(_pthread_mutexattr_gettype); LT10_COMPAT_DEFAULT(pthread_mutexattr_gettype); LT10_COMPAT_PRIVATE(_pthread_mutexattr_settype); LT10_COMPAT_DEFAULT(pthread_mutexattr_settype); + +int _pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind); +int _pthread_mutexattr_getkind_np(pthread_mutexattr_t attr); __weak_reference(_pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np); __weak_reference(_pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np); __weak_reference(_pthread_mutexattr_gettype, pthread_mutexattr_gettype); __weak_reference(_pthread_mutexattr_settype, pthread_mutexattr_settype); int _pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) { int ret; if (attr == NULL || *attr == NULL) { errno = EINVAL; ret = -1; } else { (*attr)->m_type = kind; ret = 0; } return(ret); } int _pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) { int ret; if (attr == NULL) { errno = EINVAL; ret = -1; } else { ret = attr->m_type; } return(ret); } int _pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { int ret; if (attr == NULL || *attr == NULL || type >= PTHREAD_MUTEX_TYPE_MAX) { errno = EINVAL; ret = -1; } else { (*attr)->m_type = type; ret = 0; } return(ret); } int _pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *type) { int ret; if (attr == NULL || *attr == NULL || (*attr)->m_type >= PTHREAD_MUTEX_TYPE_MAX) { ret = EINVAL; } else { *type = (*attr)->m_type; ret = 0; } return ret; } Index: head/lib/libkse/thread/thr_mattr_pshared.c =================================================================== --- head/lib/libkse/thread/thr_mattr_pshared.c (revision 174111) +++ head/lib/libkse/thread/thr_mattr_pshared.c (revision 174112) @@ -1,56 +1,63 @@ /* * Copyright (c) 2005 David Xu * 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 unmodified, 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ * */ +#include "namespace.h" #include +#include "un-namespace.h" #include "thr_private.h" + +int _pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, + int *pshared); +int _pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); + __weak_reference(_pthread_mutexattr_getpshared, pthread_mutexattr_getpshared); __weak_reference(_pthread_mutexattr_setpshared, pthread_mutexattr_setpshared); int _pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); pshared = PTHREAD_PROCESS_PRIVATE; return (0); } int _pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); if (pshared != PTHREAD_PROCESS_PRIVATE) return (EINVAL); return (0); } Index: head/lib/libkse/thread/thr_msync.c =================================================================== --- head/lib/libkse/thread/thr_msync.c (revision 174111) +++ head/lib/libkse/thread/thr_msync.c (revision 174112) @@ -1,36 +1,40 @@ /* * David Leonard , 1999. Public Domain. * * $OpenBSD: uthread_msync.c,v 1.2 1999/06/09 07:16:17 d Exp $ * * $FreeBSD$ */ +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__msync); LT10_COMPAT_DEFAULT(msync); +int __msync(void *addr, size_t len, int flags); + __weak_reference(__msync, msync); int __msync(void *addr, size_t len, int flags) { struct pthread *curthread = _get_curthread(); 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. */ _thr_cancel_enter(curthread); ret = __sys_msync(addr, len, flags); _thr_cancel_leave(curthread, 1); - return ret; + return (ret); } Index: head/lib/libkse/thread/thr_multi_np.c =================================================================== --- head/lib/libkse/thread/thr_multi_np.c (revision 174111) +++ head/lib/libkse/thread/thr_multi_np.c (revision 174112) @@ -1,52 +1,54 @@ /* * Copyright (c) 1996 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include - +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_multi_np); LT10_COMPAT_DEFAULT(pthread_multi_np); __weak_reference(_pthread_multi_np, pthread_multi_np); int _pthread_multi_np() { /* Return to multi-threaded scheduling mode: */ /* * XXX - Do we want to do this? * __is_threaded = 1; */ - pthread_resume_all_np(); + _pthread_resume_all_np(); return (0); } Index: head/lib/libkse/thread/thr_mutex.c =================================================================== --- head/lib/libkse/thread/thr_mutex.c (revision 174111) +++ head/lib/libkse/thread/thr_mutex.c (revision 174112) @@ -1,1855 +1,1868 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_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) #define THR_ASSERT_NOT_IN_SYNCQ(thr) do { \ THR_ASSERT(((thr)->sflags & THR_FLAGS_IN_SYNCQ) == 0, \ "thread in syncq when it shouldn't be."); \ } while (0); #else #define MUTEX_INIT_LINK(m) #define MUTEX_ASSERT_IS_OWNED(m) #define MUTEX_ASSERT_NOT_OWNED(m) #define THR_ASSERT_NOT_IN_SYNCQ(thr) #endif #define THR_IN_MUTEXQ(thr) (((thr)->sflags & THR_FLAGS_IN_SYNCQ) != 0) #define MUTEX_DESTROY(m) do { \ _lock_destroy(&(m)->m_lock); \ free(m); \ } while (0) /* * Prototypes */ static struct kse_mailbox *mutex_handoff(struct pthread *, struct pthread_mutex *); -static inline int mutex_self_trylock(struct pthread *, pthread_mutex_t); +static inline int mutex_self_trylock(pthread_mutex_t); static inline int mutex_self_lock(struct pthread *, pthread_mutex_t); static int mutex_unlock_common(pthread_mutex_t *, int); static void mutex_priority_adjust(struct pthread *, pthread_mutex_t); static void mutex_rescan_owned (struct pthread *, struct pthread *, struct pthread_mutex *); static inline pthread_t mutex_queue_deq(pthread_mutex_t); static inline void mutex_queue_remove(pthread_mutex_t, pthread_t); static inline void mutex_queue_enq(pthread_mutex_t, pthread_t); static void mutex_lock_backout(void *arg); +int __pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutex_attr); +int __pthread_mutex_trylock(pthread_mutex_t *mutex); +int __pthread_mutex_lock(pthread_mutex_t *m); +int __pthread_mutex_timedlock(pthread_mutex_t *m, + const struct timespec *abs_timeout); +int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, + void *(calloc_cb)(size_t, size_t)); + + static struct pthread_mutex_attr static_mutex_attr = PTHREAD_MUTEXATTR_STATIC_INITIALIZER; static pthread_mutexattr_t static_mattr = &static_mutex_attr; LT10_COMPAT_PRIVATE(__pthread_mutex_init); LT10_COMPAT_PRIVATE(_pthread_mutex_init); LT10_COMPAT_DEFAULT(pthread_mutex_init); LT10_COMPAT_PRIVATE(__pthread_mutex_lock); LT10_COMPAT_PRIVATE(_pthread_mutex_lock); LT10_COMPAT_DEFAULT(pthread_mutex_lock); LT10_COMPAT_PRIVATE(__pthread_mutex_timedlock); LT10_COMPAT_PRIVATE(_pthread_mutex_timedlock); LT10_COMPAT_DEFAULT(pthread_mutex_timedlock); LT10_COMPAT_PRIVATE(__pthread_mutex_trylock); LT10_COMPAT_PRIVATE(_pthread_mutex_trylock); LT10_COMPAT_DEFAULT(pthread_mutex_trylock); LT10_COMPAT_PRIVATE(_pthread_mutex_destroy); LT10_COMPAT_DEFAULT(pthread_mutex_destroy); LT10_COMPAT_PRIVATE(_pthread_mutex_unlock); LT10_COMPAT_DEFAULT(pthread_mutex_unlock); /* Single underscore versions provided for libc internal usage: */ __weak_reference(__pthread_mutex_init, pthread_mutex_init); __weak_reference(__pthread_mutex_lock, pthread_mutex_lock); __weak_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock); __weak_reference(__pthread_mutex_trylock, pthread_mutex_trylock); /* No difference between libc and application usage of these: */ __weak_reference(_pthread_mutex_destroy, pthread_mutex_destroy); __weak_reference(_pthread_mutex_unlock, pthread_mutex_unlock); static int thr_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr, void *(calloc_cb)(size_t, size_t)) { struct pthread_mutex *pmutex; enum pthread_mutextype type; int protocol; int ceiling; int flags; int ret = 0; if (mutex == NULL) ret = EINVAL; /* Check if default mutex attributes: */ else if (mutex_attr == NULL || *mutex_attr == NULL) { /* Default to a (error checking) POSIX mutex: */ type = PTHREAD_MUTEX_ERRORCHECK; protocol = PTHREAD_PRIO_NONE; ceiling = THR_MAX_PRIORITY; flags = 0; } /* Check mutex type: */ else if (((*mutex_attr)->m_type < PTHREAD_MUTEX_ERRORCHECK) || ((*mutex_attr)->m_type >= PTHREAD_MUTEX_TYPE_MAX)) /* Return an invalid argument error: */ ret = EINVAL; /* Check mutex protocol: */ else if (((*mutex_attr)->m_protocol < PTHREAD_PRIO_NONE) || ((*mutex_attr)->m_protocol > PTHREAD_MUTEX_RECURSIVE)) /* Return an invalid argument error: */ ret = EINVAL; else { /* Use the requested mutex type and protocol: */ type = (*mutex_attr)->m_type; protocol = (*mutex_attr)->m_protocol; ceiling = (*mutex_attr)->m_ceiling; flags = (*mutex_attr)->m_flags; } /* Check no errors so far: */ if (ret == 0) { if ((pmutex = (pthread_mutex_t) calloc_cb(1, sizeof(struct pthread_mutex))) == NULL) ret = ENOMEM; else if (_lock_init(&pmutex->m_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc_cb) != 0) { free(pmutex); *mutex = NULL; ret = ENOMEM; } else { /* Set the mutex flags: */ pmutex->m_flags = flags; /* Process according to mutex type: */ switch (type) { /* case PTHREAD_MUTEX_DEFAULT: */ case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_ADAPTIVE_NP: /* Nothing to do here. */ break; /* Single UNIX Spec 2 recursive mutex: */ case PTHREAD_MUTEX_RECURSIVE: /* Reset the mutex count: */ pmutex->m_count = 0; break; /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ ret = EINVAL; break; } if (ret == 0) { /* Initialise the rest of the mutex: */ TAILQ_INIT(&pmutex->m_queue); pmutex->m_flags |= MUTEX_FLAGS_INITED; pmutex->m_owner = NULL; pmutex->m_type = type; pmutex->m_protocol = protocol; pmutex->m_refcount = 0; if (protocol == PTHREAD_PRIO_PROTECT) pmutex->m_prio = ceiling; else pmutex->m_prio = -1; pmutex->m_saved_prio = 0; MUTEX_INIT_LINK(pmutex); *mutex = pmutex; } else { /* Free the mutex lock structure: */ MUTEX_DESTROY(pmutex); *mutex = NULL; } } } /* Return the completion status: */ return (ret); } int __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr) { return (thr_mutex_init(mutex, mutex_attr, calloc)); } int _pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr) { struct pthread_mutex_attr mattr, *mattrp; if ((mutex_attr == NULL) || (*mutex_attr == NULL)) return (__pthread_mutex_init(mutex, &static_mattr)); else { mattr = **mutex_attr; mattr.m_flags |= MUTEX_FLAGS_PRIVATE; mattrp = &mattr; return (__pthread_mutex_init(mutex, &mattrp)); } } /* This function is used internally by malloc. */ int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, void *(calloc_cb)(size_t, size_t)) { static const struct pthread_mutex_attr attr = { .m_type = PTHREAD_MUTEX_NORMAL, .m_protocol = PTHREAD_PRIO_NONE, .m_ceiling = 0, .m_flags = 0 }; static const struct pthread_mutex_attr *pattr = &attr; return (thr_mutex_init(mutex, (pthread_mutexattr_t *)&pattr, calloc_cb)); } void _thr_mutex_reinit(pthread_mutex_t *mutex) { _lock_reinit(&(*mutex)->m_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup); TAILQ_INIT(&(*mutex)->m_queue); (*mutex)->m_owner = NULL; (*mutex)->m_count = 0; (*mutex)->m_refcount = 0; (*mutex)->m_prio = 0; (*mutex)->m_saved_prio = 0; } int _pthread_mutex_destroy(pthread_mutex_t *mutex) { struct pthread *curthread = _get_curthread(); pthread_mutex_t m; int ret = 0; if (mutex == NULL || *mutex == NULL) ret = EINVAL; else { /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &(*mutex)->m_lock); /* * Check to see if this mutex is in use: */ if (((*mutex)->m_owner != NULL) || (!TAILQ_EMPTY(&(*mutex)->m_queue)) || ((*mutex)->m_refcount != 0)) { ret = EBUSY; /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*mutex)->m_lock); } else { /* * Save a pointer to the mutex so it can be free'd * and set the caller's pointer to NULL: */ m = *mutex; *mutex = NULL; /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &m->m_lock); /* * Free the memory allocated for the mutex * structure: */ MUTEX_ASSERT_NOT_OWNED(m); MUTEX_DESTROY(m); } } /* Return the completion status: */ return (ret); } static int init_static(struct pthread *thread, pthread_mutex_t *mutex) { int ret; THR_LOCK_ACQUIRE(thread, &_mutex_static_lock); if (*mutex == NULL) - ret = pthread_mutex_init(mutex, NULL); + ret = _pthread_mutex_init(mutex, NULL); else ret = 0; THR_LOCK_RELEASE(thread, &_mutex_static_lock); return (ret); } static int init_static_private(struct pthread *thread, pthread_mutex_t *mutex) { int ret; THR_LOCK_ACQUIRE(thread, &_mutex_static_lock); if (*mutex == NULL) - ret = pthread_mutex_init(mutex, &static_mattr); + ret = _pthread_mutex_init(mutex, &static_mattr); else ret = 0; THR_LOCK_RELEASE(thread, &_mutex_static_lock); return (ret); } static int mutex_trylock_common(struct pthread *curthread, pthread_mutex_t *mutex) { int private; int ret = 0; THR_ASSERT((mutex != NULL) && (*mutex != NULL), "Uninitialized mutex in pthread_mutex_trylock_basic"); /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &(*mutex)->m_lock); private = (*mutex)->m_flags & MUTEX_FLAGS_PRIVATE; /* * 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; } /* Process according to mutex type: */ switch ((*mutex)->m_protocol) { /* Default POSIX mutex: */ case PTHREAD_PRIO_NONE: /* Check if this mutex is not locked: */ if ((*mutex)->m_owner == NULL) { /* Lock the mutex for the running thread: */ (*mutex)->m_owner = curthread; /* Add to the list of owned mutexes: */ MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&curthread->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == curthread) - ret = mutex_self_trylock(curthread, *mutex); + ret = mutex_self_trylock(*mutex); else /* Return a busy error: */ ret = EBUSY; break; /* POSIX priority inheritence mutex: */ case PTHREAD_PRIO_INHERIT: /* Check if this mutex is not locked: */ if ((*mutex)->m_owner == NULL) { /* Lock the mutex for the running thread: */ (*mutex)->m_owner = curthread; THR_SCHED_LOCK(curthread, curthread); /* Track number of priority mutexes owned: */ curthread->priority_mutex_count++; /* * The mutex takes on the attributes of the * running thread when there are no waiters. */ (*mutex)->m_prio = curthread->active_priority; (*mutex)->m_saved_prio = curthread->inherited_priority; curthread->inherited_priority = (*mutex)->m_prio; THR_SCHED_UNLOCK(curthread, curthread); /* Add to the list of owned mutexes: */ MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&curthread->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == curthread) - ret = mutex_self_trylock(curthread, *mutex); + ret = mutex_self_trylock(*mutex); else /* Return a busy error: */ ret = EBUSY; break; /* POSIX priority protection mutex: */ case PTHREAD_PRIO_PROTECT: /* Check for a priority ceiling violation: */ if (curthread->active_priority > (*mutex)->m_prio) ret = EINVAL; /* Check if this mutex is not locked: */ else if ((*mutex)->m_owner == NULL) { /* Lock the mutex for the running thread: */ (*mutex)->m_owner = curthread; THR_SCHED_LOCK(curthread, curthread); /* Track number of priority mutexes owned: */ curthread->priority_mutex_count++; /* * The running thread inherits the ceiling * priority of the mutex and executes at that * priority. */ curthread->active_priority = (*mutex)->m_prio; (*mutex)->m_saved_prio = curthread->inherited_priority; curthread->inherited_priority = (*mutex)->m_prio; THR_SCHED_UNLOCK(curthread, curthread); /* Add to the list of owned mutexes: */ MUTEX_ASSERT_NOT_OWNED(*mutex); TAILQ_INSERT_TAIL(&curthread->mutexq, (*mutex), m_qe); } else if ((*mutex)->m_owner == curthread) - ret = mutex_self_trylock(curthread, *mutex); + ret = mutex_self_trylock(*mutex); else /* Return a busy error: */ ret = EBUSY; break; /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ ret = EINVAL; break; } if (ret == 0 && private) THR_CRITICAL_ENTER(curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*mutex)->m_lock); /* Return the completion status: */ return (ret); } int __pthread_mutex_trylock(pthread_mutex_t *mutex) { struct pthread *curthread = _get_curthread(); int ret = 0; if (mutex == NULL) ret = EINVAL; /* * If the mutex is statically initialized, perform the dynamic * initialization: */ else if ((*mutex != NULL) || ((ret = init_static(curthread, mutex)) == 0)) ret = mutex_trylock_common(curthread, mutex); return (ret); } int _pthread_mutex_trylock(pthread_mutex_t *mutex) { struct pthread *curthread = _get_curthread(); int ret = 0; if (mutex == NULL) ret = EINVAL; /* * If the mutex is statically initialized, perform the dynamic * initialization marking the mutex private (delete safe): */ else if ((*mutex != NULL) || ((ret = init_static_private(curthread, mutex)) == 0)) ret = mutex_trylock_common(curthread, mutex); return (ret); } static int mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m, const struct timespec * abstime) { int private; int ret = 0; THR_ASSERT((m != NULL) && (*m != NULL), "Uninitialized mutex in pthread_mutex_trylock_basic"); if (abstime != NULL && (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) return (EINVAL); /* Reset the interrupted flag: */ curthread->interrupted = 0; curthread->timeout = 0; curthread->wakeup_time.tv_sec = -1; private = (*m)->m_flags & MUTEX_FLAGS_PRIVATE; /* * Enter a loop waiting to become the mutex owner. We need a * loop in case the waiting thread is interrupted by a signal * to execute a signal handler. It is not (currently) possible * to remain in the waiting queue while running a handler. * Instead, the thread is interrupted and backed out of the * waiting queue prior to executing the signal handler. */ do { /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); /* * If the mutex was statically allocated, properly * initialize the tail queue. */ if (((*m)->m_flags & MUTEX_FLAGS_INITED) == 0) { TAILQ_INIT(&(*m)->m_queue); (*m)->m_flags |= MUTEX_FLAGS_INITED; MUTEX_INIT_LINK(*m); } /* Process according to mutex type: */ switch ((*m)->m_protocol) { /* Default POSIX mutex: */ case PTHREAD_PRIO_NONE: if ((*m)->m_owner == NULL) { /* Lock the mutex for this thread: */ (*m)->m_owner = curthread; /* Add to the list of owned mutexes: */ MUTEX_ASSERT_NOT_OWNED(*m); TAILQ_INSERT_TAIL(&curthread->mutexq, (*m), m_qe); if (private) THR_CRITICAL_ENTER(curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else if ((*m)->m_owner == curthread) { ret = mutex_self_lock(curthread, *m); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else { /* * Join the queue of threads waiting to lock * the mutex and save a pointer to the mutex. */ mutex_queue_enq(*m, curthread); curthread->data.mutex = *m; curthread->sigbackout = mutex_lock_backout; /* * This thread is active and is in a critical * region (holding the mutex lock); we should * be able to safely set the state. */ THR_SCHED_LOCK(curthread, curthread); /* Set the wakeup time: */ if (abstime) { curthread->wakeup_time.tv_sec = abstime->tv_sec; curthread->wakeup_time.tv_nsec = abstime->tv_nsec; } THR_SET_STATE(curthread, PS_MUTEX_WAIT); THR_SCHED_UNLOCK(curthread, curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); /* Schedule the next thread: */ _thr_sched_switch(curthread); if (THR_IN_MUTEXQ(curthread)) { THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); mutex_queue_remove(*m, curthread); THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } /* * Only clear these after assuring the * thread is dequeued. */ curthread->data.mutex = NULL; curthread->sigbackout = NULL; } break; /* POSIX priority inheritence mutex: */ case PTHREAD_PRIO_INHERIT: /* Check if this mutex is not locked: */ if ((*m)->m_owner == NULL) { /* Lock the mutex for this thread: */ (*m)->m_owner = curthread; THR_SCHED_LOCK(curthread, curthread); /* Track number of priority mutexes owned: */ curthread->priority_mutex_count++; /* * The mutex takes on attributes of the * running thread when there are no waiters. * Make sure the thread's scheduling lock is * held while priorities are adjusted. */ (*m)->m_prio = curthread->active_priority; (*m)->m_saved_prio = curthread->inherited_priority; curthread->inherited_priority = (*m)->m_prio; THR_SCHED_UNLOCK(curthread, curthread); /* Add to the list of owned mutexes: */ MUTEX_ASSERT_NOT_OWNED(*m); TAILQ_INSERT_TAIL(&curthread->mutexq, (*m), m_qe); if (private) THR_CRITICAL_ENTER(curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else if ((*m)->m_owner == curthread) { ret = mutex_self_lock(curthread, *m); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else { /* * Join the queue of threads waiting to lock * the mutex and save a pointer to the mutex. */ mutex_queue_enq(*m, curthread); curthread->data.mutex = *m; curthread->sigbackout = mutex_lock_backout; /* * This thread is active and is in a critical * region (holding the mutex lock); we should * be able to safely set the state. */ if (curthread->active_priority > (*m)->m_prio) /* Adjust priorities: */ mutex_priority_adjust(curthread, *m); THR_SCHED_LOCK(curthread, curthread); /* Set the wakeup time: */ if (abstime) { curthread->wakeup_time.tv_sec = abstime->tv_sec; curthread->wakeup_time.tv_nsec = abstime->tv_nsec; } THR_SET_STATE(curthread, PS_MUTEX_WAIT); THR_SCHED_UNLOCK(curthread, curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); /* Schedule the next thread: */ _thr_sched_switch(curthread); if (THR_IN_MUTEXQ(curthread)) { THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); mutex_queue_remove(*m, curthread); THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } /* * Only clear these after assuring the * thread is dequeued. */ curthread->data.mutex = NULL; curthread->sigbackout = NULL; } break; /* POSIX priority protection mutex: */ case PTHREAD_PRIO_PROTECT: /* Check for a priority ceiling violation: */ if (curthread->active_priority > (*m)->m_prio) { /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); ret = EINVAL; } /* Check if this mutex is not locked: */ else if ((*m)->m_owner == NULL) { /* * Lock the mutex for the running * thread: */ (*m)->m_owner = curthread; THR_SCHED_LOCK(curthread, curthread); /* Track number of priority mutexes owned: */ curthread->priority_mutex_count++; /* * The running thread inherits the ceiling * priority of the mutex and executes at that * priority. Make sure the thread's * scheduling lock is held while priorities * are adjusted. */ curthread->active_priority = (*m)->m_prio; (*m)->m_saved_prio = curthread->inherited_priority; curthread->inherited_priority = (*m)->m_prio; THR_SCHED_UNLOCK(curthread, curthread); /* Add to the list of owned mutexes: */ MUTEX_ASSERT_NOT_OWNED(*m); TAILQ_INSERT_TAIL(&curthread->mutexq, (*m), m_qe); if (private) THR_CRITICAL_ENTER(curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else if ((*m)->m_owner == curthread) { ret = mutex_self_lock(curthread, *m); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } else { /* * Join the queue of threads waiting to lock * the mutex and save a pointer to the mutex. */ mutex_queue_enq(*m, curthread); curthread->data.mutex = *m; curthread->sigbackout = mutex_lock_backout; /* Clear any previous error: */ curthread->error = 0; /* * This thread is active and is in a critical * region (holding the mutex lock); we should * be able to safely set the state. */ THR_SCHED_LOCK(curthread, curthread); /* Set the wakeup time: */ if (abstime) { curthread->wakeup_time.tv_sec = abstime->tv_sec; curthread->wakeup_time.tv_nsec = abstime->tv_nsec; } THR_SET_STATE(curthread, PS_MUTEX_WAIT); THR_SCHED_UNLOCK(curthread, curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); /* Schedule the next thread: */ _thr_sched_switch(curthread); if (THR_IN_MUTEXQ(curthread)) { THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); mutex_queue_remove(*m, curthread); THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } /* * Only clear these after assuring the * thread is dequeued. */ curthread->data.mutex = NULL; curthread->sigbackout = NULL; /* * The threads priority may have changed while * waiting for the mutex causing a ceiling * violation. */ ret = curthread->error; curthread->error = 0; } break; /* Trap invalid mutex types: */ default: /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); /* Return an invalid argument error: */ ret = EINVAL; break; } } while (((*m)->m_owner != curthread) && (ret == 0) && (curthread->interrupted == 0) && (curthread->timeout == 0)); if (ret == 0 && (*m)->m_owner != curthread && curthread->timeout) ret = ETIMEDOUT; /* * Check to see if this thread was interrupted and * is still in the mutex queue of waiting threads: */ if (curthread->interrupted != 0) { /* Remove this thread from the mutex queue. */ THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); if (THR_IN_SYNCQ(curthread)) mutex_queue_remove(*m, curthread); THR_LOCK_RELEASE(curthread, &(*m)->m_lock); /* Check for asynchronous cancellation. */ if (curthread->continuation != NULL) curthread->continuation((void *) curthread); } /* Return the completion status: */ return (ret); } int __pthread_mutex_lock(pthread_mutex_t *m) { struct pthread *curthread; int ret = 0; if (_thr_initial == NULL) _libpthread_init(NULL); curthread = _get_curthread(); if (m == NULL) ret = EINVAL; /* * If the mutex is statically initialized, perform the dynamic * initialization: */ else if ((*m != NULL) || ((ret = init_static(curthread, m)) == 0)) ret = mutex_lock_common(curthread, m, NULL); return (ret); } __strong_reference(__pthread_mutex_lock, _thr_mutex_lock); int _pthread_mutex_lock(pthread_mutex_t *m) { struct pthread *curthread; int ret = 0; if (_thr_initial == NULL) _libpthread_init(NULL); curthread = _get_curthread(); if (m == NULL) ret = EINVAL; /* * If the mutex is statically initialized, perform the dynamic * initialization marking it private (delete safe): */ else if ((*m != NULL) || ((ret = init_static_private(curthread, m)) == 0)) ret = mutex_lock_common(curthread, m, NULL); return (ret); } int __pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *abs_timeout) { struct pthread *curthread; int ret = 0; if (_thr_initial == NULL) _libpthread_init(NULL); curthread = _get_curthread(); if (m == NULL) ret = EINVAL; /* * If the mutex is statically initialized, perform the dynamic * initialization: */ else if ((*m != NULL) || ((ret = init_static(curthread, m)) == 0)) ret = mutex_lock_common(curthread, m, abs_timeout); return (ret); } int _pthread_mutex_timedlock(pthread_mutex_t *m, const struct timespec *abs_timeout) { struct pthread *curthread; int ret = 0; if (_thr_initial == NULL) _libpthread_init(NULL); curthread = _get_curthread(); if (m == NULL) ret = EINVAL; /* * If the mutex is statically initialized, perform the dynamic * initialization marking it private (delete safe): */ else if ((*m != NULL) || ((ret = init_static_private(curthread, m)) == 0)) ret = mutex_lock_common(curthread, m, abs_timeout); return (ret); } int _pthread_mutex_unlock(pthread_mutex_t *m) { return (mutex_unlock_common(m, /* add reference */ 0)); } __strong_reference(_pthread_mutex_unlock, _thr_mutex_unlock); int _mutex_cv_unlock(pthread_mutex_t *m) { return (mutex_unlock_common(m, /* add reference */ 1)); } int _mutex_cv_lock(pthread_mutex_t *m) { struct pthread *curthread; int ret; curthread = _get_curthread(); if ((ret = _pthread_mutex_lock(m)) == 0) { THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); (*m)->m_refcount--; THR_LOCK_RELEASE(curthread, &(*m)->m_lock); } return (ret); } static inline int -mutex_self_trylock(struct pthread *curthread, pthread_mutex_t m) +mutex_self_trylock(pthread_mutex_t m) { int ret = 0; switch (m->m_type) { /* case PTHREAD_MUTEX_DEFAULT: */ case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_ADAPTIVE_NP: ret = EBUSY; break; case PTHREAD_MUTEX_RECURSIVE: /* Increment the lock count: */ m->m_count++; break; default: /* Trap invalid mutex types; */ ret = EINVAL; } return (ret); } static inline int mutex_self_lock(struct pthread *curthread, pthread_mutex_t m) { int ret = 0; /* * Don't allow evil recursive mutexes for private use * in libc and libpthread. */ if (m->m_flags & MUTEX_FLAGS_PRIVATE) PANIC("Recurse on a private mutex."); switch (m->m_type) { /* case PTHREAD_MUTEX_DEFAULT: */ case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_ADAPTIVE_NP: /* * POSIX specifies that mutexes should return EDEADLK if a * recursive lock is detected. */ ret = EDEADLK; break; case PTHREAD_MUTEX_NORMAL: /* * What SS2 define as a 'normal' mutex. Intentionally * deadlock on attempts to get a lock you already own. */ THR_SCHED_LOCK(curthread, curthread); THR_SET_STATE(curthread, PS_DEADLOCK); THR_SCHED_UNLOCK(curthread, curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &m->m_lock); /* Schedule the next thread: */ _thr_sched_switch(curthread); break; case PTHREAD_MUTEX_RECURSIVE: /* Increment the lock count: */ m->m_count++; break; default: /* Trap invalid mutex types; */ ret = EINVAL; } return (ret); } static int mutex_unlock_common(pthread_mutex_t *m, int add_reference) { struct pthread *curthread = _get_curthread(); struct kse_mailbox *kmbx = NULL; int ret = 0; if (m == NULL || *m == NULL) ret = EINVAL; else { /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &(*m)->m_lock); /* Process according to mutex type: */ switch ((*m)->m_protocol) { /* Default POSIX mutex: */ case PTHREAD_PRIO_NONE: /* * Check if the running thread is not the owner of the * mutex: */ if ((*m)->m_owner != curthread) ret = EPERM; else if (((*m)->m_type == PTHREAD_MUTEX_RECURSIVE) && ((*m)->m_count > 0)) /* Decrement the count: */ (*m)->m_count--; else { /* * Clear the count in case this is a recursive * mutex. */ (*m)->m_count = 0; /* Remove the mutex from the threads queue. */ MUTEX_ASSERT_IS_OWNED(*m); TAILQ_REMOVE(&(*m)->m_owner->mutexq, (*m), m_qe); MUTEX_INIT_LINK(*m); /* * Hand off the mutex to the next waiting * thread: */ kmbx = mutex_handoff(curthread, *m); } break; /* POSIX priority inheritence mutex: */ case PTHREAD_PRIO_INHERIT: /* * Check if the running thread is not the owner of the * mutex: */ if ((*m)->m_owner != curthread) ret = EPERM; else if (((*m)->m_type == PTHREAD_MUTEX_RECURSIVE) && ((*m)->m_count > 0)) /* Decrement the count: */ (*m)->m_count--; else { /* * Clear the count in case this is recursive * mutex. */ (*m)->m_count = 0; /* * Restore the threads inherited priority and * recompute the active priority (being careful * not to override changes in the threads base * priority subsequent to locking the mutex). */ THR_SCHED_LOCK(curthread, curthread); curthread->inherited_priority = (*m)->m_saved_prio; curthread->active_priority = MAX(curthread->inherited_priority, curthread->base_priority); /* * This thread now owns one less priority mutex. */ curthread->priority_mutex_count--; THR_SCHED_UNLOCK(curthread, curthread); /* Remove the mutex from the threads queue. */ MUTEX_ASSERT_IS_OWNED(*m); TAILQ_REMOVE(&(*m)->m_owner->mutexq, (*m), m_qe); MUTEX_INIT_LINK(*m); /* * Hand off the mutex to the next waiting * thread: */ kmbx = mutex_handoff(curthread, *m); } break; /* POSIX priority ceiling mutex: */ case PTHREAD_PRIO_PROTECT: /* * Check if the running thread is not the owner of the * mutex: */ if ((*m)->m_owner != curthread) ret = EPERM; else if (((*m)->m_type == PTHREAD_MUTEX_RECURSIVE) && ((*m)->m_count > 0)) /* Decrement the count: */ (*m)->m_count--; else { /* * Clear the count in case this is a recursive * mutex. */ (*m)->m_count = 0; /* * Restore the threads inherited priority and * recompute the active priority (being careful * not to override changes in the threads base * priority subsequent to locking the mutex). */ THR_SCHED_LOCK(curthread, curthread); curthread->inherited_priority = (*m)->m_saved_prio; curthread->active_priority = MAX(curthread->inherited_priority, curthread->base_priority); /* * This thread now owns one less priority mutex. */ curthread->priority_mutex_count--; THR_SCHED_UNLOCK(curthread, curthread); /* Remove the mutex from the threads queue. */ MUTEX_ASSERT_IS_OWNED(*m); TAILQ_REMOVE(&(*m)->m_owner->mutexq, (*m), m_qe); MUTEX_INIT_LINK(*m); /* * Hand off the mutex to the next waiting * thread: */ kmbx = mutex_handoff(curthread, *m); } break; /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ ret = EINVAL; break; } if ((ret == 0) && (add_reference != 0)) /* Increment the reference count: */ (*m)->m_refcount++; /* Leave the critical region if this is a private mutex. */ if ((ret == 0) && ((*m)->m_flags & MUTEX_FLAGS_PRIVATE)) THR_CRITICAL_LEAVE(curthread); /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &(*m)->m_lock); if (kmbx != NULL) kse_wakeup(kmbx); } /* Return the completion status: */ return (ret); } /* * 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 without the target thread's scheduling lock held. */ void _mutex_notify_priochange(struct pthread *curthread, struct pthread *pthread, int propagate_prio) { struct pthread_mutex *m; /* Adjust the priorites of any owned priority mutexes: */ if (pthread->priority_mutex_count > 0) { /* * Rescan the mutexes owned by this thread and correct * their priorities to account for this threads change * in priority. This has the side effect of changing * the threads active priority. * * Be sure to lock the first mutex in the list of owned * mutexes. This acts as a barrier against another * simultaneous call to change the threads priority * and from the owning thread releasing the mutex. */ m = TAILQ_FIRST(&pthread->mutexq); if (m != NULL) { THR_LOCK_ACQUIRE(curthread, &m->m_lock); /* * Make sure the thread still owns the lock. */ if (m == TAILQ_FIRST(&pthread->mutexq)) mutex_rescan_owned(curthread, pthread, /* rescan all owned */ NULL); THR_LOCK_RELEASE(curthread, &m->m_lock); } } /* * If this thread is waiting on a priority inheritence mutex, * check for priority adjustments. A change in priority can * also cause a ceiling violation(*) for a thread waiting on * a priority protection mutex; we don't perform the check here * as it is done in pthread_mutex_unlock. * * (*) It should be noted that a priority change to a thread * _after_ taking and owning a priority ceiling mutex * does not affect ownership of that mutex; the ceiling * priority is only checked before mutex ownership occurs. */ if (propagate_prio != 0) { /* * Lock the thread's scheduling queue. This is a bit * convoluted; the "in synchronization queue flag" can * only be cleared with both the thread's scheduling and * mutex locks held. The thread's pointer to the wanted * mutex is guaranteed to be valid during this time. */ THR_SCHED_LOCK(curthread, pthread); if (((pthread->sflags & THR_FLAGS_IN_SYNCQ) == 0) || ((m = pthread->data.mutex) == NULL)) THR_SCHED_UNLOCK(curthread, pthread); else { /* * This thread is currently waiting on a mutex; unlock * the scheduling queue lock and lock the mutex. We * can't hold both at the same time because the locking * order could cause a deadlock. */ THR_SCHED_UNLOCK(curthread, pthread); THR_LOCK_ACQUIRE(curthread, &m->m_lock); /* * Check to make sure this thread is still in the * same state (the lock above can yield the CPU to * another thread or the thread may be running on * another CPU). */ if (((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) && (pthread->data.mutex == m)) { /* * Remove and reinsert this thread into * the list of waiting threads to preserve * decreasing priority order. */ mutex_queue_remove(m, pthread); mutex_queue_enq(m, pthread); if (m->m_protocol == PTHREAD_PRIO_INHERIT) /* Adjust priorities: */ mutex_priority_adjust(curthread, m); } /* Unlock the mutex structure: */ THR_LOCK_RELEASE(curthread, &m->m_lock); } } } /* * Called when a new thread is added to the mutex waiting queue or * when a threads priority changes that is already in the mutex * waiting queue. * * This must be called with the mutex locked by the current thread. */ static void mutex_priority_adjust(struct pthread *curthread, pthread_mutex_t mutex) { pthread_mutex_t m = mutex; struct pthread *pthread_next, *pthread = mutex->m_owner; int done, temp_prio; /* * Calculate the mutex priority as the maximum of the highest * active priority of any waiting threads and the owning threads * active priority(*). * * (*) Because the owning threads current active priority may * reflect priority inherited from this mutex (and the mutex * priority may have changed) we must recalculate the active * priority based on the threads saved inherited priority * and its base priority. */ pthread_next = TAILQ_FIRST(&m->m_queue); /* should never be NULL */ temp_prio = MAX(pthread_next->active_priority, MAX(m->m_saved_prio, pthread->base_priority)); /* See if this mutex really needs adjusting: */ if (temp_prio == m->m_prio) /* No need to propagate the priority: */ return; /* Set new priority of the mutex: */ m->m_prio = temp_prio; /* * Don't unlock the mutex passed in as an argument. It is * expected to be locked and unlocked by the caller. */ done = 1; do { /* * Save the threads priority before rescanning the * owned mutexes: */ temp_prio = pthread->active_priority; /* * Fix the priorities for all mutexes held by the owning * thread since taking this mutex. This also has a * potential side-effect of changing the threads priority. * * At this point the mutex is locked by the current thread. * The owning thread can't release the mutex until it is * unlocked, so we should be able to safely walk its list * of owned mutexes. */ mutex_rescan_owned(curthread, pthread, m); /* * If this isn't the first time through the loop, * the current mutex needs to be unlocked. */ if (done == 0) THR_LOCK_RELEASE(curthread, &m->m_lock); /* Assume we're done unless told otherwise: */ done = 1; /* * If the thread is currently waiting on a mutex, check * to see if the threads new priority has affected the * priority of the mutex. */ if ((temp_prio != pthread->active_priority) && ((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) && ((m = pthread->data.mutex) != NULL) && (m->m_protocol == PTHREAD_PRIO_INHERIT)) { /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &m->m_lock); /* * Make sure the thread is still waiting on the * mutex: */ if (((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) && (m == pthread->data.mutex)) { /* * The priority for this thread has changed. * Remove and reinsert this thread into the * list of waiting threads to preserve * decreasing priority order. */ mutex_queue_remove(m, pthread); mutex_queue_enq(m, pthread); /* * Grab the waiting thread with highest * priority: */ pthread_next = TAILQ_FIRST(&m->m_queue); /* * Calculate the mutex priority as the maximum * of the highest active priority of any * waiting threads and the owning threads * active priority. */ temp_prio = MAX(pthread_next->active_priority, MAX(m->m_saved_prio, m->m_owner->base_priority)); if (temp_prio != m->m_prio) { /* * The priority needs to be propagated * to the mutex this thread is waiting * on and up to the owner of that mutex. */ m->m_prio = temp_prio; pthread = m->m_owner; /* We're not done yet: */ done = 0; } } /* Only release the mutex if we're done: */ if (done != 0) THR_LOCK_RELEASE(curthread, &m->m_lock); } } while (done == 0); } static void mutex_rescan_owned(struct pthread *curthread, struct pthread *pthread, struct pthread_mutex *mutex) { struct pthread_mutex *m; struct pthread *pthread_next; int active_prio, inherited_prio; /* * Start walking the mutexes the thread has taken since * taking this mutex. */ if (mutex == NULL) { /* * A null mutex means start at the beginning of the owned * mutex list. */ m = TAILQ_FIRST(&pthread->mutexq); /* There is no inherited priority yet. */ inherited_prio = 0; } else { /* * The caller wants to start after a specific mutex. It * is assumed that this mutex is a priority inheritence * mutex and that its priority has been correctly * calculated. */ m = TAILQ_NEXT(mutex, m_qe); /* Start inheriting priority from the specified mutex. */ inherited_prio = mutex->m_prio; } active_prio = MAX(inherited_prio, pthread->base_priority); for (; m != NULL; m = TAILQ_NEXT(m, m_qe)) { /* * We only want to deal with priority inheritence * mutexes. This might be optimized by only placing * priority inheritence mutexes into the owned mutex * list, but it may prove to be useful having all * owned mutexes in this list. Consider a thread * exiting while holding mutexes... */ if (m->m_protocol == PTHREAD_PRIO_INHERIT) { /* * Fix the owners saved (inherited) priority to * reflect the priority of the previous mutex. */ m->m_saved_prio = inherited_prio; if ((pthread_next = TAILQ_FIRST(&m->m_queue)) != NULL) /* Recalculate the priority of the mutex: */ m->m_prio = MAX(active_prio, pthread_next->active_priority); else m->m_prio = active_prio; /* Recalculate new inherited and active priorities: */ inherited_prio = m->m_prio; active_prio = MAX(m->m_prio, pthread->base_priority); } } /* * Fix the threads inherited priority and recalculate its * active priority. */ pthread->inherited_priority = inherited_prio; active_prio = MAX(inherited_prio, pthread->base_priority); if (active_prio != pthread->active_priority) { /* Lock the thread's scheduling queue: */ THR_SCHED_LOCK(curthread, pthread); if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0) { /* * This thread is not in a run queue. Just set * its active priority. */ pthread->active_priority = active_prio; } else { /* * This thread is in a run queue. Remove it from * the queue before changing its priority: */ THR_RUNQ_REMOVE(pthread); /* * POSIX states that if the priority is being * lowered, the thread must be inserted at the * head of the queue for its priority if it owns * any priority protection or inheritence mutexes. */ if ((active_prio < pthread->active_priority) && (pthread->priority_mutex_count > 0)) { /* Set the new active priority. */ pthread->active_priority = active_prio; THR_RUNQ_INSERT_HEAD(pthread); } else { /* Set the new active priority. */ pthread->active_priority = active_prio; THR_RUNQ_INSERT_TAIL(pthread); } } THR_SCHED_UNLOCK(curthread, pthread); } } void _mutex_unlock_private(pthread_t pthread) { struct pthread_mutex *m, *m_next; for (m = TAILQ_FIRST(&pthread->mutexq); m != NULL; m = m_next) { m_next = TAILQ_NEXT(m, m_qe); if ((m->m_flags & MUTEX_FLAGS_PRIVATE) != 0) - pthread_mutex_unlock(&m); + _pthread_mutex_unlock(&m); } } /* * This is called by the current thread when it wants to back out of a * mutex_lock in order to run a signal handler. */ static void mutex_lock_backout(void *arg) { struct pthread *curthread = (struct pthread *)arg; struct pthread_mutex *m; if ((curthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) { /* * Any other thread may clear the "in sync queue flag", * but only the current thread can clear the pointer * to the mutex. So if the flag is set, we can * guarantee that the pointer to the mutex is valid. * The only problem may be if the mutex is destroyed * out from under us, but that should be considered * an application bug. */ m = curthread->data.mutex; /* Lock the mutex structure: */ THR_LOCK_ACQUIRE(curthread, &m->m_lock); /* * Check to make sure this thread doesn't already own * the mutex. Since mutexes are unlocked with direct * handoffs, it is possible the previous owner gave it * to us after we checked the sync queue flag and before * we locked the mutex structure. */ if (m->m_owner == curthread) { THR_LOCK_RELEASE(curthread, &m->m_lock); mutex_unlock_common(&m, /* add_reference */ 0); } else { /* * Remove ourselves from the mutex queue and * clear the pointer to the mutex. We may no * longer be in the mutex queue, but the removal * function will DTRT. */ mutex_queue_remove(m, curthread); curthread->data.mutex = NULL; THR_LOCK_RELEASE(curthread, &m->m_lock); } } /* No need to call this again. */ curthread->sigbackout = NULL; } /* * Dequeue a waiting thread from the head of a mutex queue in descending * priority order. * * In order to properly dequeue a thread from the mutex queue and * make it runnable without the possibility of errant wakeups, it * is necessary to lock the thread's scheduling queue while also * holding the mutex lock. */ static struct kse_mailbox * mutex_handoff(struct pthread *curthread, struct pthread_mutex *mutex) { struct kse_mailbox *kmbx = NULL; struct pthread *pthread; /* Keep dequeueing until we find a valid thread: */ mutex->m_owner = NULL; pthread = TAILQ_FIRST(&mutex->m_queue); while (pthread != NULL) { /* Take the thread's scheduling lock: */ THR_SCHED_LOCK(curthread, pthread); /* Remove the thread from the mutex queue: */ TAILQ_REMOVE(&mutex->m_queue, pthread, sqe); pthread->sflags &= ~THR_FLAGS_IN_SYNCQ; /* * Only exit the loop if the thread hasn't been * cancelled. */ switch (mutex->m_protocol) { case PTHREAD_PRIO_NONE: /* * Assign the new owner and add the mutex to the * thread's list of owned mutexes. */ mutex->m_owner = pthread; TAILQ_INSERT_TAIL(&pthread->mutexq, mutex, m_qe); break; case PTHREAD_PRIO_INHERIT: /* * Assign the new owner and add the mutex to the * thread's list of owned mutexes. */ mutex->m_owner = pthread; TAILQ_INSERT_TAIL(&pthread->mutexq, mutex, m_qe); /* Track number of priority mutexes owned: */ pthread->priority_mutex_count++; /* * Set the priority of the mutex. Since our waiting * threads are in descending priority order, the * priority of the mutex becomes the active priority * of the thread we just dequeued. */ mutex->m_prio = pthread->active_priority; /* Save the owning threads inherited priority: */ mutex->m_saved_prio = pthread->inherited_priority; /* * The owning threads inherited priority now becomes * his active priority (the priority of the mutex). */ pthread->inherited_priority = mutex->m_prio; break; case PTHREAD_PRIO_PROTECT: if (pthread->active_priority > mutex->m_prio) { /* * Either the mutex ceiling priority has * been lowered and/or this threads priority * has been raised subsequent to the thread * being queued on the waiting list. */ pthread->error = EINVAL; } else { /* * Assign the new owner and add the mutex * to the thread's list of owned mutexes. */ mutex->m_owner = pthread; TAILQ_INSERT_TAIL(&pthread->mutexq, mutex, m_qe); /* Track number of priority mutexes owned: */ pthread->priority_mutex_count++; /* * Save the owning threads inherited * priority: */ mutex->m_saved_prio = pthread->inherited_priority; /* * The owning thread inherits the ceiling * priority of the mutex and executes at * that priority: */ pthread->inherited_priority = mutex->m_prio; pthread->active_priority = mutex->m_prio; } break; } /* Make the thread runnable and unlock the scheduling queue: */ kmbx = _thr_setrunnable_unlocked(pthread); /* Add a preemption point. */ if ((curthread->kseg == pthread->kseg) && (pthread->active_priority > curthread->active_priority)) curthread->critical_yield = 1; if (mutex->m_owner == pthread) { /* We're done; a valid owner was found. */ if (mutex->m_flags & MUTEX_FLAGS_PRIVATE) THR_CRITICAL_ENTER(pthread); THR_SCHED_UNLOCK(curthread, pthread); break; } THR_SCHED_UNLOCK(curthread, pthread); /* Get the next thread from the waiting queue: */ pthread = TAILQ_NEXT(pthread, sqe); } if ((pthread == NULL) && (mutex->m_protocol == PTHREAD_PRIO_INHERIT)) /* This mutex has no priority: */ mutex->m_prio = 0; return (kmbx); } /* * Dequeue a waiting thread from the head of a mutex queue in descending * priority order. */ static inline pthread_t mutex_queue_deq(struct pthread_mutex *mutex) { pthread_t pthread; while ((pthread = TAILQ_FIRST(&mutex->m_queue)) != NULL) { TAILQ_REMOVE(&mutex->m_queue, pthread, sqe); pthread->sflags &= ~THR_FLAGS_IN_SYNCQ; /* * Only exit the loop if the thread hasn't been * cancelled. */ if (pthread->interrupted == 0) break; } return (pthread); } /* * Remove a waiting thread from a mutex queue in descending priority order. */ static inline void mutex_queue_remove(pthread_mutex_t mutex, pthread_t pthread) { if ((pthread->sflags & THR_FLAGS_IN_SYNCQ) != 0) { TAILQ_REMOVE(&mutex->m_queue, pthread, sqe); pthread->sflags &= ~THR_FLAGS_IN_SYNCQ; } } /* * Enqueue a waiting thread to a queue in descending priority order. */ static inline void mutex_queue_enq(pthread_mutex_t mutex, pthread_t pthread) { pthread_t tid = TAILQ_LAST(&mutex->m_queue, mutex_head); THR_ASSERT_NOT_IN_SYNCQ(pthread); /* * For the common case of all threads having equal priority, * we perform a quick check against the priority of the thread * at the tail of the queue. */ if ((tid == NULL) || (pthread->active_priority <= tid->active_priority)) TAILQ_INSERT_TAIL(&mutex->m_queue, pthread, sqe); else { tid = TAILQ_FIRST(&mutex->m_queue); while (pthread->active_priority <= tid->active_priority) tid = TAILQ_NEXT(tid, sqe); TAILQ_INSERT_BEFORE(tid, pthread, sqe); } pthread->sflags |= THR_FLAGS_IN_SYNCQ; } Index: head/lib/libkse/thread/thr_mutex_prioceiling.c =================================================================== --- head/lib/libkse/thread/thr_mutex_prioceiling.c (revision 174111) +++ head/lib/libkse/thread/thr_mutex_prioceiling.c (revision 174112) @@ -1,124 +1,128 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_mutexattr_getprioceiling); LT10_COMPAT_DEFAULT(pthread_mutexattr_getprioceiling); LT10_COMPAT_PRIVATE(_pthread_mutexattr_setprioceiling); LT10_COMPAT_DEFAULT(pthread_mutexattr_setprioceiling); LT10_COMPAT_PRIVATE(_pthread_mutex_getprioceiling); LT10_COMPAT_DEFAULT(pthread_mutex_getprioceiling); LT10_COMPAT_PRIVATE(_pthread_mutex_setprioceiling); LT10_COMPAT_DEFAULT(pthread_mutex_setprioceiling); __weak_reference(_pthread_mutexattr_getprioceiling, pthread_mutexattr_getprioceiling); __weak_reference(_pthread_mutexattr_setprioceiling, pthread_mutexattr_setprioceiling); __weak_reference(_pthread_mutex_getprioceiling, pthread_mutex_getprioceiling); __weak_reference(_pthread_mutex_setprioceiling, pthread_mutex_setprioceiling); int _pthread_mutexattr_getprioceiling(pthread_mutexattr_t *mattr, int *prioceiling) { int ret = 0; if ((mattr == NULL) || (*mattr == NULL)) ret = EINVAL; else if ((*mattr)->m_protocol != PTHREAD_PRIO_PROTECT) ret = EINVAL; else *prioceiling = (*mattr)->m_ceiling; return(ret); } int _pthread_mutexattr_setprioceiling(pthread_mutexattr_t *mattr, int prioceiling) { int ret = 0; if ((mattr == NULL) || (*mattr == NULL)) ret = EINVAL; else if ((*mattr)->m_protocol != PTHREAD_PRIO_PROTECT) ret = EINVAL; else (*mattr)->m_ceiling = prioceiling; return(ret); } int _pthread_mutex_getprioceiling(pthread_mutex_t *mutex, int *prioceiling) { int ret; if ((mutex == NULL) || (*mutex == NULL)) ret = EINVAL; else if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT) ret = EINVAL; - else - ret = (*mutex)->m_prio; - - return(ret); + else { + *prioceiling = (*mutex)->m_prio; + ret = 0; + } + return (ret); } int _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling) { int ret = 0; int tmp; if ((mutex == NULL) || (*mutex == NULL)) ret = EINVAL; else if ((*mutex)->m_protocol != PTHREAD_PRIO_PROTECT) ret = EINVAL; /* Lock the mutex: */ - else if ((ret = pthread_mutex_lock(mutex)) == 0) { + else if ((ret = _pthread_mutex_lock(mutex)) == 0) { tmp = (*mutex)->m_prio; /* Set the new ceiling: */ (*mutex)->m_prio = prioceiling; /* Unlock the mutex: */ - ret = pthread_mutex_unlock(mutex); + ret = _pthread_mutex_unlock(mutex); /* Return the old ceiling: */ *old_ceiling = tmp; } return(ret); } Index: head/lib/libkse/thread/thr_mutex_protocol.c =================================================================== --- head/lib/libkse/thread/thr_mutex_protocol.c (revision 174111) +++ head/lib/libkse/thread/thr_mutex_protocol.c (revision 174112) @@ -1,75 +1,78 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_mutexattr_getprotocol); LT10_COMPAT_DEFAULT(pthread_mutexattr_getprotocol); LT10_COMPAT_PRIVATE(_pthread_mutexattr_setprotocol); LT10_COMPAT_DEFAULT(pthread_mutexattr_setprotocol); __weak_reference(_pthread_mutexattr_getprotocol, pthread_mutexattr_getprotocol); __weak_reference(_pthread_mutexattr_setprotocol, pthread_mutexattr_setprotocol); int _pthread_mutexattr_getprotocol(pthread_mutexattr_t *mattr, int *protocol) { int ret = 0; if ((mattr == NULL) || (*mattr == NULL)) ret = EINVAL; else *protocol = (*mattr)->m_protocol; return(ret); } int _pthread_mutexattr_setprotocol(pthread_mutexattr_t *mattr, int protocol) { int ret = 0; if ((mattr == NULL) || (*mattr == NULL) || (protocol < PTHREAD_PRIO_NONE) || (protocol > PTHREAD_PRIO_PROTECT)) ret = EINVAL; else { (*mattr)->m_protocol = protocol; (*mattr)->m_ceiling = THR_MAX_PRIORITY; } return(ret); } Index: head/lib/libkse/thread/thr_mutexattr_destroy.c =================================================================== --- head/lib/libkse/thread/thr_mutexattr_destroy.c (revision 174111) +++ head/lib/libkse/thread/thr_mutexattr_destroy.c (revision 174112) @@ -1,53 +1,56 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_mutexattr_destroy); LT10_COMPAT_DEFAULT(pthread_mutexattr_destroy); __weak_reference(_pthread_mutexattr_destroy, pthread_mutexattr_destroy); int _pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { int ret; if (attr == NULL || *attr == NULL) { ret = EINVAL; } else { free(*attr); *attr = NULL; ret = 0; } return(ret); } Index: head/lib/libkse/thread/thr_nanosleep.c =================================================================== --- head/lib/libkse/thread/thr_nanosleep.c (revision 174111) +++ head/lib/libkse/thread/thr_nanosleep.c (revision 174112) @@ -1,132 +1,138 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" + +int __nanosleep(const struct timespec *time_to_sleep, + struct timespec *time_remaining); LT10_COMPAT_PRIVATE(__nanosleep); LT10_COMPAT_PRIVATE(_nanosleep); LT10_COMPAT_DEFAULT(nanosleep); __weak_reference(__nanosleep, nanosleep); int _nanosleep(const struct timespec *time_to_sleep, struct timespec *time_remaining) { struct pthread *curthread = _get_curthread(); int ret = 0; struct timespec ts, ts1; struct timespec remaining_time; struct timespec wakeup_time; /* Check if the time to sleep is legal: */ 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 { if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) return (__sys_nanosleep(time_to_sleep, time_remaining)); KSE_GET_TOD(curthread->kse, &ts); /* Calculate the time for the current thread to wake up: */ TIMESPEC_ADD(&wakeup_time, &ts, time_to_sleep); THR_LOCK_SWITCH(curthread); curthread->interrupted = 0; curthread->wakeup_time = wakeup_time; THR_SET_STATE(curthread, PS_SLEEP_WAIT); /* Reschedule the current thread to sleep: */ _thr_sched_switch_unlocked(curthread); /* Calculate the remaining time to sleep: */ KSE_GET_TOD(curthread->kse, &ts1); remaining_time.tv_sec = time_to_sleep->tv_sec + ts.tv_sec - ts1.tv_sec; remaining_time.tv_nsec = time_to_sleep->tv_nsec + ts.tv_nsec - ts1.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: */ else 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: */ remaining_time.tv_sec = 0; remaining_time.tv_nsec = 0; } /* Check if the time remaining is to be returned: */ if (time_remaining != NULL) { /* Return the actual time slept: */ time_remaining->tv_sec = remaining_time.tv_sec; time_remaining->tv_nsec = remaining_time.tv_nsec; } /* Check if the sleep was interrupted: */ if (curthread->interrupted) { /* Return an EINTR error : */ errno = EINTR; ret = -1; } } return (ret); } int __nanosleep(const struct timespec *time_to_sleep, struct timespec *time_remaining) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = _nanosleep(time_to_sleep, time_remaining); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_once.c =================================================================== --- head/lib/libkse/thread/thr_once.c (revision 174111) +++ head/lib/libkse/thread/thr_once.c (revision 174112) @@ -1,98 +1,99 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + #include "namespace.h" #include #include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_once); LT10_COMPAT_DEFAULT(pthread_once); __weak_reference(_pthread_once, pthread_once); #define ONCE_NEVER_DONE PTHREAD_NEEDS_INIT #define ONCE_DONE PTHREAD_DONE_INIT #define ONCE_IN_PROGRESS 0x02 #define ONCE_MASK 0x03 static pthread_mutex_t once_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER; /* * POSIX: * The pthread_once() function is not a cancellation point. However, * if init_routine is a cancellation point and is canceled, the effect * on once_control shall be as if pthread_once() was never called. */ static void once_cancel_handler(void *arg) { pthread_once_t *once_control = arg; _pthread_mutex_lock(&once_lock); once_control->state = ONCE_NEVER_DONE; _pthread_mutex_unlock(&once_lock); _pthread_cond_broadcast(&once_cv); } int _pthread_once(pthread_once_t *once_control, void (*init_routine) (void)) { struct pthread *curthread; int wakeup = 0; if (once_control->state == ONCE_DONE) return (0); _pthread_mutex_lock(&once_lock); while (*(volatile int *)&(once_control->state) == ONCE_IN_PROGRESS) _pthread_cond_wait(&once_cv, &once_lock); /* * If previous thread was canceled, then the state still * could be ONCE_NEVER_DONE, we need to check it again. */ if (*(volatile int *)&(once_control->state) == ONCE_NEVER_DONE) { once_control->state = ONCE_IN_PROGRESS; _pthread_mutex_unlock(&once_lock); curthread = _get_curthread(); THR_CLEANUP_PUSH(curthread, once_cancel_handler, once_control); init_routine(); THR_CLEANUP_POP(curthread, 0); _pthread_mutex_lock(&once_lock); once_control->state = ONCE_DONE; wakeup = 1; } _pthread_mutex_unlock(&once_lock); if (wakeup) _pthread_cond_broadcast(&once_cv); return (0); } Index: head/lib/libkse/thread/thr_open.c =================================================================== --- head/lib/libkse/thread/thr_open.c (revision 174111) +++ head/lib/libkse/thread/thr_open.c (revision 174112) @@ -1,71 +1,76 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ * */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" + +int __open(const char *path, int flags,...); LT10_COMPAT_PRIVATE(__open); LT10_COMPAT_DEFAULT(open); __weak_reference(__open, open); int __open(const char *path, int flags,...) { struct pthread *curthread = _get_curthread(); int ret; int mode = 0; va_list ap; _thr_cancel_enter(curthread); /* Check if the file is being created: */ if (flags & O_CREAT) { /* Get the creation mode: */ va_start(ap, flags); mode = va_arg(ap, int); va_end(ap); } ret = __sys_open(path, flags, mode); /* * To avoid possible file handle leak, * only check cancellation point if it is failure */ _thr_cancel_leave(curthread, (ret == -1)); return ret; } Index: head/lib/libkse/thread/thr_pause.c =================================================================== --- head/lib/libkse/thread/thr_pause.c (revision 174111) +++ head/lib/libkse/thread/thr_pause.c (revision 174112) @@ -1,54 +1,58 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" + +int _pause(void); extern int __pause(void); LT10_COMPAT_PRIVATE(_pause); LT10_COMPAT_DEFAULT(pause); __weak_reference(_pause, pause); int _pause(void) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __pause(); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_poll.c =================================================================== --- head/lib/libkse/thread/thr_poll.c (revision 174111) +++ head/lib/libkse/thread/thr_poll.c (revision 174112) @@ -1,60 +1,65 @@ /* * Copyright (c) 1999 Daniel Eischen * 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__poll); LT10_COMPAT_DEFAULT(poll); + +int __poll(struct pollfd *fds, unsigned int nfds, int timeout); __weak_reference(__poll, poll); int __poll(struct pollfd *fds, unsigned int nfds, int timeout) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __sys_poll(fds, nfds, timeout); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_priority_queue.c =================================================================== --- head/lib/libkse/thread/thr_priority_queue.c (revision 174111) +++ head/lib/libkse/thread/thr_priority_queue.c (revision 174112) @@ -1,324 +1,327 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" /* Prototypes: */ static void pq_insert_prio_list(pq_queue_t *pq, int prio); #if defined(_PTHREADS_INVARIANTS) #define PQ_IN_SCHEDQ (THR_FLAGS_IN_RUNQ | THR_FLAGS_IN_WAITQ) #define PQ_SET_ACTIVE(pq) (pq)->pq_flags |= PQF_ACTIVE #define PQ_CLEAR_ACTIVE(pq) (pq)->pq_flags &= ~PQF_ACTIVE #define PQ_ASSERT_ACTIVE(pq, msg) do { \ if (((pq)->pq_flags & PQF_ACTIVE) == 0) \ PANIC(msg); \ } while (0) #define PQ_ASSERT_INACTIVE(pq, msg) do { \ if (((pq)->pq_flags & PQF_ACTIVE) != 0) \ PANIC(msg); \ } while (0) #define PQ_ASSERT_IN_WAITQ(thrd, msg) do { \ if (((thrd)->flags & THR_FLAGS_IN_WAITQ) == 0) \ PANIC(msg); \ } while (0) #define PQ_ASSERT_IN_RUNQ(thrd, msg) do { \ if (((thrd)->flags & THR_FLAGS_IN_RUNQ) == 0) \ PANIC(msg); \ } while (0) #define PQ_ASSERT_NOT_QUEUED(thrd, msg) do { \ if (((thrd)->flags & PQ_IN_SCHEDQ) != 0) \ PANIC(msg); \ } while (0) #else #define PQ_SET_ACTIVE(pq) #define PQ_CLEAR_ACTIVE(pq) #define PQ_ASSERT_ACTIVE(pq, msg) #define PQ_ASSERT_INACTIVE(pq, msg) #define PQ_ASSERT_IN_WAITQ(thrd, msg) #define PQ_ASSERT_IN_RUNQ(thrd, msg) #define PQ_ASSERT_NOT_QUEUED(thrd, msg) #endif int _pq_alloc(pq_queue_t *pq, int minprio, int maxprio) { int ret = 0; int prioslots = maxprio - minprio + 1; if (pq == NULL) ret = -1; /* Create the priority queue with (maxprio - minprio + 1) slots: */ else if ((pq->pq_lists = (pq_list_t *) malloc(sizeof(pq_list_t) * prioslots)) == NULL) ret = -1; else { /* Remember the queue size: */ pq->pq_size = prioslots; ret = _pq_init(pq); } return (ret); } void _pq_free(pq_queue_t *pq) { if ((pq != NULL) && (pq->pq_lists != NULL)) free(pq->pq_lists); } 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 < 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; } /* Initialize the priority queue: */ TAILQ_INIT(&pq->pq_queue); pq->pq_flags = 0; pq->pq_threads = 0; } return (ret); } void _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, "_pq_remove: pq_active"); PQ_SET_ACTIVE(pq); PQ_ASSERT_IN_RUNQ(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); pq->pq_threads--; /* This thread is now longer in the priority queue. */ pthread->flags &= ~THR_FLAGS_IN_RUNQ; PQ_CLEAR_ACTIVE(pq); } void _pq_insert_head(pq_queue_t *pq, pthread_t pthread) { int prio; /* * Make some assertions when debugging is enabled: */ PQ_ASSERT_INACTIVE(pq, "_pq_insert_head: pq_active"); PQ_SET_ACTIVE(pq); PQ_ASSERT_NOT_QUEUED(pthread, "_pq_insert_head: Already in priority queue"); prio = pthread->active_priority; 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); pq->pq_threads++; /* Mark this thread as being in the priority queue. */ pthread->flags |= THR_FLAGS_IN_RUNQ; PQ_CLEAR_ACTIVE(pq); } void _pq_insert_tail(pq_queue_t *pq, pthread_t pthread) { int prio; /* * Make some assertions when debugging is enabled: */ PQ_ASSERT_INACTIVE(pq, "_pq_insert_tail: pq_active"); PQ_SET_ACTIVE(pq); PQ_ASSERT_NOT_QUEUED(pthread, "_pq_insert_tail: Already in priority queue"); prio = pthread->active_priority; 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); pq->pq_threads++; /* Mark this thread as being in the priority queue. */ pthread->flags |= THR_FLAGS_IN_RUNQ; PQ_CLEAR_ACTIVE(pq); } pthread_t _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, "_pq_first: pq_active"); PQ_SET_ACTIVE(pq); while (((pql = TAILQ_FIRST(&pq->pq_queue)) != NULL) && (pthread == NULL)) { if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) { /* * The priority list is empty; remove the list * from the queue. */ TAILQ_REMOVE(&pq->pq_queue, pql, pl_link); /* Mark the list as not being in the queue: */ pql->pl_queued = 0; } } PQ_CLEAR_ACTIVE(pq); return (pthread); } /* * Select a thread which is allowed to run by debugger, we probably * should merge the function into _pq_first if that function is only * used by scheduler to select a thread. */ pthread_t _pq_first_debug(pq_queue_t *pq) { pq_list_t *pql, *pqlnext = NULL; pthread_t pthread = NULL; /* * Make some assertions when debugging is enabled: */ PQ_ASSERT_INACTIVE(pq, "_pq_first: pq_active"); PQ_SET_ACTIVE(pq); for (pql = TAILQ_FIRST(&pq->pq_queue); pql != NULL && pthread == NULL; pql = pqlnext) { if ((pthread = TAILQ_FIRST(&pql->pl_head)) == NULL) { /* * The priority list is empty; remove the list * from the queue. */ pqlnext = TAILQ_NEXT(pql, pl_link); TAILQ_REMOVE(&pq->pq_queue, pql, pl_link); /* Mark the list as not being in the queue: */ pql->pl_queued = 0; } else { /* * note there may be a suspension event during this * test, If TMDF_SUSPEND is set after we tested it, * we will run the thread, this seems be a problem, * fortunatly, when we are being debugged, all context * switch will be done by kse_switchin, that is a * syscall, kse_switchin will check the flag again, * the thread will be returned via upcall, so next * time, UTS won't run the thread. */ while (pthread != NULL && !DBG_CAN_RUN(pthread)) { pthread = TAILQ_NEXT(pthread, pqe); } if (pthread == NULL) pqlnext = TAILQ_NEXT(pql, pl_link); } } PQ_CLEAR_ACTIVE(pq); return (pthread); } static void 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, "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 be inserted. */ pql = TAILQ_FIRST(&pq->pq_queue); while ((pql != NULL) && (pql->pl_prio > prio)) pql = TAILQ_NEXT(pql, pl_link); /* Insert the list: */ if (pql == NULL) TAILQ_INSERT_TAIL(&pq->pq_queue, &pq->pq_lists[prio], pl_link); else TAILQ_INSERT_BEFORE(pql, &pq->pq_lists[prio], pl_link); /* Mark this list as being in the queue: */ pq->pq_lists[prio].pl_queued = 1; } Index: head/lib/libkse/thread/thr_private.h =================================================================== --- head/lib/libkse/thread/thr_private.h (revision 174111) +++ head/lib/libkse/thread/thr_private.h (revision 174112) @@ -1,1324 +1,1327 @@ /* * Copyright (c) 1995-1998 John Birrell . * 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. 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 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. * * Private thread definitions for the uthread kernel. * * $FreeBSD$ */ #ifndef _THR_PRIVATE_H #define _THR_PRIVATE_H /* * Include files. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef LIBTHREAD_DB #include "lock.h" #include "pthread_md.h" #endif /* * Unfortunately, libpthread had symbol versioning before libc. * But now libc has symbol versioning, we need to occupy the * same version namespace in order to override some libc functions. * So in order to avoid breaking binaries requiring symbols from * LIBTHREAD_1_0, we need to provide a compatible interface for * those symbols. */ #if 0 #define SYM_LT10(sym) __CONCAT(sym, _lt10) #define SYM_FB10(sym) __CONCAT(sym, _fb10) #define SYM_FBP10(sym) __CONCAT(sym, _fbp10) #define WEAK_REF(sym, alias) __weak_reference(sym, alias) #define SYM_COMPAT(sym, impl, ver) __sym_compat(sym, impl, ver) #define SYM_DEFAULT(sym, impl, ver) __sym_default(sym, impl, ver) #define LT10_COMPAT(sym) \ WEAK_REF(sym, SYM_LT10(sym)); \ SYM_COMPAT(sym, SYM_LT10(sym), LIBTHREAD_1_0) #define LT10_COMPAT_DEFAULT(sym) \ LT10_COMPAT(sym); \ WEAK_REF(sym, SYM_FB10(sym)); \ SYM_DEFAULT(sym, SYM_FB10(sym), FBSD_1.0) #define LT10_COMPAT_PRIVATE(sym) \ LT10_COMPAT(sym); \ WEAK_REF(sym, SYM_FBP10(sym)); \ SYM_DEFAULT(sym, SYM_FBP10(sym), FBSDprivate_1.0) #else #define LT10_COMPAT_DEFAULT(sym) #define LT10_COMPAT_PRIVATE(sym) #endif /* * Evaluate the storage class specifier. */ #ifdef GLOBAL_PTHREAD_PRIVATE #define SCLASS #define SCLASS_PRESET(x...) = x #else #define SCLASS extern #define SCLASS_PRESET(x...) #endif /* * Kernel fatal error handler macro. */ #define PANIC(string) _thr_exit(__FILE__, __LINE__, string) /* Output debug messages like this: */ #ifdef STDOUT_FILENO #define stdout_debug(...) _thread_printf(STDOUT_FILENO, __VA_ARGS__) #endif #ifdef STDERR_FILENO #define stderr_debug(...) _thread_printf(STDERR_FILENO, __VA_ARGS__) #endif #define DBG_MUTEX 0x0001 #define DBG_SIG 0x0002 #define DBG_INFO_DUMP 0x0004 #ifdef _PTHREADS_INVARIANTS #define THR_ASSERT(cond, msg) do { \ if (!(cond)) \ PANIC(msg); \ } while (0) #else #define THR_ASSERT(cond, msg) #endif /* * State change macro without scheduling queue change: */ #define THR_SET_STATE(thrd, newstate) do { \ (thrd)->state = newstate; \ (thrd)->fname = __FILE__; \ (thrd)->lineno = __LINE__; \ } while (0) #define TIMESPEC_ADD(dst, src, val) \ do { \ (dst)->tv_sec = (src)->tv_sec + (val)->tv_sec; \ (dst)->tv_nsec = (src)->tv_nsec + (val)->tv_nsec; \ if ((dst)->tv_nsec >= 1000000000) { \ (dst)->tv_sec++; \ (dst)->tv_nsec -= 1000000000; \ } \ } while (0) #define TIMESPEC_SUB(dst, src, val) \ do { \ (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \ (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \ if ((dst)->tv_nsec < 0) { \ (dst)->tv_sec--; \ (dst)->tv_nsec += 1000000000; \ } \ } while (0) /* * Priority queues. * * XXX It'd be nice if these were contained in uthread_priority_queue.[ch]. */ typedef struct pq_list { TAILQ_HEAD(, pthread) pl_head; /* list of threads at this priority */ TAILQ_ENTRY(pq_list) pl_link; /* link for queue of priority lists */ int pl_prio; /* the priority of this list */ int pl_queued; /* is this in the priority queue */ } pq_list_t; typedef struct pq_queue { TAILQ_HEAD(, pq_list) pq_queue; /* queue of priority lists */ pq_list_t *pq_lists; /* array of all priority lists */ int pq_size; /* number of priority lists */ #define PQF_ACTIVE 0x0001 int pq_flags; int pq_threads; } pq_queue_t; /* * Each KSEG has a scheduling queue. For now, threads that exist in their * own KSEG (system scope) will get a full priority queue. In the future * this can be optimized for the single thread per KSEG case. */ struct sched_queue { pq_queue_t sq_runq; TAILQ_HEAD(, pthread) sq_waitq; /* waiting in userland */ }; typedef struct kse_thr_mailbox *kse_critical_t; struct kse_group; #define MAX_KSE_LOCKLEVEL 5 struct kse { /* -- location and order specific items for gdb -- */ struct kcb *k_kcb; struct pthread *k_curthread; /* current thread */ struct kse_group *k_kseg; /* parent KSEG */ struct sched_queue *k_schedq; /* scheduling queue */ /* -- end of location and order specific items -- */ TAILQ_ENTRY(kse) k_qe; /* KSE list link entry */ TAILQ_ENTRY(kse) k_kgqe; /* KSEG's KSE list entry */ /* * Items that are only modified by the kse, or that otherwise * don't need to be locked when accessed */ struct lock k_lock; struct lockuser k_lockusers[MAX_KSE_LOCKLEVEL]; int k_locklevel; stack_t k_stack; int k_flags; #define KF_STARTED 0x0001 /* kernel kse created */ #define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */ #define KF_TERMINATED 0x0004 /* kse is terminated */ #define KF_IDLE 0x0008 /* kse is idle */ #define KF_SWITCH 0x0010 /* thread switch in UTS */ int k_error; /* syscall errno in critical */ int k_cpu; /* CPU ID when bound */ int k_sigseqno; /* signal buffered count */ }; #define KSE_SET_IDLE(kse) ((kse)->k_flags |= KF_IDLE) #define KSE_CLEAR_IDLE(kse) ((kse)->k_flags &= ~KF_IDLE) #define KSE_IS_IDLE(kse) (((kse)->k_flags & KF_IDLE) != 0) #define KSE_SET_SWITCH(kse) ((kse)->k_flags |= KF_SWITCH) #define KSE_CLEAR_SWITCH(kse) ((kse)->k_flags &= ~KF_SWITCH) #define KSE_IS_SWITCH(kse) (((kse)->k_flags & KF_SWITCH) != 0) /* * Each KSE group contains one or more KSEs in which threads can run. * At least for now, there is one scheduling queue per KSE group; KSEs * within the same KSE group compete for threads from the same scheduling * queue. A scope system thread has one KSE in one KSE group; the group * does not use its scheduling queue. */ struct kse_group { TAILQ_HEAD(, kse) kg_kseq; /* list of KSEs in group */ TAILQ_HEAD(, pthread) kg_threadq; /* list of threads in group */ TAILQ_ENTRY(kse_group) kg_qe; /* link entry */ struct sched_queue kg_schedq; /* scheduling queue */ struct lock kg_lock; int kg_threadcount; /* # of assigned threads */ int kg_ksecount; /* # of assigned KSEs */ int kg_idle_kses; int kg_flags; #define KGF_SINGLE_THREAD 0x0001 /* scope system kse group */ #define KGF_SCHEDQ_INITED 0x0002 /* has an initialized schedq */ }; /* * Add/remove threads from a KSE's scheduling queue. * For now the scheduling queue is hung off the KSEG. */ #define KSEG_THRQ_ADD(kseg, thr) \ do { \ TAILQ_INSERT_TAIL(&(kseg)->kg_threadq, thr, kle);\ (kseg)->kg_threadcount++; \ } while (0) #define KSEG_THRQ_REMOVE(kseg, thr) \ do { \ TAILQ_REMOVE(&(kseg)->kg_threadq, thr, kle); \ (kseg)->kg_threadcount--; \ } while (0) /* * Lock acquire and release for KSEs. */ #define KSE_LOCK_ACQUIRE(kse, lck) \ do { \ if ((kse)->k_locklevel < MAX_KSE_LOCKLEVEL) { \ (kse)->k_locklevel++; \ _lock_acquire((lck), \ &(kse)->k_lockusers[(kse)->k_locklevel - 1], 0); \ } \ else \ PANIC("Exceeded maximum lock level"); \ } while (0) #define KSE_LOCK_RELEASE(kse, lck) \ do { \ if ((kse)->k_locklevel > 0) { \ _lock_release((lck), \ &(kse)->k_lockusers[(kse)->k_locklevel - 1]); \ (kse)->k_locklevel--; \ } \ } while (0) /* * Lock our own KSEG. */ #define KSE_LOCK(curkse) \ KSE_LOCK_ACQUIRE(curkse, &(curkse)->k_kseg->kg_lock) #define KSE_UNLOCK(curkse) \ KSE_LOCK_RELEASE(curkse, &(curkse)->k_kseg->kg_lock) /* * Lock a potentially different KSEG. */ #define KSE_SCHED_LOCK(curkse, kseg) \ KSE_LOCK_ACQUIRE(curkse, &(kseg)->kg_lock) #define KSE_SCHED_UNLOCK(curkse, kseg) \ KSE_LOCK_RELEASE(curkse, &(kseg)->kg_lock) /* * Waiting queue manipulation macros (using pqe link): */ #define KSE_WAITQ_REMOVE(kse, thrd) \ do { \ if (((thrd)->flags & THR_FLAGS_IN_WAITQ) != 0) { \ TAILQ_REMOVE(&(kse)->k_schedq->sq_waitq, thrd, pqe); \ (thrd)->flags &= ~THR_FLAGS_IN_WAITQ; \ } \ } while (0) #define KSE_WAITQ_INSERT(kse, thrd) kse_waitq_insert(thrd) #define KSE_WAITQ_FIRST(kse) TAILQ_FIRST(&(kse)->k_schedq->sq_waitq) #define KSE_WAKEUP(kse) kse_wakeup(&(kse)->k_kcb->kcb_kmbx) /* * TailQ initialization values. */ #define TAILQ_INITIALIZER { NULL, NULL } /* * lock initialization values. */ #define LCK_INITIALIZER { NULL, NULL, LCK_DEFAULT } struct pthread_mutex { /* * Lock for accesses to this structure. */ struct lock m_lock; enum pthread_mutextype m_type; int m_protocol; TAILQ_HEAD(mutex_head, pthread) m_queue; struct pthread *m_owner; long m_flags; int m_count; int m_refcount; /* * Used for priority inheritence and protection. * * m_prio - For priority inheritence, the highest active * priority (threads locking the mutex inherit * this priority). For priority protection, the * ceiling priority of this mutex. * m_saved_prio - mutex owners inherited priority before * taking the mutex, restored when the owner * unlocks the mutex. */ int m_prio; int m_saved_prio; /* * Link for list of all mutexes a thread currently owns. */ TAILQ_ENTRY(pthread_mutex) m_qe; }; /* * Flags for mutexes. */ #define MUTEX_FLAGS_PRIVATE 0x01 #define MUTEX_FLAGS_INITED 0x02 #define MUTEX_FLAGS_BUSY 0x04 /* * Static mutex initialization values. */ #define PTHREAD_MUTEX_STATIC_INITIALIZER \ { LCK_INITIALIZER, PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, \ TAILQ_INITIALIZER, NULL, MUTEX_FLAGS_PRIVATE, 0, 0, 0, 0, \ TAILQ_INITIALIZER } struct pthread_mutex_attr { enum pthread_mutextype m_type; int m_protocol; int m_ceiling; long m_flags; }; #define PTHREAD_MUTEXATTR_STATIC_INITIALIZER \ { PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, MUTEX_FLAGS_PRIVATE } /* * Condition variable definitions. */ enum pthread_cond_type { COND_TYPE_FAST, COND_TYPE_MAX }; struct pthread_cond { /* * Lock for accesses to this structure. */ struct lock c_lock; enum pthread_cond_type c_type; TAILQ_HEAD(cond_head, pthread) c_queue; struct pthread_mutex *c_mutex; long c_flags; long c_seqno; }; struct pthread_cond_attr { enum pthread_cond_type c_type; long c_flags; }; struct pthread_barrier { pthread_mutex_t b_lock; pthread_cond_t b_cond; int b_count; int b_waiters; int b_generation; }; struct pthread_barrierattr { int pshared; }; struct pthread_spinlock { volatile int s_lock; pthread_t s_owner; }; /* * Flags for condition variables. */ #define COND_FLAGS_PRIVATE 0x01 #define COND_FLAGS_INITED 0x02 #define COND_FLAGS_BUSY 0x04 /* * Static cond initialization values. */ #define PTHREAD_COND_STATIC_INITIALIZER \ { LCK_INITIALIZER, COND_TYPE_FAST, TAILQ_INITIALIZER, \ NULL, NULL, 0, 0 } /* * Cleanup definitions. */ struct pthread_cleanup { struct pthread_cleanup *next; void (*routine) (void *); void *routine_arg; int onstack; }; #define THR_CLEANUP_PUSH(td, func, arg) { \ struct pthread_cleanup __cup; \ \ __cup.routine = func; \ __cup.routine_arg = arg; \ __cup.onstack = 1; \ __cup.next = (td)->cleanup; \ (td)->cleanup = &__cup; #define THR_CLEANUP_POP(td, exec) \ (td)->cleanup = __cup.next; \ if ((exec) != 0) \ __cup.routine(__cup.routine_arg); \ } struct pthread_atfork { TAILQ_ENTRY(pthread_atfork) qe; void (*prepare)(void); void (*parent)(void); void (*child)(void); }; struct pthread_attr { int sched_policy; int sched_inherit; int sched_interval; int prio; int suspend; #define THR_STACK_USER 0x100 /* 0xFF reserved for */ #define THR_SIGNAL_THREAD 0x200 /* This is a signal thread */ int flags; void *arg_attr; void (*cleanup_attr) (void *); void *stackaddr_attr; size_t stacksize_attr; size_t guardsize_attr; }; /* * Thread creation state attributes. */ #define THR_CREATE_RUNNING 0 #define THR_CREATE_SUSPENDED 1 /* * Miscellaneous definitions. */ #define THR_STACK32_DEFAULT (1 * 1024 * 1024) #define THR_STACK64_DEFAULT (2 * 1024 * 1024) /* * 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 THR_STACK32_INITIAL (2 * 1024 * 1024) #define THR_STACK64_INITIAL (4 * 1024 * 1024) /* * Define the different priority ranges. All applications have thread * priorities constrained within 0-31. The threads library raises the * priority when delivering signals in order to ensure that signal * delivery happens (from the POSIX spec) "as soon as possible". * In the future, the threads library will also be able to map specific * threads into real-time (cooperating) processes or kernel threads. * The RT and SIGNAL priorities will be used internally and added to * thread base priorities so that the scheduling queue can handle both * normal and RT priority threads with and without signal handling. * * The approach taken is that, within each class, signal delivery * always has priority over thread execution. */ #define THR_DEFAULT_PRIORITY 15 #define THR_MIN_PRIORITY 0 #define THR_MAX_PRIORITY 31 /* 0x1F */ #define THR_SIGNAL_PRIORITY 32 /* 0x20 */ #define THR_RT_PRIORITY 64 /* 0x40 */ #define THR_FIRST_PRIORITY THR_MIN_PRIORITY #define THR_LAST_PRIORITY \ (THR_MAX_PRIORITY + THR_SIGNAL_PRIORITY + THR_RT_PRIORITY) #define THR_BASE_PRIORITY(prio) ((prio) & THR_MAX_PRIORITY) /* * Clock resolution in microseconds. */ #define CLOCK_RES_USEC 10000 /* * Time slice period in microseconds. */ #define TIMESLICE_USEC 20000 /* * XXX - Define a thread-safe macro to get the current time of day * which is updated at regular intervals by something. * * For now, we just make the system call to get the time. */ #define KSE_GET_TOD(curkse, tsp) \ do { \ *tsp = (curkse)->k_kcb->kcb_kmbx.km_timeofday; \ if ((tsp)->tv_sec == 0) \ clock_gettime(CLOCK_REALTIME, tsp); \ } while (0) struct pthread_rwlockattr { int pshared; }; struct pthread_rwlock { pthread_mutex_t lock; /* monitor lock */ pthread_cond_t read_signal; pthread_cond_t write_signal; int state; /* 0 = idle >0 = # of readers -1 = writer */ int blocked_writers; }; /* * Thread states. */ enum pthread_state { PS_RUNNING, PS_LOCKWAIT, PS_MUTEX_WAIT, PS_COND_WAIT, PS_SLEEP_WAIT, PS_SIGSUSPEND, PS_SIGWAIT, PS_JOIN, PS_SUSPENDED, PS_DEAD, PS_DEADLOCK, PS_STATE_MAX }; struct sigwait_data { sigset_t *waitset; siginfo_t *siginfo; /* used to save siginfo for sigwaitinfo() */ }; union pthread_wait_data { pthread_mutex_t mutex; pthread_cond_t cond; struct lock *lock; struct sigwait_data *sigwait; }; /* * Define a continuation routine that can be used to perform a * transfer of control: */ typedef void (*thread_continuation_t) (void *); /* * This stores a thread's state prior to running a signal handler. * It is used when a signal is delivered to a thread blocked in * userland. If the signal handler returns normally, the thread's * state is restored from here. */ struct pthread_sigframe { int psf_valid; int psf_flags; int psf_cancelflags; int psf_interrupted; int psf_timeout; int psf_signo; enum pthread_state psf_state; union pthread_wait_data psf_wait_data; struct timespec psf_wakeup_time; sigset_t psf_sigset; sigset_t psf_sigmask; int psf_seqno; thread_continuation_t psf_continuation; }; struct join_status { struct pthread *thread; void *ret; int error; }; struct pthread_specific_elem { - const void *data; - int seqno; + void *data; + int seqno; }; +typedef void (*const_key_destructor_t)(const void *); +typedef void (*key_destructor_t)(void *); + struct pthread_key { volatile int allocated; volatile int count; int seqno; - void (*destructor) (void *); + key_destructor_t destructor; }; #define MAX_THR_LOCKLEVEL 5 /* * Thread structure. */ struct pthread { /* Thread control block */ struct tcb *tcb; /* * Magic value to help recognize a valid thread structure * from an invalid one: */ #define THR_MAGIC ((u_int32_t) 0xd09ba115) u_int32_t magic; char *name; u_int64_t uniqueid; /* for gdb */ /* Queue entry for list of all threads: */ TAILQ_ENTRY(pthread) tle; /* link for all threads in process */ TAILQ_ENTRY(pthread) kle; /* link for all threads in KSE/KSEG */ /* Queue entry for GC lists: */ TAILQ_ENTRY(pthread) gcle; /* Hash queue entry */ LIST_ENTRY(pthread) hle; /* * Lock for accesses to this thread structure. */ struct lock lock; struct lockuser lockusers[MAX_THR_LOCKLEVEL]; int locklevel; kse_critical_t critical[MAX_KSE_LOCKLEVEL]; struct kse *kse; struct kse_group *kseg; /* * Thread start routine, argument, stack pointer and thread * attributes. */ void *(*start_routine)(void *); void *arg; struct pthread_attr attr; int active; /* thread running */ int blocked; /* thread blocked in kernel */ int need_switchout; /* * Used for tracking delivery of signal handlers. */ siginfo_t *siginfo; thread_continuation_t sigbackout; /* * Cancelability flags - the lower 2 bits are used by cancel * definitions in pthread.h */ #define THR_AT_CANCEL_POINT 0x0004 #define THR_CANCELLING 0x0008 #define THR_CANCEL_NEEDED 0x0010 int cancelflags; thread_continuation_t continuation; /* * The thread's base and pending signal masks. The active * signal mask is stored in the thread's context (in mailbox). */ sigset_t sigmask; sigset_t sigpend; sigset_t *oldsigmask; volatile int check_pending; int refcount; /* Thread state: */ enum pthread_state state; volatile int lock_switch; /* * Number of microseconds accumulated by this thread when * time slicing is active. */ long slice_usec; /* * Time to wake up thread. This is used for sleeping threads and * for any operation which may time out (such as select). */ struct timespec wakeup_time; /* TRUE if operation has timed out. */ int timeout; /* * Error variable used instead of errno. The function __error() * returns a pointer to this. */ int error; /* * The joiner is the thread that is joining to this thread. The * join status keeps track of a join operation to another thread. */ struct pthread *joiner; struct join_status join_status; /* * The current thread can belong to only one scheduling queue at * a time (ready or waiting queue). It can also belong to: * * o A queue of threads waiting for a mutex * o A queue of threads waiting for a condition variable * * It is possible for a thread to belong to more than one of the * above queues if it is handling a signal. A thread may only * enter a mutex or condition variable queue when it is not * being called from a signal handler. If a thread is a member * of one of these queues when a signal handler is invoked, it * must be removed from the queue before invoking the handler * and then added back to the queue after return from the handler. * * Use pqe for the scheduling queue link (both ready and waiting), * sqe for synchronization (mutex, condition variable, and join) * queue links, and qe for all other links. */ TAILQ_ENTRY(pthread) pqe; /* priority, wait queues link */ TAILQ_ENTRY(pthread) sqe; /* synchronization queue link */ /* Wait data. */ union pthread_wait_data data; /* * Set to TRUE if a blocking operation was * interrupted by a signal: */ int interrupted; /* * Set to non-zero when this thread has entered a critical * region. We allow for recursive entries into critical regions. */ int critical_count; /* * Set to TRUE if this thread should yield after leaving a * critical region to check for signals, messages, etc. */ int critical_yield; int sflags; #define THR_FLAGS_IN_SYNCQ 0x0001 /* Miscellaneous flags; only set with scheduling lock held. */ int flags; #define THR_FLAGS_PRIVATE 0x0001 #define THR_FLAGS_IN_WAITQ 0x0002 /* in waiting queue using pqe link */ #define THR_FLAGS_IN_RUNQ 0x0004 /* in run queue using pqe link */ #define THR_FLAGS_EXITING 0x0008 /* thread is exiting */ #define THR_FLAGS_SUSPENDED 0x0010 /* thread is suspended */ /* Thread list flags; only set with thread list lock held. */ #define TLFLAGS_GC_SAFE 0x0001 /* thread safe for cleaning */ #define TLFLAGS_IN_TDLIST 0x0002 /* thread in all thread list */ #define TLFLAGS_IN_GCLIST 0x0004 /* thread in gc list */ int tlflags; /* * Base priority is the user setable and retrievable priority * of the thread. It is only affected by explicit calls to * set thread priority and upon thread creation via a thread * attribute or default priority. */ char base_priority; /* * Inherited priority is the priority a thread inherits by * taking a priority inheritence or protection mutex. It * is not affected by base priority changes. Inherited * priority defaults to and remains 0 until a mutex is taken * that is being waited on by any other thread whose priority * is non-zero. */ char inherited_priority; /* * Active priority is always the maximum of the threads base * priority and inherited priority. When there is a change * in either the base or inherited priority, the active * priority must be recalculated. */ char active_priority; /* Number of priority ceiling or protection mutexes owned. */ int priority_mutex_count; /* Number rwlocks rdlocks held. */ int rdlock_count; /* * Queue of currently owned mutexes. */ TAILQ_HEAD(, pthread_mutex) mutexq; void *ret; struct pthread_specific_elem *specific; int specific_data_count; /* Alternative stack for sigaltstack() */ stack_t sigstk; /* * Current locks bitmap for rtld. */ int rtld_bits; /* Cleanup handlers Link List */ struct pthread_cleanup *cleanup; - char *fname; /* Ptr to source file name */ + const char *fname; /* Ptr to source file name */ int lineno; /* Source line number. */ }; /* * Critical regions can also be detected by looking at the threads * current lock level. Ensure these macros increment and decrement * the lock levels such that locks can not be held with a lock level * of 0. */ #define THR_IN_CRITICAL(thrd) \ (((thrd)->locklevel > 0) || \ ((thrd)->critical_count > 0)) #define THR_YIELD_CHECK(thrd) \ do { \ if (!THR_IN_CRITICAL(thrd)) { \ if (__predict_false(_libkse_debug)) \ _thr_debug_check_yield(thrd); \ if ((thrd)->critical_yield != 0) \ _thr_sched_switch(thrd); \ if ((thrd)->check_pending != 0) \ _thr_sig_check_pending(thrd); \ } \ } while (0) #define THR_LOCK_ACQUIRE(thrd, lck) \ do { \ if ((thrd)->locklevel < MAX_THR_LOCKLEVEL) { \ THR_DEACTIVATE_LAST_LOCK(thrd); \ (thrd)->locklevel++; \ _lock_acquire((lck), \ &(thrd)->lockusers[(thrd)->locklevel - 1], \ (thrd)->active_priority); \ } else \ PANIC("Exceeded maximum lock level"); \ } while (0) #define THR_LOCK_RELEASE(thrd, lck) \ do { \ if ((thrd)->locklevel > 0) { \ _lock_release((lck), \ &(thrd)->lockusers[(thrd)->locklevel - 1]); \ (thrd)->locklevel--; \ THR_ACTIVATE_LAST_LOCK(thrd); \ if ((thrd)->locklevel == 0) \ THR_YIELD_CHECK(thrd); \ } \ } while (0) #define THR_ACTIVATE_LAST_LOCK(thrd) \ do { \ if ((thrd)->locklevel > 0) \ _lockuser_setactive( \ &(thrd)->lockusers[(thrd)->locklevel - 1], 1); \ } while (0) #define THR_DEACTIVATE_LAST_LOCK(thrd) \ do { \ if ((thrd)->locklevel > 0) \ _lockuser_setactive( \ &(thrd)->lockusers[(thrd)->locklevel - 1], 0); \ } while (0) /* * For now, threads will have their own lock separate from their * KSE scheduling lock. */ #define THR_LOCK(thr) THR_LOCK_ACQUIRE(thr, &(thr)->lock) #define THR_UNLOCK(thr) THR_LOCK_RELEASE(thr, &(thr)->lock) #define THR_THREAD_LOCK(curthrd, thr) THR_LOCK_ACQUIRE(curthrd, &(thr)->lock) #define THR_THREAD_UNLOCK(curthrd, thr) THR_LOCK_RELEASE(curthrd, &(thr)->lock) /* * Priority queue manipulation macros (using pqe link). We use * the thread's kseg link instead of the kse link because a thread * does not (currently) have a statically assigned kse. */ #define THR_RUNQ_INSERT_HEAD(thrd) \ _pq_insert_head(&(thrd)->kseg->kg_schedq.sq_runq, thrd) #define THR_RUNQ_INSERT_TAIL(thrd) \ _pq_insert_tail(&(thrd)->kseg->kg_schedq.sq_runq, thrd) #define THR_RUNQ_REMOVE(thrd) \ _pq_remove(&(thrd)->kseg->kg_schedq.sq_runq, thrd) /* * Macros to insert/remove threads to the all thread list and * the gc list. */ #define THR_LIST_ADD(thrd) do { \ if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) == 0) { \ TAILQ_INSERT_HEAD(&_thread_list, thrd, tle); \ _thr_hash_add(thrd); \ (thrd)->tlflags |= TLFLAGS_IN_TDLIST; \ } \ } while (0) #define THR_LIST_REMOVE(thrd) do { \ if (((thrd)->tlflags & TLFLAGS_IN_TDLIST) != 0) { \ TAILQ_REMOVE(&_thread_list, thrd, tle); \ _thr_hash_remove(thrd); \ (thrd)->tlflags &= ~TLFLAGS_IN_TDLIST; \ } \ } while (0) #define THR_GCLIST_ADD(thrd) do { \ if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) == 0) { \ TAILQ_INSERT_HEAD(&_thread_gc_list, thrd, gcle);\ (thrd)->tlflags |= TLFLAGS_IN_GCLIST; \ _gc_count++; \ } \ } while (0) #define THR_GCLIST_REMOVE(thrd) do { \ if (((thrd)->tlflags & TLFLAGS_IN_GCLIST) != 0) { \ TAILQ_REMOVE(&_thread_gc_list, thrd, gcle); \ (thrd)->tlflags &= ~TLFLAGS_IN_GCLIST; \ _gc_count--; \ } \ } while (0) #define GC_NEEDED() (atomic_load_acq_int(&_gc_count) >= 5) /* * Locking the scheduling queue for another thread uses that thread's * KSEG lock. */ #define THR_SCHED_LOCK(curthr, thr) do { \ (curthr)->critical[(curthr)->locklevel] = _kse_critical_enter(); \ (curthr)->locklevel++; \ KSE_SCHED_LOCK((curthr)->kse, (thr)->kseg); \ } while (0) #define THR_SCHED_UNLOCK(curthr, thr) do { \ KSE_SCHED_UNLOCK((curthr)->kse, (thr)->kseg); \ (curthr)->locklevel--; \ _kse_critical_leave((curthr)->critical[(curthr)->locklevel]); \ } while (0) /* Take the scheduling lock with the intent to call the scheduler. */ #define THR_LOCK_SWITCH(curthr) do { \ (void)_kse_critical_enter(); \ KSE_SCHED_LOCK((curthr)->kse, (curthr)->kseg); \ } while (0) #define THR_UNLOCK_SWITCH(curthr) do { \ KSE_SCHED_UNLOCK((curthr)->kse, (curthr)->kseg);\ } while (0) #define THR_CRITICAL_ENTER(thr) (thr)->critical_count++ #define THR_CRITICAL_LEAVE(thr) do { \ (thr)->critical_count--; \ if (((thr)->critical_yield != 0) && \ ((thr)->critical_count == 0)) { \ (thr)->critical_yield = 0; \ _thr_sched_switch(thr); \ } \ } while (0) #define THR_IS_ACTIVE(thrd) \ ((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd)) #define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0) #define THR_IS_SUSPENDED(thrd) \ (((thrd)->state == PS_SUSPENDED) || \ (((thrd)->flags & THR_FLAGS_SUSPENDED) != 0)) #define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0) #define DBG_CAN_RUN(thrd) (((thrd)->tcb->tcb_tmbx.tm_dflags & \ TMDF_SUSPEND) == 0) extern int __isthreaded; static inline int _kse_isthreaded(void) { return (__isthreaded != 0); } /* * Global variables for the pthread kernel. */ SCLASS void *_usrstack SCLASS_PRESET(NULL); SCLASS struct kse *_kse_initial SCLASS_PRESET(NULL); SCLASS struct pthread *_thr_initial SCLASS_PRESET(NULL); /* For debugger */ SCLASS int _libkse_debug SCLASS_PRESET(0); SCLASS int _thread_activated SCLASS_PRESET(0); SCLASS int _thread_scope_system SCLASS_PRESET(0); /* List of all threads: */ SCLASS TAILQ_HEAD(, pthread) _thread_list SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_list)); /* List of threads needing GC: */ SCLASS TAILQ_HEAD(, pthread) _thread_gc_list SCLASS_PRESET(TAILQ_HEAD_INITIALIZER(_thread_gc_list)); SCLASS int _thread_active_threads SCLASS_PRESET(1); SCLASS TAILQ_HEAD(atfork_head, pthread_atfork) _thr_atfork_list; SCLASS pthread_mutex_t _thr_atfork_mutex; /* Default thread attributes: */ SCLASS struct pthread_attr _pthread_attr_default SCLASS_PRESET({ SCHED_RR, 0, TIMESLICE_USEC, THR_DEFAULT_PRIORITY, THR_CREATE_RUNNING, PTHREAD_CREATE_JOINABLE, NULL, NULL, NULL, /* stacksize */0, /* guardsize */0 }); /* Default mutex attributes: */ SCLASS struct pthread_mutex_attr _pthread_mutexattr_default SCLASS_PRESET({PTHREAD_MUTEX_DEFAULT, PTHREAD_PRIO_NONE, 0, 0 }); /* Default condition variable attributes: */ SCLASS struct pthread_cond_attr _pthread_condattr_default SCLASS_PRESET({COND_TYPE_FAST, 0}); /* Clock resolution in usec. */ SCLASS int _clock_res_usec SCLASS_PRESET(CLOCK_RES_USEC); /* Array of signal actions for this process: */ SCLASS struct sigaction _thread_sigact[_SIG_MAXSIG]; /* * Lock for above count of dummy handlers and for the process signal * mask and pending signal sets. */ SCLASS struct lock _thread_signal_lock; /* Pending signals and mask for this process: */ SCLASS sigset_t _thr_proc_sigpending; SCLASS siginfo_t _thr_proc_siginfo[_SIG_MAXSIG]; SCLASS pid_t _thr_pid SCLASS_PRESET(0); /* Garbage collector lock. */ SCLASS struct lock _gc_lock; SCLASS int _gc_check SCLASS_PRESET(0); SCLASS int _gc_count SCLASS_PRESET(0); SCLASS struct lock _mutex_static_lock; SCLASS struct lock _rwlock_static_lock; SCLASS struct lock _keytable_lock; SCLASS struct lock _thread_list_lock; -SCLASS int _thr_guard_default; -SCLASS int _thr_stack_default; -SCLASS int _thr_stack_initial; +SCLASS size_t _thr_guard_default; +SCLASS size_t _thr_stack_default; +SCLASS size_t _thr_stack_initial; SCLASS int _thr_page_size; SCLASS pthread_t _thr_sig_daemon; SCLASS int _thr_debug_flags SCLASS_PRESET(0); /* Undefine the storage class and preset specifiers: */ #undef SCLASS #undef SCLASS_PRESET /* * Function prototype definitions. */ __BEGIN_DECLS int _cond_reinit(pthread_cond_t *); struct kse *_kse_alloc(struct pthread *, int sys_scope); kse_critical_t _kse_critical_enter(void); void _kse_critical_leave(kse_critical_t); int _kse_in_critical(void); void _kse_free(struct pthread *, struct kse *); void _kse_init(void); struct kse_group *_kseg_alloc(struct pthread *); void _kse_lock_wait(struct lock *, struct lockuser *lu); void _kse_lock_wakeup(struct lock *, struct lockuser *lu); void _kse_single_thread(struct pthread *); int _kse_setthreaded(int); void _kseg_free(struct kse_group *); int _mutex_cv_lock(pthread_mutex_t *); int _mutex_cv_unlock(pthread_mutex_t *); void _mutex_notify_priochange(struct pthread *, struct pthread *, int); int _mutex_reinit(struct pthread_mutex *); void _mutex_unlock_private(struct pthread *); void _libpthread_init(struct pthread *); int _pq_alloc(struct pq_queue *, int, int); void _pq_free(struct pq_queue *); 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); struct pthread *_pq_first_debug(struct pq_queue *pq); void *_pthread_getspecific(pthread_key_t); int _pthread_key_create(pthread_key_t *, void (*) (void *)); int _pthread_key_delete(pthread_key_t); int _pthread_mutex_destroy(pthread_mutex_t *); int _pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *); int _pthread_mutex_lock(pthread_mutex_t *); int _pthread_mutex_trylock(pthread_mutex_t *); int _pthread_mutex_unlock(pthread_mutex_t *); int _pthread_mutexattr_init(pthread_mutexattr_t *); int _pthread_mutexattr_destroy(pthread_mutexattr_t *); int _pthread_mutexattr_settype(pthread_mutexattr_t *, int); int _pthread_once(pthread_once_t *, void (*) (void)); int _pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *); int _pthread_rwlock_destroy (pthread_rwlock_t *); struct pthread *_pthread_self(void); int _pthread_setspecific(pthread_key_t, const void *); void _pthread_yield(void); void _pthread_cleanup_push(void (*routine) (void *), void *routine_arg); void _pthread_cleanup_pop(int execute); struct pthread *_thr_alloc(struct pthread *); -void _thr_exit(char *, int, char *); +void _thr_exit(const char *, int, const char *) __dead2; void _thr_exit_cleanup(void); void _thr_lock_wait(struct lock *lock, struct lockuser *lu); void _thr_lock_wakeup(struct lock *lock, struct lockuser *lu); void _thr_mutex_reinit(pthread_mutex_t *); int _thr_ref_add(struct pthread *, struct pthread *, int); void _thr_ref_delete(struct pthread *, struct pthread *); void _thr_rtld_init(void); void _thr_rtld_fini(void); int _thr_schedule_add(struct pthread *, struct pthread *); void _thr_schedule_remove(struct pthread *, struct pthread *); void _thr_setrunnable(struct pthread *curthread, struct pthread *thread); struct kse_mailbox *_thr_setrunnable_unlocked(struct pthread *thread); struct kse_mailbox *_thr_sig_add(struct pthread *, int, siginfo_t *); void _thr_sig_dispatch(struct kse *, int, siginfo_t *); int _thr_stack_alloc(struct pthread_attr *); void _thr_stack_free(struct pthread_attr *); void _thr_exit_cleanup(void); void _thr_free(struct pthread *, struct pthread *); void _thr_gc(struct pthread *); void _thr_panic_exit(char *, int, char *); void _thread_cleanupspecific(void); void _thread_dump_info(void); void _thread_printf(int, const char *, ...); void _thr_sched_switch(struct pthread *); void _thr_sched_switch_unlocked(struct pthread *); void _thr_set_timeout(const struct timespec *); void _thr_seterrno(struct pthread *, int); -void _thr_sig_handler(int, siginfo_t *, ucontext_t *); +void _thr_sig_handler(int, siginfo_t *, void *); void _thr_sig_check_pending(struct pthread *); void _thr_sig_rundown(struct pthread *, ucontext_t *); void _thr_sig_send(struct pthread *pthread, int sig); void _thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf); void _thr_spinlock_init(void); void _thr_cancel_enter(struct pthread *); void _thr_cancel_leave(struct pthread *, int); int _thr_setconcurrency(int new_level); int _thr_setmaxconcurrency(void); void _thr_critical_enter(struct pthread *); void _thr_critical_leave(struct pthread *); int _thr_start_sig_daemon(void); int _thr_getprocsig(int sig, siginfo_t *siginfo); int _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo); void _thr_signal_init(void); void _thr_signal_deinit(void); void _thr_hash_add(struct pthread *); void _thr_hash_remove(struct pthread *); struct pthread *_thr_hash_find(struct pthread *); void _thr_finish_cancellation(void *arg); int _thr_sigonstack(void *sp); void _thr_debug_check_yield(struct pthread *); /* * Aliases for _pthread functions. Should be called instead of * originals if PLT replocation is unwanted at runtme. */ int _thr_cond_broadcast(pthread_cond_t *); int _thr_cond_signal(pthread_cond_t *); int _thr_cond_wait(pthread_cond_t *, pthread_mutex_t *); int _thr_mutex_lock(pthread_mutex_t *); int _thr_mutex_unlock(pthread_mutex_t *); int _thr_rwlock_rdlock (pthread_rwlock_t *); int _thr_rwlock_wrlock (pthread_rwlock_t *); int _thr_rwlock_unlock (pthread_rwlock_t *); /* #include */ #ifdef _SYS_AIO_H_ int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *); #endif /* #include */ #ifdef _SYS_FCNTL_H_ int __sys_fcntl(int, int, ...); int __sys_open(const char *, int, ...); #endif /* #include */ #ifdef _SYS_IOCTL_H_ int __sys_ioctl(int, unsigned long, ...); #endif /* #inclde */ #ifdef _SCHED_H_ int __sys_sched_yield(void); #endif /* #include */ #ifdef _SIGNAL_H_ int __sys_kill(pid_t, int); int __sys_sigaction(int, const struct sigaction *, struct sigaction *); int __sys_sigpending(sigset_t *); int __sys_sigprocmask(int, const sigset_t *, sigset_t *); int __sys_sigsuspend(const sigset_t *); int __sys_sigreturn(ucontext_t *); int __sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *); #endif /* #include */ #ifdef _SYS_SOCKET_H_ int __sys_accept(int, struct sockaddr *, socklen_t *); int __sys_connect(int, const struct sockaddr *, socklen_t); int __sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *, off_t *, int); #endif /* #include */ #ifdef _SYS_UIO_H_ ssize_t __sys_readv(int, const struct iovec *, int); ssize_t __sys_writev(int, const struct iovec *, int); #endif /* #include */ #ifdef _TIME_H_ int __sys_nanosleep(const struct timespec *, struct timespec *); #endif /* #include */ #ifdef _UNISTD_H_ int __sys_close(int); int __sys_execve(const char *, char * const *, char * const *); int __sys_fork(void); int __sys_fsync(int); pid_t __sys_getpid(void); int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); ssize_t __sys_read(int, void *, size_t); ssize_t __sys_write(int, const void *, size_t); void __sys_exit(int); int __sys_sigwait(const sigset_t *, int *); -int __sys_sigtimedwait(sigset_t *, siginfo_t *, struct timespec *); +int __sys_sigtimedwait(const sigset_t *, siginfo_t *, const struct timespec *); #endif /* #include */ #ifdef _SYS_POLL_H_ int __sys_poll(struct pollfd *, unsigned, int); #endif /* #include */ #ifdef _SYS_MMAN_H_ int __sys_msync(void *, size_t, int); #endif static __inline int _thr_dump_enabled(void) { return ((_thr_debug_flags & DBG_INFO_DUMP) != 0); } #endif /* !_THR_PRIVATE_H */ Index: head/lib/libkse/thread/thr_pselect.c =================================================================== --- head/lib/libkse/thread/thr_pselect.c (revision 174111) +++ head/lib/libkse/thread/thr_pselect.c (revision 174112) @@ -1,60 +1,64 @@ /*- * Copyright (c) 2002 Daniel M. Eischen * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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. * */ #include __FBSDID("$FreeBSD$"); +#include "namespace.h" #include #include - #include #include #include +#include "un-namespace.h" #include "thr_private.h" -extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, - const struct timespec *timo, const sigset_t *mask); +extern int __pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, + const struct timespec *timo, const sigset_t *mask); + +int _pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, + const struct timespec *timo, const sigset_t *mask); LT10_COMPAT_PRIVATE(_pselect); LT10_COMPAT_DEFAULT(pselect); __weak_reference(_pselect, pselect); int _pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *timo, const sigset_t *mask) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __pselect(count, rfds, wfds, efds, timo, mask); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_pspinlock.c =================================================================== --- head/lib/libkse/thread/thr_pspinlock.c (revision 174111) +++ head/lib/libkse/thread/thr_pspinlock.c (revision 174112) @@ -1,174 +1,176 @@ /*- * Copyright (c) 2003 David Xu * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ +#include "namespace.h" #include #include #include #include #include +#include "un-namespace.h" #include "atomic_ops.h" #include "thr_private.h" #define SPIN_COUNT 10000 LT10_COMPAT_PRIVATE(_pthread_spin_init); LT10_COMPAT_DEFAULT(pthread_spin_init); LT10_COMPAT_PRIVATE(_pthread_spin_destroy); LT10_COMPAT_DEFAULT(pthread_spin_destroy); LT10_COMPAT_PRIVATE(_pthread_spin_trylock); LT10_COMPAT_DEFAULT(pthread_spin_trylock); LT10_COMPAT_PRIVATE(_pthread_spin_lock); LT10_COMPAT_DEFAULT(pthread_spin_lock); LT10_COMPAT_PRIVATE(_pthread_spin_unlock); LT10_COMPAT_DEFAULT(pthread_spin_unlock); __weak_reference(_pthread_spin_init, pthread_spin_init); __weak_reference(_pthread_spin_destroy, pthread_spin_destroy); __weak_reference(_pthread_spin_trylock, pthread_spin_trylock); __weak_reference(_pthread_spin_lock, pthread_spin_lock); __weak_reference(_pthread_spin_unlock, pthread_spin_unlock); int _pthread_spin_init(pthread_spinlock_t *lock, int pshared) { struct pthread_spinlock *lck; int ret; if (lock == NULL || pshared != PTHREAD_PROCESS_PRIVATE) ret = EINVAL; else if ((lck = malloc(sizeof(struct pthread_spinlock))) == NULL) ret = ENOMEM; else { lck->s_lock = 0; lck->s_owner= NULL; *lock = lck; ret = 0; } return (ret); } int _pthread_spin_destroy(pthread_spinlock_t *lock) { int ret; if (lock == NULL || *lock == NULL) ret = EINVAL; else if ((*lock)->s_owner != NULL) ret = EBUSY; else { free(*lock); *lock = NULL; ret = 0; } return (ret); } int _pthread_spin_trylock(pthread_spinlock_t *lock) { struct pthread_spinlock *lck; struct pthread *self = _pthread_self(); int oldval, ret; if (lock == NULL || (lck = *lock) == NULL) ret = EINVAL; else if (lck->s_owner == self) ret = EDEADLK; else if (lck->s_lock != 0) ret = EBUSY; else { - atomic_swap_int((int *)&(lck)->s_lock, 1, &oldval); + atomic_swap_int(&(lck)->s_lock, 1, &oldval); if (oldval) ret = EBUSY; else { lck->s_owner = _pthread_self(); ret = 0; } } return (ret); } int _pthread_spin_lock(pthread_spinlock_t *lock) { struct pthread_spinlock *lck; struct pthread *self = _pthread_self(); int count, oldval, ret; if (lock == NULL || (lck = *lock) == NULL) ret = EINVAL; else if (lck->s_owner == self) ret = EDEADLK; else { do { count = SPIN_COUNT; while (lck->s_lock) { #ifdef __i386__ /* tell cpu we are spinning */ __asm __volatile("pause"); #endif if (--count <= 0) { count = SPIN_COUNT; _pthread_yield(); } } - atomic_swap_int((int *)&(lck)->s_lock, 1, &oldval); + atomic_swap_int(&(lck)->s_lock, 1, &oldval); } while (oldval); lck->s_owner = self; ret = 0; } return (ret); } int _pthread_spin_unlock(pthread_spinlock_t *lock) { struct pthread_spinlock *lck; int ret; if (lock == NULL || (lck = *lock) == NULL) ret = EINVAL; else { if (lck->s_owner != _pthread_self()) ret = EPERM; else { lck->s_owner = NULL; - atomic_swap_int((int *)&lck->s_lock, 0, &ret); + atomic_swap_int(&lck->s_lock, 0, &ret); ret = 0; } } return (ret); } Index: head/lib/libkse/thread/thr_raise.c =================================================================== --- head/lib/libkse/thread/thr_raise.c (revision 174111) +++ head/lib/libkse/thread/thr_raise.c (revision 174112) @@ -1,56 +1,60 @@ /* * Copyright (C) 2003 David Xu. * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ -#include +#include "namespace.h" #include +#include +#include "un-namespace.h" #include "thr_private.h" +int _raise(int sig); + LT10_COMPAT_PRIVATE(_raise); LT10_COMPAT_DEFAULT(raise); __weak_reference(_raise, raise); int _raise(int sig) { int ret; if (!_kse_isthreaded()) ret = kill(getpid(), sig); else { - ret = pthread_kill(pthread_self(), sig); + ret = _pthread_kill(_pthread_self(), sig); if (ret != 0) { errno = ret; ret = -1; } } return (ret); } Index: head/lib/libkse/thread/thr_read.c =================================================================== --- head/lib/libkse/thread/thr_read.c (revision 174111) +++ head/lib/libkse/thread/thr_read.c (revision 174112) @@ -1,56 +1,61 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ * */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" + +ssize_t __read(int fd, void *buf, size_t nbytes); LT10_COMPAT_PRIVATE(__read); LT10_COMPAT_DEFAULT(read); __weak_reference(__read, read); ssize_t __read(int fd, void *buf, size_t nbytes) { struct pthread *curthread = _get_curthread(); ssize_t ret; _thr_cancel_enter(curthread); ret = __sys_read(fd, buf, nbytes); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_readv.c =================================================================== --- head/lib/libkse/thread/thr_readv.c (revision 174111) +++ head/lib/libkse/thread/thr_readv.c (revision 174112) @@ -1,56 +1,61 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ * */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" + +ssize_t __readv(int fd, const struct iovec *iov, int iovcnt); LT10_COMPAT_PRIVATE(__readv); LT10_COMPAT_DEFAULT(readv); __weak_reference(__readv, readv); ssize_t __readv(int fd, const struct iovec *iov, int iovcnt) { struct pthread *curthread = _get_curthread(); ssize_t ret; _thr_cancel_enter(curthread); ret = __sys_readv(fd, iov, iovcnt); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_resume_np.c =================================================================== --- head/lib/libkse/thread/thr_resume_np.c (revision 174111) +++ head/lib/libkse/thread/thr_resume_np.c (revision 174112) @@ -1,109 +1,115 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" + +int _pthread_resume_np(pthread_t thread); +void _pthread_resume_all_np(void); static struct kse_mailbox *resume_common(struct pthread *); LT10_COMPAT_PRIVATE(_pthread_resume_np); LT10_COMPAT_DEFAULT(pthread_resume_np); LT10_COMPAT_PRIVATE(_pthread_resume_all_np); LT10_COMPAT_DEFAULT(pthread_resume_all_np); __weak_reference(_pthread_resume_np, pthread_resume_np); __weak_reference(_pthread_resume_all_np, pthread_resume_all_np); /* Resume a thread: */ int _pthread_resume_np(pthread_t thread) { struct pthread *curthread = _get_curthread(); struct kse_mailbox *kmbx; int ret; /* Add a reference to the thread: */ if ((ret = _thr_ref_add(curthread, thread, /*include dead*/0)) == 0) { /* Lock the threads scheduling queue: */ THR_SCHED_LOCK(curthread, thread); kmbx = resume_common(thread); THR_SCHED_UNLOCK(curthread, thread); _thr_ref_delete(curthread, thread); if (kmbx != NULL) kse_wakeup(kmbx); } return (ret); } void _pthread_resume_all_np(void) { struct pthread *curthread = _get_curthread(); struct pthread *thread; struct kse_mailbox *kmbx; kse_critical_t crit; /* Take the thread list lock: */ crit = _kse_critical_enter(); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock); TAILQ_FOREACH(thread, &_thread_list, tle) { if (thread != curthread) { THR_SCHED_LOCK(curthread, thread); kmbx = resume_common(thread); THR_SCHED_UNLOCK(curthread, thread); if (kmbx != NULL) kse_wakeup(kmbx); } } /* Release the thread list lock: */ KSE_LOCK_RELEASE(curthread->kse, &_thread_list_lock); _kse_critical_leave(crit); } static struct kse_mailbox * resume_common(struct pthread *thread) { /* Clear the suspend flag: */ thread->flags &= ~THR_FLAGS_SUSPENDED; /* * If the thread's state is suspended, that means it is * now runnable but not in any scheduling queue. Set the * state to running and insert it into the run queue. */ if (thread->state == PS_SUSPENDED) return (_thr_setrunnable_unlocked(thread)); else return (NULL); } Index: head/lib/libkse/thread/thr_rtld.c =================================================================== --- head/lib/libkse/thread/thr_rtld.c (revision 174111) +++ head/lib/libkse/thread/thr_rtld.c (revision 174112) @@ -1,302 +1,302 @@ /* * Copyright (c) 2001 Alexander Kabaev * 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 * in this position and unchanged. * 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$ */ #include #include #include "rtld_lock.h" #include "thr_private.h" static int _thr_rtld_clr_flag(int); static void *_thr_rtld_lock_create(void); static void _thr_rtld_lock_destroy(void *); static void _thr_rtld_lock_release(void *); static void _thr_rtld_rlock_acquire(void *); static int _thr_rtld_set_flag(int); static void _thr_rtld_wlock_acquire(void *); #ifdef NOTYET static void * _thr_rtld_lock_create(void) { pthread_rwlock_t prwlock; if (_pthread_rwlock_init(&prwlock, NULL)) return (NULL); return (prwlock); } static void _thr_rtld_lock_destroy(void *lock) { pthread_rwlock_t prwlock; prwlock = (pthread_rwlock_t)lock; if (prwlock != NULL) _pthread_rwlock_destroy(&prwlock); } static void _thr_rtld_rlock_acquire(void *lock) { pthread_rwlock_t prwlock; prwlock = (pthread_rwlock_t)lock; _thr_rwlock_rdlock(&prwlock); } static void _thr_rtld_wlock_acquire(void *lock) { pthread_rwlock_t prwlock; prwlock = (pthread_rwlock_t)lock; _thr_rwlock_wrlock(&prwlock); } static void _thr_rtld_lock_release(void *lock) { pthread_rwlock_t prwlock; prwlock = (pthread_rwlock_t)lock; _thr_rwlock_unlock(&prwlock); } static int _thr_rtld_set_flag(int mask) { struct pthread *curthread; int bits; curthread = _get_curthread(); if (curthread != NULL) { bits = curthread->rtld_bits; curthread->rtld_bits |= mask; } else { bits = 0; PANIC("No current thread in rtld call"); } return (bits); } static int _thr_rtld_clr_flag(int mask) { struct pthread *curthread; int bits; curthread = _get_curthread(); if (curthread != NULL) { bits = curthread->rtld_bits; curthread->rtld_bits &= ~mask; } else { bits = 0; PANIC("No current thread in rtld call"); } return (bits); } void _thr_rtld_init(void) { struct RtldLockInfo li; li.lock_create = _thr_rtld_lock_create; li.lock_destroy = _thr_rtld_lock_destroy; li.rlock_acquire = _thr_rtld_rlock_acquire; li.wlock_acquire = _thr_rtld_wlock_acquire; li.lock_release = _thr_rtld_lock_release; li.thread_set_flag = _thr_rtld_set_flag; li.thread_clr_flag = _thr_rtld_clr_flag; li.at_fork = NULL; _rtld_thread_init(&li); } void _thr_rtld_fini(void) { _rtld_thread_init(NULL); } #endif struct rtld_kse_lock { struct lock lck; struct kse *owner; kse_critical_t crit; int count; int write; }; static void * _thr_rtld_lock_create(void) { struct rtld_kse_lock *l; if ((l = malloc(sizeof(struct rtld_kse_lock))) != NULL) { _lock_init(&l->lck, LCK_ADAPTIVE, _kse_lock_wait, _kse_lock_wakeup, calloc); l->owner = NULL; l->count = 0; l->write = 0; } return (l); } static void -_thr_rtld_lock_destroy(void *lock) +_thr_rtld_lock_destroy(void *lock __unused) { /* XXX We really can not free memory after a fork() */ #if 0 struct rtld_kse_lock *l; l = (struct rtld_kse_lock *)lock; _lock_destroy(&l->lck); free(l); #endif return; } static void _thr_rtld_rlock_acquire(void *lock) { struct rtld_kse_lock *l; kse_critical_t crit; struct kse *curkse; l = (struct rtld_kse_lock *)lock; crit = _kse_critical_enter(); curkse = _get_curkse(); if (l->owner == curkse) { l->count++; _kse_critical_leave(crit); /* probably not necessary */ } else { KSE_LOCK_ACQUIRE(curkse, &l->lck); l->crit = crit; l->owner = curkse; l->count = 1; l->write = 0; } } static void _thr_rtld_wlock_acquire(void *lock) { struct rtld_kse_lock *l; kse_critical_t crit; struct kse *curkse; l = (struct rtld_kse_lock *)lock; crit = _kse_critical_enter(); curkse = _get_curkse(); if (l->owner == curkse) { _kse_critical_leave(crit); PANIC("Recursive write lock attempt on rtld lock"); } else { KSE_LOCK_ACQUIRE(curkse, &l->lck); l->crit = crit; l->owner = curkse; l->count = 1; l->write = 1; } } static void _thr_rtld_lock_release(void *lock) { struct rtld_kse_lock *l; kse_critical_t crit; struct kse *curkse; l = (struct rtld_kse_lock *)lock; crit = _kse_critical_enter(); curkse = _get_curkse(); if (l->owner != curkse) { /* * We might want to forcibly unlock the rtld lock * and/or disable threaded mode so there is better * chance that the panic will work. Otherwise, * we could end up trying to take the rtld lock * again. */ _kse_critical_leave(crit); PANIC("Attempt to unlock rtld lock when not owner."); } else { l->count--; if (l->count == 0) { /* * If there ever is a count associated with * _kse_critical_leave(), we'll need to add * another call to it here with the crit * value from above. */ crit = l->crit; l->owner = NULL; l->write = 0; KSE_LOCK_RELEASE(curkse, &l->lck); } _kse_critical_leave(crit); } } static int -_thr_rtld_set_flag(int mask) +_thr_rtld_set_flag(int mask __unused) { return (0); } static int -_thr_rtld_clr_flag(int mask) +_thr_rtld_clr_flag(int mask __unused) { return (0); } void _thr_rtld_init(void) { struct RtldLockInfo li; li.lock_create = _thr_rtld_lock_create; li.lock_destroy = _thr_rtld_lock_destroy; li.rlock_acquire = _thr_rtld_rlock_acquire; li.wlock_acquire = _thr_rtld_wlock_acquire; li.lock_release = _thr_rtld_lock_release; li.thread_set_flag = _thr_rtld_set_flag; li.thread_clr_flag = _thr_rtld_clr_flag; li.at_fork = NULL; _rtld_thread_init(&li); } void _thr_rtld_fini(void) { _rtld_thread_init(NULL); } Index: head/lib/libkse/thread/thr_rwlock.c =================================================================== --- head/lib/libkse/thread/thr_rwlock.c (revision 174111) +++ head/lib/libkse/thread/thr_rwlock.c (revision 174112) @@ -1,438 +1,438 @@ /*- * Copyright (c) 1998 Alex Nash * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ +#include "namespace.h" #include #include #include - -#include "namespace.h" #include #include "un-namespace.h" #include "thr_private.h" /* maximum number of times a read lock may be obtained */ #define MAX_READ_LOCKS (INT_MAX - 1) LT10_COMPAT_PRIVATE(_pthread_rwlock_destroy); LT10_COMPAT_DEFAULT(pthread_rwlock_destroy); LT10_COMPAT_PRIVATE(_pthread_rwlock_init); LT10_COMPAT_DEFAULT(pthread_rwlock_init); LT10_COMPAT_PRIVATE(_pthread_rwlock_rdlock); LT10_COMPAT_DEFAULT(pthread_rwlock_rdlock); LT10_COMPAT_PRIVATE(_pthread_rwlock_timedrdlock); LT10_COMPAT_DEFAULT(pthread_rwlock_timedrdlock); LT10_COMPAT_PRIVATE(_pthread_rwlock_tryrdlock); LT10_COMPAT_DEFAULT(pthread_rwlock_tryrdlock); LT10_COMPAT_PRIVATE(_pthread_rwlock_trywrlock); LT10_COMPAT_DEFAULT(pthread_rwlock_trywrlock); LT10_COMPAT_PRIVATE(_pthread_rwlock_unlock); LT10_COMPAT_DEFAULT(pthread_rwlock_unlock); LT10_COMPAT_PRIVATE(_pthread_rwlock_wrlock); LT10_COMPAT_DEFAULT(pthread_rwlock_wrlock); LT10_COMPAT_PRIVATE(_pthread_rwlock_timedwrlock); LT10_COMPAT_DEFAULT(pthread_rwlock_timedwrlock); __weak_reference(_pthread_rwlock_destroy, pthread_rwlock_destroy); __weak_reference(_pthread_rwlock_init, pthread_rwlock_init); __weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); __weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); __weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); __weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); __weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); __weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); __weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); /* * Prototypes */ static int init_static(pthread_rwlock_t *rwlock); static int init_static(pthread_rwlock_t *rwlock) { struct pthread *thread = _get_curthread(); int ret; THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock); if (*rwlock == NULL) ret = _pthread_rwlock_init(rwlock, NULL); else ret = 0; THR_LOCK_RELEASE(thread, &_rwlock_static_lock); return (ret); } int _pthread_rwlock_destroy (pthread_rwlock_t *rwlock) { int ret; if (rwlock == NULL) ret = EINVAL; else { pthread_rwlock_t prwlock; prwlock = *rwlock; _pthread_mutex_destroy(&prwlock->lock); _pthread_cond_destroy(&prwlock->read_signal); _pthread_cond_destroy(&prwlock->write_signal); free(prwlock); *rwlock = NULL; ret = 0; } return (ret); } int -_pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) +_pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr __unused) { pthread_rwlock_t prwlock; int ret; /* allocate rwlock object */ prwlock = (pthread_rwlock_t)malloc(sizeof(struct pthread_rwlock)); if (prwlock == NULL) return (ENOMEM); /* initialize the lock */ if ((ret = _pthread_mutex_init(&prwlock->lock, NULL)) != 0) free(prwlock); else { /* initialize the read condition signal */ ret = _pthread_cond_init(&prwlock->read_signal, NULL); if (ret != 0) { _pthread_mutex_destroy(&prwlock->lock); free(prwlock); } else { /* initialize the write condition signal */ ret = _pthread_cond_init(&prwlock->write_signal, NULL); if (ret != 0) { _pthread_cond_destroy(&prwlock->read_signal); _pthread_mutex_destroy(&prwlock->lock); free(prwlock); } else { /* success */ prwlock->state = 0; prwlock->blocked_writers = 0; *rwlock = prwlock; } } } return (ret); } static int rwlock_rdlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) { pthread_rwlock_t prwlock; struct pthread *curthread; int ret; if (rwlock == NULL) return (EINVAL); prwlock = *rwlock; /* check for static initialization */ if (prwlock == NULL) { if ((ret = init_static(rwlock)) != 0) return (ret); prwlock = *rwlock; } /* grab the monitor lock */ if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0) return (ret); /* check lock count */ if (prwlock->state == MAX_READ_LOCKS) { _thr_mutex_unlock(&prwlock->lock); return (EAGAIN); } curthread = _get_curthread(); if ((curthread->rdlock_count > 0) && (prwlock->state > 0)) { /* * To avoid having to track all the rdlocks held by * a thread or all of the threads that hold a rdlock, * we keep a simple count of all the rdlocks held by * a thread. If a thread holds any rdlocks it is * possible that it is attempting to take a recursive * rdlock. If there are blocked writers and precedence * is given to them, then that would result in the thread * deadlocking. So allowing a thread to take the rdlock * when it already has one or more rdlocks avoids the * deadlock. I hope the reader can follow that logic ;-) */ ; /* nothing needed */ } else { /* give writers priority over readers */ while (prwlock->blocked_writers || prwlock->state < 0) { if (abstime) ret = _pthread_cond_timedwait (&prwlock->read_signal, &prwlock->lock, abstime); else ret = _thr_cond_wait(&prwlock->read_signal, &prwlock->lock); if (ret != 0) { /* can't do a whole lot if this fails */ _thr_mutex_unlock(&prwlock->lock); return (ret); } } } curthread->rdlock_count++; prwlock->state++; /* indicate we are locked for reading */ /* * Something is really wrong if this call fails. Returning * error won't do because we've already obtained the read * lock. Decrementing 'state' is no good because we probably * don't have the monitor lock. */ _thr_mutex_unlock(&prwlock->lock); return (ret); } int _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) { return (rwlock_rdlock_common(rwlock, NULL)); } __strong_reference(_pthread_rwlock_rdlock, _thr_rwlock_rdlock); int _pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, const struct timespec *abstime) { return (rwlock_rdlock_common(rwlock, abstime)); } int _pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) { struct pthread *curthread; pthread_rwlock_t prwlock; int ret; if (rwlock == NULL) return (EINVAL); prwlock = *rwlock; /* check for static initialization */ if (prwlock == NULL) { if ((ret = init_static(rwlock)) != 0) return (ret); prwlock = *rwlock; } /* grab the monitor lock */ if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) return (ret); curthread = _get_curthread(); if (prwlock->state == MAX_READ_LOCKS) ret = EAGAIN; else if ((curthread->rdlock_count > 0) && (prwlock->state > 0)) { /* see comment for pthread_rwlock_rdlock() */ curthread->rdlock_count++; prwlock->state++; } /* give writers priority over readers */ else if (prwlock->blocked_writers || prwlock->state < 0) ret = EBUSY; else { curthread->rdlock_count++; prwlock->state++; /* indicate we are locked for reading */ } /* see the comment on this in pthread_rwlock_rdlock */ _pthread_mutex_unlock(&prwlock->lock); return (ret); } int _pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) { pthread_rwlock_t prwlock; int ret; if (rwlock == NULL) return (EINVAL); prwlock = *rwlock; /* check for static initialization */ if (prwlock == NULL) { if ((ret = init_static(rwlock)) != 0) return (ret); prwlock = *rwlock; } /* grab the monitor lock */ if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) return (ret); if (prwlock->state != 0) ret = EBUSY; else /* indicate we are locked for writing */ prwlock->state = -1; /* see the comment on this in pthread_rwlock_rdlock */ _pthread_mutex_unlock(&prwlock->lock); return (ret); } int _pthread_rwlock_unlock (pthread_rwlock_t *rwlock) { struct pthread *curthread; pthread_rwlock_t prwlock; int ret; if (rwlock == NULL) return (EINVAL); prwlock = *rwlock; if (prwlock == NULL) return (EINVAL); /* grab the monitor lock */ if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0) return (ret); curthread = _get_curthread(); if (prwlock->state > 0) { curthread->rdlock_count--; prwlock->state--; if (prwlock->state == 0 && prwlock->blocked_writers) ret = _thr_cond_signal(&prwlock->write_signal); } else if (prwlock->state < 0) { prwlock->state = 0; if (prwlock->blocked_writers) ret = _thr_cond_signal(&prwlock->write_signal); else ret = _thr_cond_broadcast(&prwlock->read_signal); } else ret = EINVAL; /* see the comment on this in pthread_rwlock_rdlock */ _thr_mutex_unlock(&prwlock->lock); return (ret); } __strong_reference(_pthread_rwlock_unlock, _thr_rwlock_unlock); static int rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) { pthread_rwlock_t prwlock; int ret; if (rwlock == NULL) return (EINVAL); prwlock = *rwlock; /* check for static initialization */ if (prwlock == NULL) { if ((ret = init_static(rwlock)) != 0) return (ret); prwlock = *rwlock; } /* grab the monitor lock */ if ((ret = _thr_mutex_lock(&prwlock->lock)) != 0) return (ret); while (prwlock->state != 0) { prwlock->blocked_writers++; if (abstime != NULL) ret = _pthread_cond_timedwait(&prwlock->write_signal, &prwlock->lock, abstime); else ret = _thr_cond_wait(&prwlock->write_signal, &prwlock->lock); if (ret != 0) { prwlock->blocked_writers--; _thr_mutex_unlock(&prwlock->lock); return (ret); } prwlock->blocked_writers--; } /* indicate we are locked for writing */ prwlock->state = -1; /* see the comment on this in pthread_rwlock_rdlock */ _thr_mutex_unlock(&prwlock->lock); return (ret); } int _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) { return (rwlock_wrlock_common (rwlock, NULL)); } __strong_reference(_pthread_rwlock_wrlock, _thr_rwlock_wrlock); int _pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, const struct timespec *abstime) { return (rwlock_wrlock_common (rwlock, abstime)); } Index: head/lib/libkse/thread/thr_rwlockattr.c =================================================================== --- head/lib/libkse/thread/thr_rwlockattr.c (revision 174111) +++ head/lib/libkse/thread/thr_rwlockattr.c (revision 174112) @@ -1,107 +1,108 @@ /*- * Copyright (c) 1998 Alex Nash * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ +#include "namespace.h" #include #include - #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_rwlockattr_destroy); LT10_COMPAT_DEFAULT(pthread_rwlockattr_destroy); LT10_COMPAT_PRIVATE(_pthread_rwlockattr_getpshared); LT10_COMPAT_DEFAULT(pthread_rwlockattr_getpshared); LT10_COMPAT_PRIVATE(_pthread_rwlockattr_init); LT10_COMPAT_DEFAULT(pthread_rwlockattr_init); LT10_COMPAT_PRIVATE(_pthread_rwlockattr_setpshared); LT10_COMPAT_DEFAULT(pthread_rwlockattr_setpshared); __weak_reference(_pthread_rwlockattr_destroy, pthread_rwlockattr_destroy); __weak_reference(_pthread_rwlockattr_getpshared, pthread_rwlockattr_getpshared); __weak_reference(_pthread_rwlockattr_init, pthread_rwlockattr_init); __weak_reference(_pthread_rwlockattr_setpshared, pthread_rwlockattr_setpshared); int _pthread_rwlockattr_destroy(pthread_rwlockattr_t *rwlockattr) { pthread_rwlockattr_t prwlockattr; if (rwlockattr == NULL) return(EINVAL); prwlockattr = *rwlockattr; if (prwlockattr == NULL) return(EINVAL); free(prwlockattr); return(0); } int _pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *rwlockattr, int *pshared) { *pshared = (*rwlockattr)->pshared; return(0); } int _pthread_rwlockattr_init(pthread_rwlockattr_t *rwlockattr) { pthread_rwlockattr_t prwlockattr; if (rwlockattr == NULL) return(EINVAL); prwlockattr = (pthread_rwlockattr_t) malloc(sizeof(struct pthread_rwlockattr)); if (prwlockattr == NULL) return(ENOMEM); prwlockattr->pshared = PTHREAD_PROCESS_PRIVATE; *rwlockattr = prwlockattr; return(0); } int _pthread_rwlockattr_setpshared(pthread_rwlockattr_t *rwlockattr, int pshared) { /* Only PTHREAD_PROCESS_PRIVATE is supported. */ if (pshared != PTHREAD_PROCESS_PRIVATE) return(EINVAL); (*rwlockattr)->pshared = pshared; return(0); } Index: head/lib/libkse/thread/thr_select.c =================================================================== --- head/lib/libkse/thread/thr_select.c (revision 174111) +++ head/lib/libkse/thread/thr_select.c (revision 174112) @@ -1,65 +1,71 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" +int __select(int numfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout); + LT10_COMPAT_PRIVATE(__select); LT10_COMPAT_DEFAULT(select); __weak_reference(__select, select); int __select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { struct pthread *curthread = _get_curthread(); struct timespec ts; int ret; if (numfds == 0 && timeout != NULL) { TIMEVAL_TO_TIMESPEC(timeout, &ts); - return nanosleep(&ts, NULL); + ret = _nanosleep(&ts, NULL); } else { _thr_cancel_enter(curthread); ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout); _thr_cancel_leave(curthread, 1); } - return ret; + return (ret); } Index: head/lib/libkse/thread/thr_self.c =================================================================== --- head/lib/libkse/thread/thr_self.c (revision 174111) +++ head/lib/libkse/thread/thr_self.c (revision 174112) @@ -1,47 +1,50 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_self); LT10_COMPAT_DEFAULT(pthread_self); __weak_reference(_pthread_self, pthread_self); pthread_t _pthread_self(void) { if (_thr_initial == NULL) _libpthread_init(NULL); /* Return the running thread pointer: */ return (_get_curthread()); } Index: head/lib/libkse/thread/thr_seterrno.c =================================================================== --- head/lib/libkse/thread/thr_seterrno.c (revision 174111) +++ head/lib/libkse/thread/thr_seterrno.c (revision 174112) @@ -1,56 +1,61 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include +#include "un-namespace.h" #include "thr_private.h" /* * This function needs to reference the global error variable which is * normally hidden from the user. */ #ifdef errno #undef errno; #endif extern int errno; + +void _thread_seterrno(pthread_t thread, int error); void _thread_seterrno(pthread_t thread, int error) { /* Check for the initial thread: */ if (thread == _thr_initial) /* The initial thread always uses the global error variable: */ errno = error; else /* * Threads other than the initial thread always use the error * field in the thread structureL */ thread->error = error; } Index: head/lib/libkse/thread/thr_setprio.c =================================================================== --- head/lib/libkse/thread/thr_setprio.c (revision 174111) +++ head/lib/libkse/thread/thr_setprio.c (revision 174112) @@ -1,52 +1,57 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include +#include "un-namespace.h" #include "thr_private.h" +int _pthread_setprio(pthread_t pthread, int prio); + LT10_COMPAT_PRIVATE(_pthread_setprio); LT10_COMPAT_DEFAULT(pthread_setprio); __weak_reference(_pthread_setprio, pthread_setprio); int _pthread_setprio(pthread_t pthread, int prio) { int ret, policy; struct sched_param param; - if ((ret = pthread_getschedparam(pthread, &policy, ¶m)) == 0) { + if ((ret = _pthread_getschedparam(pthread, &policy, ¶m)) == 0) { param.sched_priority = prio; - ret = pthread_setschedparam(pthread, policy, ¶m); + ret = _pthread_setschedparam(pthread, policy, ¶m); } /* Return the error status: */ return (ret); } Index: head/lib/libkse/thread/thr_setschedparam.c =================================================================== --- head/lib/libkse/thread/thr_setschedparam.c (revision 174111) +++ head/lib/libkse/thread/thr_setschedparam.c (revision 174112) @@ -1,139 +1,142 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_setschedparam); LT10_COMPAT_DEFAULT(pthread_setschedparam); __weak_reference(_pthread_setschedparam, pthread_setschedparam); int _pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *param) { struct pthread *curthread = _get_curthread(); int in_syncq; int in_readyq = 0; int old_prio; int ret = 0; if ((param == NULL) || (policy < SCHED_FIFO) || (policy > SCHED_RR)) { /* Return an invalid argument error: */ ret = EINVAL; } else if ((param->sched_priority < THR_MIN_PRIORITY) || (param->sched_priority > THR_MAX_PRIORITY)) { /* Return an unsupported value error. */ ret = ENOTSUP; /* Find the thread in the list of active threads: */ } else if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/0)) == 0) { /* * Lock the threads scheduling queue while we change * its priority: */ THR_SCHED_LOCK(curthread, pthread); if ((pthread->state == PS_DEAD) || (pthread->state == PS_DEADLOCK) || ((pthread->flags & THR_FLAGS_EXITING) != 0)) { THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); return (ESRCH); } in_syncq = pthread->sflags & THR_FLAGS_IN_SYNCQ; /* Set the scheduling policy: */ pthread->attr.sched_policy = policy; if (param->sched_priority == THR_BASE_PRIORITY(pthread->base_priority)) /* * There is nothing to do; unlock the threads * scheduling queue. */ THR_SCHED_UNLOCK(curthread, pthread); else { /* * Remove the thread from its current priority * queue before any adjustments are made to its * active priority: */ old_prio = pthread->active_priority; if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0) { in_readyq = 1; THR_RUNQ_REMOVE(pthread); } /* Set the thread base priority: */ pthread->base_priority &= (THR_SIGNAL_PRIORITY | THR_RT_PRIORITY); pthread->base_priority = param->sched_priority; /* Recalculate the active priority: */ pthread->active_priority = MAX(pthread->base_priority, pthread->inherited_priority); if (in_readyq) { if ((pthread->priority_mutex_count > 0) && (old_prio > pthread->active_priority)) { /* * POSIX states that if the priority is * being lowered, the thread must be * inserted at the head of the queue for * its priority if it owns any priority * protection or inheritence mutexes. */ THR_RUNQ_INSERT_HEAD(pthread); } else THR_RUNQ_INSERT_TAIL(pthread); } /* Unlock the threads scheduling queue: */ THR_SCHED_UNLOCK(curthread, pthread); /* * Check for any mutex priority adjustments. This * includes checking for a priority mutex on which * this thread is waiting. */ _mutex_notify_priochange(curthread, pthread, in_syncq); } _thr_ref_delete(curthread, pthread); } return (ret); } Index: head/lib/libkse/thread/thr_sig.c =================================================================== --- head/lib/libkse/thread/thr_sig.c (revision 174111) +++ head/lib/libkse/thread/thr_sig.c (revision 174112) @@ -1,1250 +1,1255 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" /* Prototypes: */ static inline void build_siginfo(siginfo_t *info, int signo); #ifndef SYSTEM_SCOPE_ONLY static struct pthread *thr_sig_find(struct kse *curkse, int sig, siginfo_t *info); #endif static inline void thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf); static inline void thr_sigframe_save(struct pthread *thread, struct pthread_sigframe *psf); #define SA_KILL 0x01 /* terminates process by default */ #define SA_STOP 0x02 #define SA_CONT 0x04 static int sigproptbl[NSIG] = { SA_KILL, /* SIGHUP */ SA_KILL, /* SIGINT */ SA_KILL, /* SIGQUIT */ SA_KILL, /* SIGILL */ SA_KILL, /* SIGTRAP */ SA_KILL, /* SIGABRT */ SA_KILL, /* SIGEMT */ SA_KILL, /* SIGFPE */ SA_KILL, /* SIGKILL */ SA_KILL, /* SIGBUS */ SA_KILL, /* SIGSEGV */ SA_KILL, /* SIGSYS */ SA_KILL, /* SIGPIPE */ SA_KILL, /* SIGALRM */ SA_KILL, /* SIGTERM */ 0, /* SIGURG */ SA_STOP, /* SIGSTOP */ SA_STOP, /* SIGTSTP */ SA_CONT, /* SIGCONT */ 0, /* SIGCHLD */ SA_STOP, /* SIGTTIN */ SA_STOP, /* SIGTTOU */ 0, /* SIGIO */ SA_KILL, /* SIGXCPU */ SA_KILL, /* SIGXFSZ */ SA_KILL, /* SIGVTALRM */ SA_KILL, /* SIGPROF */ 0, /* SIGWINCH */ 0, /* SIGINFO */ SA_KILL, /* SIGUSR1 */ SA_KILL /* SIGUSR2 */ }; /* #define DEBUG_SIGNAL */ #ifdef DEBUG_SIGNAL #define DBG_MSG stdout_debug #else #define DBG_MSG(x...) #endif /* * Signal setup and delivery. * * 1) Delivering signals to threads in the same KSE. * These signals are sent by upcall events and are set in the * km_sigscaught field of the KSE mailbox. Since these signals * are received while operating on the KSE stack, they can be * delivered either by using signalcontext() to add a stack frame * to the target thread's stack, or by adding them in the thread's * pending set and having the thread run them down after it * 2) Delivering signals to threads in other KSEs/KSEGs. * 3) Delivering signals to threads in critical regions. * 4) Delivering signals to threads after they change their signal masks. * * Methods of delivering signals. * * 1) Add a signal frame to the thread's saved context. * 2) Add the signal to the thread structure, mark the thread as * having signals to handle, and let the thread run them down * after it resumes from the KSE scheduler. * * Problem with 1). You can't do this to a running thread or a * thread in a critical region. * * Problem with 2). You can't do this to a thread that doesn't * yield in some way (explicitly enters the scheduler). A thread * blocked in the kernel or a CPU hungry thread will not see the * signal without entering the scheduler. * * The solution is to use both 1) and 2) to deliver signals: * * o Thread in critical region - use 2). When the thread * leaves the critical region it will check to see if it * has pending signals and run them down. * * o Thread enters scheduler explicitly - use 2). The thread * can check for pending signals after it returns from the * the scheduler. * * o Thread is running and not current thread - use 2). When the * thread hits a condition specified by one of the other bullets, * the signal will be delivered. * * o Thread is running and is current thread (e.g., the thread * has just changed its signal mask and now sees that it has * pending signals) - just run down the pending signals. * * o Thread is swapped out due to quantum expiration - use 1) * * o Thread is blocked in kernel - kse_thr_wakeup() and then * use 1) */ /* * Rules for selecting threads for signals received: * * 1) If the signal is a sychronous signal, it is delivered to * the generating (current thread). If the thread has the * signal masked, it is added to the threads pending signal * set until the thread unmasks it. * * 2) A thread in sigwait() where the signal is in the thread's * waitset. * * 3) A thread in sigsuspend() where the signal is not in the * thread's suspended signal mask. * * 4) Any thread (first found/easiest to deliver) that has the * signal unmasked. */ #ifndef SYSTEM_SCOPE_ONLY static void * -sig_daemon(void *arg /* Unused */) +sig_daemon(void *arg __unused) { int i; kse_critical_t crit; struct timespec ts; sigset_t set; struct kse *curkse; struct pthread *curthread = _get_curthread(); DBG_MSG("signal daemon started(%p)\n", curthread); curthread->name = strdup("signal thread"); crit = _kse_critical_enter(); curkse = _get_curkse(); /* * Daemon thread is a bound thread and we must be created with * all signals masked */ #if 0 SIGFILLSET(set); __sys_sigprocmask(SIG_SETMASK, &set, NULL); #endif __sys_sigpending(&set); ts.tv_sec = 0; ts.tv_nsec = 0; while (1) { KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock); _thr_proc_sigpending = set; KSE_LOCK_RELEASE(curkse, &_thread_signal_lock); for (i = 1; i <= _SIG_MAXSIG; i++) { if (SIGISMEMBER(set, i) != 0) _thr_sig_dispatch(curkse, i, NULL /* no siginfo */); } ts.tv_sec = 30; ts.tv_nsec = 0; curkse->k_kcb->kcb_kmbx.km_flags = KMF_NOUPCALL | KMF_NOCOMPLETED | KMF_WAITSIGEVENT; kse_release(&ts); curkse->k_kcb->kcb_kmbx.km_flags = 0; set = curkse->k_kcb->kcb_kmbx.km_sigscaught; } return (0); } /* Utility function to create signal daemon thread */ int _thr_start_sig_daemon(void) { pthread_attr_t attr; sigset_t sigset, oldset; SIGFILLSET(sigset); - pthread_sigmask(SIG_SETMASK, &sigset, &oldset); - pthread_attr_init(&attr); - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + _pthread_sigmask(SIG_SETMASK, &sigset, &oldset); + _pthread_attr_init(&attr); + _pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); attr->flags |= THR_SIGNAL_THREAD; /* sigmask will be inherited */ - if (pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL)) + if (_pthread_create(&_thr_sig_daemon, &attr, sig_daemon, NULL)) PANIC("can not create signal daemon thread!\n"); - pthread_attr_destroy(&attr); - pthread_sigmask(SIG_SETMASK, &oldset, NULL); + _pthread_attr_destroy(&attr); + _pthread_sigmask(SIG_SETMASK, &oldset, NULL); return (0); } /* * This signal handler only delivers asynchronous signals. * This must be called with upcalls disabled and without * holding any locks. */ void _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info) { struct kse_mailbox *kmbx; struct pthread *thread; DBG_MSG(">>> _thr_sig_dispatch(%d)\n", sig); /* Check if the signal requires a dump of thread information: */ if (_thr_dump_enabled() && (sig == SIGINFO)) { /* Dump thread information to file: */ _thread_dump_info(); } while ((thread = thr_sig_find(curkse, sig, info)) != NULL) { /* * Setup the target thread to receive the signal: */ DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread); KSE_SCHED_LOCK(curkse, thread->kseg); if ((thread->state == PS_DEAD) || (thread->state == PS_DEADLOCK) || THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) { KSE_SCHED_UNLOCK(curkse, thread->kseg); _thr_ref_delete(NULL, thread); } else if (SIGISMEMBER(thread->sigmask, sig)) { KSE_SCHED_UNLOCK(curkse, thread->kseg); _thr_ref_delete(NULL, thread); } else { kmbx = _thr_sig_add(thread, sig, info); KSE_SCHED_UNLOCK(curkse, thread->kseg); _thr_ref_delete(NULL, thread); if (kmbx != NULL) kse_wakeup(kmbx); break; } } DBG_MSG("<<< _thr_sig_dispatch\n"); } #endif /* ! SYSTEM_SCOPE_ONLY */ static __inline int sigprop(int sig) { if (sig > 0 && sig < NSIG) return (sigproptbl[_SIG_IDX(sig)]); return (0); } typedef void (*ohandler)(int sig, int code, struct sigcontext *scp, char *addr, __sighandler_t *catcher); void -_thr_sig_handler(int sig, siginfo_t *info, ucontext_t *ucp) +_thr_sig_handler(int sig, siginfo_t *info, void *ucp_arg) { struct pthread_sigframe psf; __siginfohandler_t *sigfunc; struct pthread *curthread; struct kse *curkse; + ucontext_t *ucp; struct sigaction act; int sa_flags, err_save; err_save = errno; + ucp = (ucontext_t *)ucp_arg; DBG_MSG(">>> _thr_sig_handler(%d)\n", sig); curthread = _get_curthread(); if (curthread == NULL) PANIC("No current thread.\n"); if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)) PANIC("Thread is not system scope.\n"); if (curthread->flags & THR_FLAGS_EXITING) { errno = err_save; return; } curkse = _get_curkse(); /* * If thread is in critical region or if thread is on * the way of state transition, then latch signal into buffer. */ if (_kse_in_critical() || THR_IN_CRITICAL(curthread) || curthread->state != PS_RUNNING) { DBG_MSG(">>> _thr_sig_handler(%d) in critical\n", sig); curthread->siginfo[sig-1] = *info; curthread->check_pending = 1; curkse->k_sigseqno++; SIGADDSET(curthread->sigpend, sig); /* * If the kse is on the way to idle itself, but * we have signal ready, we should prevent it * to sleep, kernel will latch the wakeup request, * so kse_release will return from kernel immediately. */ if (KSE_IS_IDLE(curkse)) kse_wakeup(&curkse->k_kcb->kcb_kmbx); errno = err_save; return; } /* Check if the signal requires a dump of thread information: */ if (_thr_dump_enabled() && (sig == SIGINFO)) { /* Dump thread information to file: */ _thread_dump_info(); } /* Check the threads previous state: */ curthread->critical_count++; if (curthread->sigbackout != NULL) curthread->sigbackout((void *)curthread); curthread->critical_count--; thr_sigframe_save(curthread, &psf); THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared."); _kse_critical_enter(); /* Get a fresh copy of signal mask */ __sys_sigprocmask(SIG_BLOCK, NULL, &curthread->sigmask); KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock); sigfunc = _thread_sigact[sig - 1].sa_sigaction; sa_flags = _thread_sigact[sig - 1].sa_flags; if (sa_flags & SA_RESETHAND) { act.sa_handler = SIG_DFL; act.sa_flags = SA_RESTART; SIGEMPTYSET(act.sa_mask); __sys_sigaction(sig, &act, NULL); __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]); } KSE_LOCK_RELEASE(curkse, &_thread_signal_lock); _kse_critical_leave(&curthread->tcb->tcb_tmbx); /* Now invoke real handler */ if (((__sighandler_t *)sigfunc != SIG_DFL) && ((__sighandler_t *)sigfunc != SIG_IGN) && (sigfunc != (__siginfohandler_t *)_thr_sig_handler)) { if ((sa_flags & SA_SIGINFO) != 0 || info == NULL) (*(sigfunc))(sig, info, ucp); else { ((ohandler)(*sigfunc))( sig, info->si_code, (struct sigcontext *)ucp, info->si_addr, (__sighandler_t *)sigfunc); } } else { if ((__sighandler_t *)sigfunc == SIG_DFL) { if (sigprop(sig) & SA_KILL) { if (_kse_isthreaded()) kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig); else kill(getpid(), sig); } #ifdef NOTYET else if (sigprop(sig) & SA_STOP) kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, sig); #endif } } _kse_critical_enter(); curthread->sigmask = ucp->uc_sigmask; SIG_CANTMASK(curthread->sigmask); _kse_critical_leave(&curthread->tcb->tcb_tmbx); thr_sigframe_restore(curthread, &psf); DBG_MSG("<<< _thr_sig_handler(%d)\n", sig); errno = err_save; } struct sighandle_info { __siginfohandler_t *sigfunc; int sa_flags; int sig; siginfo_t *info; ucontext_t *ucp; }; static void handle_signal(struct pthread *curthread, struct sighandle_info *shi); static void handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi); /* Must be called with signal lock and schedule lock held in order */ static void thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info, ucontext_t *ucp) { __siginfohandler_t *sigfunc; sigset_t sigmask; int sa_flags; int onstack; struct sigaction act; struct kse *curkse; struct sighandle_info shi; /* * Invoke the signal handler without going through the scheduler: */ DBG_MSG("Got signal %d, calling handler for current thread %p\n", sig, curthread); if (!_kse_in_critical()) PANIC("thr_sig_invoke_handler without in critical\n"); curkse = curthread->kse; /* * Check that a custom handler is installed and if * the signal is not blocked: */ sigfunc = _thread_sigact[sig - 1].sa_sigaction; sa_flags = _thread_sigact[sig - 1].sa_flags; sigmask = curthread->sigmask; SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask); if (!(sa_flags & (SA_NODEFER | SA_RESETHAND))) SIGADDSET(curthread->sigmask, sig); if ((sig != SIGILL) && (sa_flags & SA_RESETHAND)) { act.sa_handler = SIG_DFL; act.sa_flags = SA_RESTART; SIGEMPTYSET(act.sa_mask); __sys_sigaction(sig, &act, NULL); __sys_sigaction(sig, NULL, &_thread_sigact[sig - 1]); } KSE_LOCK_RELEASE(curkse, &_thread_signal_lock); KSE_SCHED_UNLOCK(curkse, curkse->k_kseg); /* * We are processing buffered signals, synchronize working * signal mask into kernel. */ if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); onstack = _thr_sigonstack(&sigfunc); ucp->uc_stack = curthread->sigstk; ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE) ? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0); if (curthread->oldsigmask) { ucp->uc_sigmask = *(curthread->oldsigmask); curthread->oldsigmask = NULL; } else ucp->uc_sigmask = sigmask; shi.sigfunc = sigfunc; shi.sig = sig; shi.sa_flags = sa_flags; shi.info = info; shi.ucp = ucp; if ((curthread->sigstk.ss_flags & SS_DISABLE) == 0) { /* Deliver signal on alternative stack */ if (sa_flags & SA_ONSTACK && !onstack) handle_signal_altstack(curthread, &shi); else handle_signal(curthread, &shi); } else { handle_signal(curthread, &shi); } _kse_critical_enter(); /* Don't trust after critical leave/enter */ curkse = curthread->kse; /* * Restore the thread's signal mask. */ curthread->sigmask = ucp->uc_sigmask; SIG_CANTMASK(curthread->sigmask); if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) __sys_sigprocmask(SIG_SETMASK, &ucp->uc_sigmask, NULL); KSE_SCHED_LOCK(curkse, curkse->k_kseg); KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock); DBG_MSG("Got signal %d, handler returned %p\n", sig, curthread); } static void handle_signal(struct pthread *curthread, struct sighandle_info *shi) { _kse_critical_leave(&curthread->tcb->tcb_tmbx); /* Check if the signal requires a dump of thread information: */ if (_thr_dump_enabled() && (shi->sig == SIGINFO)) { /* Dump thread information to file: */ _thread_dump_info(); } if (((__sighandler_t *)shi->sigfunc != SIG_DFL) && ((__sighandler_t *)shi->sigfunc != SIG_IGN)) { if ((shi->sa_flags & SA_SIGINFO) != 0 || shi->info == NULL) (*(shi->sigfunc))(shi->sig, shi->info, shi->ucp); else { ((ohandler)(*shi->sigfunc))( shi->sig, shi->info->si_code, (struct sigcontext *)shi->ucp, shi->info->si_addr, (__sighandler_t *)shi->sigfunc); } } else { if ((__sighandler_t *)shi->sigfunc == SIG_DFL) { if (sigprop(shi->sig) & SA_KILL) { if (_kse_isthreaded()) kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, shi->sig); else kill(getpid(), shi->sig); } #ifdef NOTYET else if (sigprop(shi->sig) & SA_STOP) kse_thr_interrupt(NULL, KSE_INTR_JOBSTOP, shi->sig); #endif } } } static void handle_signal_wrapper(struct pthread *curthread, ucontext_t *ret_uc, struct sighandle_info *shi) { shi->ucp->uc_stack.ss_flags = SS_ONSTACK; handle_signal(curthread, shi); if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) setcontext(ret_uc); else { /* Work around for ia64, THR_SETCONTEXT does not work */ _kse_critical_enter(); curthread->tcb->tcb_tmbx.tm_context = *ret_uc; _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1); /* THR_SETCONTEXT */ } } /* * Jump to stack set by sigaltstack before invoking signal handler */ static void handle_signal_altstack(struct pthread *curthread, struct sighandle_info *shi) { volatile int once; ucontext_t uc1, *uc2; THR_ASSERT(_kse_in_critical(), "Not in critical"); once = 0; THR_GETCONTEXT(&uc1); if (once == 0) { once = 1; /* XXX * We are still in critical region, it is safe to operate thread * context */ uc2 = &curthread->tcb->tcb_tmbx.tm_context; uc2->uc_stack = curthread->sigstk; makecontext(uc2, (void (*)(void))handle_signal_wrapper, 3, curthread, &uc1, shi); if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) setcontext(uc2); else { _thread_switch(curthread->kse->k_kcb, curthread->tcb, 1); /* THR_SETCONTEXT(uc2); */ } } } int _thr_getprocsig(int sig, siginfo_t *siginfo) { kse_critical_t crit; struct kse *curkse; int ret; DBG_MSG(">>> _thr_getprocsig\n"); crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock); ret = _thr_getprocsig_unlocked(sig, siginfo); KSE_LOCK_RELEASE(curkse, &_thread_signal_lock); _kse_critical_leave(crit); DBG_MSG("<<< _thr_getprocsig\n"); return (ret); } int _thr_getprocsig_unlocked(int sig, siginfo_t *siginfo) { sigset_t sigset; struct timespec ts; /* try to retrieve signal from kernel */ SIGEMPTYSET(sigset); SIGADDSET(sigset, sig); ts.tv_sec = 0; ts.tv_nsec = 0; SIGDELSET(_thr_proc_sigpending, sig); if (__sys_sigtimedwait(&sigset, siginfo, &ts) > 0) return (sig); return (0); } #ifndef SYSTEM_SCOPE_ONLY /* * Find a thread that can handle the signal. This must be called * with upcalls disabled. */ struct pthread * -thr_sig_find(struct kse *curkse, int sig, siginfo_t *info) +thr_sig_find(struct kse *curkse, int sig, siginfo_t *info __unused) { struct kse_mailbox *kmbx = NULL; struct pthread *pthread; struct pthread *suspended_thread, *signaled_thread; __siginfohandler_t *sigfunc; siginfo_t si; DBG_MSG("Looking for thread to handle signal %d\n", sig); /* * Enter a loop to look for threads that have the signal * unmasked. POSIX specifies that a thread in a sigwait * will get the signal over any other threads. Second * preference will be threads in in a sigsuspend. Third * preference will be the current thread. If none of the * above, then the signal is delivered to the first thread * that is found. Note that if a custom handler is not * installed, the signal only affects threads in sigwait. */ suspended_thread = NULL; signaled_thread = NULL; KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); TAILQ_FOREACH(pthread, &_thread_list, tle) { if (pthread == _thr_sig_daemon) continue; /* Signal delivering to bound thread is done by kernel */ if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) continue; /* Take the scheduling lock. */ KSE_SCHED_LOCK(curkse, pthread->kseg); if ((pthread->state == PS_DEAD) || (pthread->state == PS_DEADLOCK) || THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread)) { ; /* Skip this thread. */ } else if (pthread->state == PS_SIGWAIT && SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) { /* * retrieve signal from kernel, if it is job control * signal, and sigaction is SIG_DFL, then we will * be stopped in kernel, we hold lock here, but that * does not matter, because that's job control, and * whole process should be stopped. */ if (_thr_getprocsig(sig, &si)) { DBG_MSG("Waking thread %p in sigwait" " with signal %d\n", pthread, sig); /* where to put siginfo ? */ *(pthread->data.sigwait->siginfo) = si; kmbx = _thr_setrunnable_unlocked(pthread); } KSE_SCHED_UNLOCK(curkse, pthread->kseg); /* * POSIX doesn't doesn't specify which thread * will get the signal if there are multiple * waiters, so we give it to the first thread * we find. * * Do not attempt to deliver this signal * to other threads and do not add the signal * to the process pending set. */ KSE_LOCK_RELEASE(curkse, &_thread_list_lock); if (kmbx != NULL) kse_wakeup(kmbx); if (suspended_thread != NULL) _thr_ref_delete(NULL, suspended_thread); if (signaled_thread != NULL) _thr_ref_delete(NULL, signaled_thread); return (NULL); } else if (!SIGISMEMBER(pthread->sigmask, sig)) { /* * If debugger is running, we don't quick exit, * and give it a chance to check the signal. */ if (_libkse_debug == 0) { sigfunc = _thread_sigact[sig - 1].sa_sigaction; if ((__sighandler_t *)sigfunc == SIG_DFL) { if (sigprop(sig) & SA_KILL) { kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig); /* Never reach */ } } } if (pthread->state == PS_SIGSUSPEND) { if (suspended_thread == NULL) { suspended_thread = pthread; suspended_thread->refcount++; } } else if (signaled_thread == NULL) { signaled_thread = pthread; signaled_thread->refcount++; } } KSE_SCHED_UNLOCK(curkse, pthread->kseg); } KSE_LOCK_RELEASE(curkse, &_thread_list_lock); if (suspended_thread != NULL) { pthread = suspended_thread; if (signaled_thread) _thr_ref_delete(NULL, signaled_thread); } else if (signaled_thread) { pthread = signaled_thread; } else { pthread = NULL; } return (pthread); } #endif /* ! SYSTEM_SCOPE_ONLY */ static inline void build_siginfo(siginfo_t *info, int signo) { bzero(info, sizeof(*info)); info->si_signo = signo; info->si_pid = _thr_pid; } /* * This is called by a thread when it has pending signals to deliver. * It should only be called from the context of the thread. */ void _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp) { struct pthread_sigframe psf; siginfo_t siginfo; int i, err_save; kse_critical_t crit; struct kse *curkse; sigset_t sigmask; err_save = errno; DBG_MSG(">>> thr_sig_rundown (%p)\n", curthread); /* Check the threads previous state: */ curthread->critical_count++; if (curthread->sigbackout != NULL) curthread->sigbackout((void *)curthread); curthread->critical_count--; THR_ASSERT(!(curthread->sigbackout), "sigbackout was not cleared."); THR_ASSERT((curthread->state == PS_RUNNING), "state is not PS_RUNNING"); thr_sigframe_save(curthread, &psf); /* * Lower the priority before calling the handler in case * it never returns (longjmps back): */ crit = _kse_critical_enter(); curkse = curthread->kse; KSE_SCHED_LOCK(curkse, curkse->k_kseg); KSE_LOCK_ACQUIRE(curkse, &_thread_signal_lock); curthread->active_priority &= ~THR_SIGNAL_PRIORITY; SIGFILLSET(sigmask); while (1) { /* * For bound thread, we mask all signals and get a fresh * copy of signal mask from kernel */ if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask); } for (i = 1; i <= _SIG_MAXSIG; i++) { if (SIGISMEMBER(curthread->sigmask, i)) continue; if (SIGISMEMBER(curthread->sigpend, i)) { SIGDELSET(curthread->sigpend, i); siginfo = curthread->siginfo[i-1]; break; } if (!(curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) && SIGISMEMBER(_thr_proc_sigpending, i)) { if (_thr_getprocsig_unlocked(i, &siginfo)) break; } } if (i <= _SIG_MAXSIG) thr_sig_invoke_handler(curthread, i, &siginfo, ucp); else { if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); } break; } } /* Don't trust after signal handling */ curkse = curthread->kse; KSE_LOCK_RELEASE(curkse, &_thread_signal_lock); KSE_SCHED_UNLOCK(curkse, curkse->k_kseg); _kse_critical_leave(&curthread->tcb->tcb_tmbx); /* repost masked signal to kernel, it hardly happens in real world */ if ((curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) && !SIGISEMPTY(curthread->sigpend)) { /* dirty read */ __sys_sigprocmask(SIG_SETMASK, &sigmask, &curthread->sigmask); for (i = 1; i <= _SIG_MAXSIG; ++i) { if (SIGISMEMBER(curthread->sigpend, i)) { SIGDELSET(curthread->sigpend, i); if (!_kse_isthreaded()) kill(getpid(), i); else kse_thr_interrupt( &curthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, i); } } __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); } DBG_MSG("<<< thr_sig_rundown (%p)\n", curthread); thr_sigframe_restore(curthread, &psf); errno = err_save; } /* * This checks pending signals for the current thread. It should be * called whenever a thread changes its signal mask. Note that this * is called from a thread (using its stack). * * XXX - We might want to just check to see if there are pending * signals for the thread here, but enter the UTS scheduler * to actually install the signal handler(s). */ void _thr_sig_check_pending(struct pthread *curthread) { ucontext_t uc; volatile int once; int errsave; /* * If the thread is in critical region, delay processing signals. * If the thread state is not PS_RUNNING, it might be switching * into UTS and but a THR_LOCK_RELEASE saw check_pending, and it * goes here, in the case we delay processing signals, lets UTS * process complicated things, normally UTS will call _thr_sig_add * to resume the thread, so we needn't repeat doing it here. */ if (THR_IN_CRITICAL(curthread) || curthread->state != PS_RUNNING) return; errsave = errno; once = 0; THR_GETCONTEXT(&uc); if (once == 0) { once = 1; curthread->check_pending = 0; _thr_sig_rundown(curthread, &uc); } errno = errsave; } /* * Perform thread specific actions in response to a signal. * This function is only called if there is a handler installed * for the signal, and if the target thread has the signal * unmasked. * * This must be called with the thread's scheduling lock held. */ struct kse_mailbox * _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info) { siginfo_t siginfo; struct kse *curkse; struct kse_mailbox *kmbx = NULL; struct pthread *curthread = _get_curthread(); int restart; int suppress_handler = 0; int fromproc = 0; __sighandler_t *sigfunc; DBG_MSG(">>> _thr_sig_add %p (%d)\n", pthread, sig); curkse = _get_curkse(); restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART; sigfunc = _thread_sigact[sig - 1].sa_handler; fromproc = (curthread == _thr_sig_daemon); if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK || pthread->state == PS_STATE_MAX) return (NULL); /* return false */ if ((pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) && (curthread != pthread)) { PANIC("Please use _thr_send_sig for bound thread"); return (NULL); } if (pthread->state != PS_SIGWAIT && SIGISMEMBER(pthread->sigmask, sig)) { /* signal is masked, just add signal to thread. */ if (!fromproc) { SIGADDSET(pthread->sigpend, sig); if (info == NULL) build_siginfo(&pthread->siginfo[sig-1], sig); else if (info != &pthread->siginfo[sig-1]) memcpy(&pthread->siginfo[sig-1], info, sizeof(*info)); } else { if (!_thr_getprocsig(sig, &pthread->siginfo[sig-1])) return (NULL); SIGADDSET(pthread->sigpend, sig); } } else { /* if process signal not exists, just return */ if (fromproc) { if (!_thr_getprocsig(sig, &siginfo)) return (NULL); info = &siginfo; } if (pthread->state != PS_SIGWAIT && sigfunc == SIG_DFL && (sigprop(sig) & SA_KILL)) { kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig); /* Never reach */ } /* * Process according to thread state: */ switch (pthread->state) { case PS_DEAD: case PS_DEADLOCK: case PS_STATE_MAX: return (NULL); /* XXX return false */ case PS_LOCKWAIT: case PS_SUSPENDED: /* * You can't call a signal handler for threads in these * states. */ suppress_handler = 1; break; case PS_RUNNING: if ((pthread->flags & THR_FLAGS_IN_RUNQ)) { THR_RUNQ_REMOVE(pthread); pthread->active_priority |= THR_SIGNAL_PRIORITY; THR_RUNQ_INSERT_TAIL(pthread); } else { /* Possible not in RUNQ and has curframe ? */ pthread->active_priority |= THR_SIGNAL_PRIORITY; } break; /* * States which cannot be interrupted but still require the * signal handler to run: */ case PS_COND_WAIT: case PS_MUTEX_WAIT: break; case PS_SLEEP_WAIT: /* * Unmasked signals always cause sleep to terminate * early regardless of SA_RESTART: */ pthread->interrupted = 1; break; case PS_JOIN: break; case PS_SIGSUSPEND: pthread->interrupted = 1; break; case PS_SIGWAIT: if (info == NULL) build_siginfo(&pthread->siginfo[sig-1], sig); else if (info != &pthread->siginfo[sig-1]) memcpy(&pthread->siginfo[sig-1], info, sizeof(*info)); /* * The signal handler is not called for threads in * SIGWAIT. */ suppress_handler = 1; /* Wake up the thread if the signal is not blocked. */ if (SIGISMEMBER(*(pthread->data.sigwait->waitset), sig)) { /* Return the signal number: */ *(pthread->data.sigwait->siginfo) = pthread->siginfo[sig-1]; /* Make the thread runnable: */ kmbx = _thr_setrunnable_unlocked(pthread); } else { /* Increment the pending signal count. */ SIGADDSET(pthread->sigpend, sig); if (!SIGISMEMBER(pthread->sigmask, sig)) { if (sigfunc == SIG_DFL && sigprop(sig) & SA_KILL) { kse_thr_interrupt(NULL, KSE_INTR_SIGEXIT, sig); /* Never reach */ } pthread->check_pending = 1; pthread->interrupted = 1; kmbx = _thr_setrunnable_unlocked(pthread); } } return (kmbx); } SIGADDSET(pthread->sigpend, sig); if (info == NULL) build_siginfo(&pthread->siginfo[sig-1], sig); else if (info != &pthread->siginfo[sig-1]) memcpy(&pthread->siginfo[sig-1], info, sizeof(*info)); pthread->check_pending = 1; if (!(pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) && (pthread->blocked != 0) && !THR_IN_CRITICAL(pthread)) kse_thr_interrupt(&pthread->tcb->tcb_tmbx, restart ? KSE_INTR_RESTART : KSE_INTR_INTERRUPT, 0); if (suppress_handler == 0) { /* * Setup a signal frame and save the current threads * state: */ if (pthread->state != PS_RUNNING) { if (pthread->flags & THR_FLAGS_IN_RUNQ) THR_RUNQ_REMOVE(pthread); pthread->active_priority |= THR_SIGNAL_PRIORITY; kmbx = _thr_setrunnable_unlocked(pthread); } } } return (kmbx); } /* * Send a signal to a specific thread (ala pthread_kill): */ void _thr_sig_send(struct pthread *pthread, int sig) { struct pthread *curthread = _get_curthread(); struct kse_mailbox *kmbx; if (pthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { kse_thr_interrupt(&pthread->tcb->tcb_tmbx, KSE_INTR_SENDSIG, sig); return; } /* Lock the scheduling queue of the target thread. */ THR_SCHED_LOCK(curthread, pthread); if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) { kmbx = _thr_sig_add(pthread, sig, NULL); /* Add a preemption point. */ if (kmbx == NULL && (curthread->kseg == pthread->kseg) && (pthread->active_priority > curthread->active_priority)) curthread->critical_yield = 1; THR_SCHED_UNLOCK(curthread, pthread); if (kmbx != NULL) kse_wakeup(kmbx); /* XXX * If thread sent signal to itself, check signals now. * It is not really needed, _kse_critical_leave should * have already checked signals. */ if (pthread == curthread && curthread->check_pending) _thr_sig_check_pending(curthread); } else { THR_SCHED_UNLOCK(curthread, pthread); } } static inline void thr_sigframe_restore(struct pthread *curthread, struct pthread_sigframe *psf) { kse_critical_t crit; struct kse *curkse; THR_THREAD_LOCK(curthread, curthread); curthread->cancelflags = psf->psf_cancelflags; crit = _kse_critical_enter(); curkse = curthread->kse; KSE_SCHED_LOCK(curkse, curthread->kseg); curthread->flags = psf->psf_flags; curthread->interrupted = psf->psf_interrupted; curthread->timeout = psf->psf_timeout; curthread->data = psf->psf_wait_data; curthread->wakeup_time = psf->psf_wakeup_time; curthread->continuation = psf->psf_continuation; KSE_SCHED_UNLOCK(curkse, curthread->kseg); _kse_critical_leave(crit); THR_THREAD_UNLOCK(curthread, curthread); } static inline void thr_sigframe_save(struct pthread *curthread, struct pthread_sigframe *psf) { kse_critical_t crit; struct kse *curkse; THR_THREAD_LOCK(curthread, curthread); psf->psf_cancelflags = curthread->cancelflags; crit = _kse_critical_enter(); curkse = curthread->kse; KSE_SCHED_LOCK(curkse, curthread->kseg); /* This has to initialize all members of the sigframe. */ psf->psf_flags = (curthread->flags & (THR_FLAGS_PRIVATE | THR_FLAGS_EXITING)); psf->psf_interrupted = curthread->interrupted; psf->psf_timeout = curthread->timeout; psf->psf_wait_data = curthread->data; psf->psf_wakeup_time = curthread->wakeup_time; psf->psf_continuation = curthread->continuation; KSE_SCHED_UNLOCK(curkse, curthread->kseg); _kse_critical_leave(crit); THR_THREAD_UNLOCK(curthread, curthread); } void _thr_signal_init(void) { struct sigaction act; __siginfohandler_t *sigfunc; int i; sigset_t sigset; SIGFILLSET(sigset); __sys_sigprocmask(SIG_SETMASK, &sigset, &_thr_initial->sigmask); /* Enter a loop to get the existing signal status: */ for (i = 1; i <= _SIG_MAXSIG; i++) { /* Get the signal handler details: */ if (__sys_sigaction(i, NULL, &_thread_sigact[i - 1]) != 0) { /* * Abort this process if signal * initialisation fails: */ PANIC("Cannot read signal handler info"); } /* Intall wrapper if handler was set */ sigfunc = _thread_sigact[i - 1].sa_sigaction; if (((__sighandler_t *)sigfunc) != SIG_DFL && ((__sighandler_t *)sigfunc) != SIG_IGN) { act = _thread_sigact[i - 1]; act.sa_flags |= SA_SIGINFO; act.sa_sigaction = (__siginfohandler_t *)_thr_sig_handler; __sys_sigaction(i, &act, NULL); } } if (_thr_dump_enabled()) { /* * Install the signal handler for SIGINFO. It isn't * really needed, but it is nice to have for debugging * purposes. */ _thread_sigact[SIGINFO - 1].sa_flags = SA_SIGINFO | SA_RESTART; SIGEMPTYSET(act.sa_mask); act.sa_flags = SA_SIGINFO | SA_RESTART; act.sa_sigaction = (__siginfohandler_t *)&_thr_sig_handler; if (__sys_sigaction(SIGINFO, &act, NULL) != 0) { __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL); /* * Abort this process if signal initialisation fails: */ PANIC("Cannot initialize signal handler"); } } __sys_sigprocmask(SIG_SETMASK, &_thr_initial->sigmask, NULL); __sys_sigaltstack(NULL, &_thr_initial->sigstk); } void _thr_signal_deinit(void) { int i; struct pthread *curthread = _get_curthread(); /* Clear process pending signals. */ sigemptyset(&_thr_proc_sigpending); /* Enter a loop to get the existing signal status: */ for (i = 1; i <= _SIG_MAXSIG; i++) { /* Check for signals which cannot be trapped: */ if (i == SIGKILL || i == SIGSTOP) { } /* Set the signal handler details: */ else if (__sys_sigaction(i, &_thread_sigact[i - 1], NULL) != 0) { /* * Abort this process if signal * initialisation fails: */ PANIC("Cannot set signal handler info"); } } __sys_sigaltstack(&curthread->sigstk, NULL); } Index: head/lib/libkse/thread/thr_sigaction.c =================================================================== --- head/lib/libkse/thread/thr_sigaction.c (revision 174111) +++ head/lib/libkse/thread/thr_sigaction.c (revision 174112) @@ -1,127 +1,129 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_sigaction); LT10_COMPAT_DEFAULT(sigaction); __weak_reference(_sigaction, sigaction); int _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) { int ret = 0; int err = 0; struct sigaction newact, oldact; struct pthread *curthread; kse_critical_t crit; /* Check if the signal number is out of range: */ if (sig < 1 || sig > _SIG_MAXSIG) { /* Return an invalid argument: */ errno = EINVAL; ret = -1; } else { if (act) newact = *act; crit = _kse_critical_enter(); curthread = _get_curthread(); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); oldact = _thread_sigact[sig - 1]; /* Check if a signal action was supplied: */ if (act != NULL) { /* Set the new signal handler: */ _thread_sigact[sig - 1] = newact; } /* * Check if the kernel needs to be advised of a change * in signal action: */ if (act != NULL) { newact.sa_flags |= SA_SIGINFO; /* * Check if the signal handler is being set to * the default or ignore handlers: */ if (newact.sa_handler != SIG_DFL && newact.sa_handler != SIG_IGN) { /* * Specify the thread kernel signal * handler: */ - newact.sa_handler = (void (*) ())_thr_sig_handler; + newact.sa_sigaction = _thr_sig_handler; } /* * Install libpthread signal handler wrapper * for SIGINFO signal if threads dump enabled * even if a user set the signal handler to * SIG_DFL or SIG_IGN. */ if (sig == SIGINFO && _thr_dump_enabled()) { - newact.sa_handler = - (void (*) ())_thr_sig_handler; + newact.sa_sigaction = _thr_sig_handler; } /* Change the signal action in the kernel: */ if (__sys_sigaction(sig, &newact, NULL) != 0) { _thread_sigact[sig - 1] = oldact; /* errno is in kse, will copy it to thread */ err = errno; ret = -1; } } KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); _kse_critical_leave(crit); /* * Check if the existing signal action structure contents are * to be returned: */ if (oact != NULL) { /* Return the existing signal action contents: */ *oact = oldact; } if (ret != 0) { /* Return errno to thread */ errno = err; } } /* Return the completion status: */ return (ret); } Index: head/lib/libkse/thread/thr_sigaltstack.c =================================================================== --- head/lib/libkse/thread/thr_sigaltstack.c (revision 174111) +++ head/lib/libkse/thread/thr_sigaltstack.c (revision 174112) @@ -1,110 +1,114 @@ /*- * Copyright (c) 2003 David Xu * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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. */ #include __FBSDID("$FreeBSD$"); +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" + +int _sigaltstack(stack_t *_ss, stack_t *_oss); LT10_COMPAT_PRIVATE(_sigaltstack); LT10_COMPAT_DEFAULT(sigaltstack); __weak_reference(_sigaltstack, sigaltstack); int _sigaltstack(stack_t *_ss, stack_t *_oss) { struct pthread *curthread = _get_curthread(); stack_t ss, oss; int oonstack, errsave, ret; kse_critical_t crit; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { crit = _kse_critical_enter(); ret = __sys_sigaltstack(_ss, _oss); errsave = errno; /* Get a copy */ if (ret == 0 && _ss != NULL) curthread->sigstk = *_ss; _kse_critical_leave(crit); errno = errsave; return (ret); } if (_ss) ss = *_ss; if (_oss) oss = *_oss; /* Should get and set stack in atomic way */ crit = _kse_critical_enter(); oonstack = _thr_sigonstack(&ss); if (_oss != NULL) { oss = curthread->sigstk; oss.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE) ? SS_DISABLE : ((oonstack) ? SS_ONSTACK : 0); } if (_ss != NULL) { if (oonstack) { _kse_critical_leave(crit); errno = EPERM; return (-1); } if ((ss.ss_flags & ~SS_DISABLE) != 0) { _kse_critical_leave(crit); errno = EINVAL; return (-1); } if (!(ss.ss_flags & SS_DISABLE)) { if (ss.ss_size < MINSIGSTKSZ) { _kse_critical_leave(crit); errno = ENOMEM; return (-1); } curthread->sigstk = ss; } else { curthread->sigstk.ss_flags |= SS_DISABLE; } } _kse_critical_leave(crit); if (_oss != NULL) *_oss = oss; return (0); } int _thr_sigonstack(void *sp) { struct pthread *curthread = _get_curthread(); return ((curthread->sigstk.ss_flags & SS_DISABLE) == 0 ? (((size_t)sp - (size_t)curthread->sigstk.ss_sp) < curthread->sigstk.ss_size) : 0); } Index: head/lib/libkse/thread/thr_sigmask.c =================================================================== --- head/lib/libkse/thread/thr_sigmask.c (revision 174111) +++ head/lib/libkse/thread/thr_sigmask.c (revision 174112) @@ -1,113 +1,116 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_sigmask); LT10_COMPAT_DEFAULT(pthread_sigmask); __weak_reference(_pthread_sigmask, pthread_sigmask); int _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { struct pthread *curthread = _get_curthread(); sigset_t oldset, newset; int ret; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { ret = __sys_sigprocmask(how, set, oset); if (ret != 0) ret = errno; /* Get a fresh copy */ __sys_sigprocmask(SIG_SETMASK, NULL, &curthread->sigmask); return (ret); } if (set) newset = *set; THR_SCHED_LOCK(curthread, curthread); ret = 0; if (oset != NULL) /* Return the current mask: */ oldset = curthread->sigmask; /* Check if a new signal set was provided by the caller: */ if (set != NULL) { /* Process according to what to do: */ switch (how) { /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ SIGSETOR(curthread->sigmask, newset); break; /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ SIGSETNAND(curthread->sigmask, newset); break; /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ curthread->sigmask = newset; break; /* Trap invalid actions: */ default: /* Return an invalid argument: */ ret = EINVAL; break; } SIG_CANTMASK(curthread->sigmask); THR_SCHED_UNLOCK(curthread, curthread); /* * Run down any pending signals: */ if (ret == 0) _thr_sig_check_pending(curthread); } else THR_SCHED_UNLOCK(curthread, curthread); if (ret == 0 && oset != NULL) *oset = oldset; return (ret); } Index: head/lib/libkse/thread/thr_sigpending.c =================================================================== --- head/lib/libkse/thread/thr_sigpending.c (revision 174111) +++ head/lib/libkse/thread/thr_sigpending.c (revision 174112) @@ -1,76 +1,81 @@ /* * Copyright (c) 1999 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" + +int _sigpending(sigset_t *set); LT10_COMPAT_PRIVATE(_sigpending); LT10_COMPAT_DEFAULT(sigpending); __weak_reference(_sigpending, sigpending); int _sigpending(sigset_t *set) { struct pthread *curthread = _get_curthread(); kse_critical_t crit; sigset_t sigset; int ret = 0; /* Check for a null signal set pointer: */ if (set == NULL) { /* Return an invalid argument: */ ret = EINVAL; } else { if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) return (__sys_sigpending(set)); crit = _kse_critical_enter(); KSE_SCHED_LOCK(curthread->kse, curthread->kseg); sigset = curthread->sigpend; KSE_SCHED_UNLOCK(curthread->kse, curthread->kseg); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); SIGSETOR(sigset, _thr_proc_sigpending); KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); _kse_critical_leave(crit); *set = sigset; } /* Return the completion status: */ return (ret); } Index: head/lib/libkse/thread/thr_sigprocmask.c =================================================================== --- head/lib/libkse/thread/thr_sigprocmask.c (revision 174111) +++ head/lib/libkse/thread/thr_sigprocmask.c (revision 174112) @@ -1,55 +1,58 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_sigprocmask); LT10_COMPAT_DEFAULT(sigprocmask); __weak_reference(_sigprocmask, sigprocmask); int _sigprocmask(int how, const sigset_t *set, sigset_t *oset) { int ret; - ret = pthread_sigmask(how, set, oset); + ret = _pthread_sigmask(how, set, oset); if (ret) { errno = ret; ret = -1; } return (ret); } Index: head/lib/libkse/thread/thr_sigsuspend.c =================================================================== --- head/lib/libkse/thread/thr_sigsuspend.c (revision 174111) +++ head/lib/libkse/thread/thr_sigsuspend.c (revision 174112) @@ -1,110 +1,113 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ +#include "namespace.h" #include #include #include #include #include #include - +#include "un-namespace.h" #include "thr_private.h" + +int __sigsuspend(const sigset_t * set); LT10_COMPAT_PRIVATE(__sigsuspend); LT10_COMPAT_PRIVATE(_sigsuspend); LT10_COMPAT_DEFAULT(sigsuspend); __weak_reference(__sigsuspend, sigsuspend); int _sigsuspend(const sigset_t *set) { struct pthread *curthread = _get_curthread(); sigset_t oldmask, newmask, tempset; int ret = -1; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) return (__sys_sigsuspend(set)); /* Check if a new signal set was provided by the caller: */ if (set != NULL) { newmask = *set; SIG_CANTMASK(newmask); THR_LOCK_SWITCH(curthread); /* Save current sigmask: */ oldmask = curthread->sigmask; curthread->oldsigmask = &oldmask; /* Change the caller's mask: */ curthread->sigmask = newmask; tempset = curthread->sigpend; SIGSETNAND(tempset, newmask); if (SIGISEMPTY(tempset)) { THR_SET_STATE(curthread, PS_SIGSUSPEND); /* Wait for a signal: */ _thr_sched_switch_unlocked(curthread); } else { curthread->check_pending = 1; THR_UNLOCK_SWITCH(curthread); /* check pending signal I can handle: */ _thr_sig_check_pending(curthread); } if ((curthread->cancelflags & THR_CANCELLING) != 0) curthread->oldsigmask = NULL; else { THR_ASSERT(curthread->oldsigmask == NULL, "oldsigmask is not cleared"); } /* Always return an interrupted error: */ errno = EINTR; } else { /* Return an invalid argument error: */ errno = EINVAL; } /* Return the completion status: */ return (ret); } int __sigsuspend(const sigset_t * set) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = _sigsuspend(set); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_sigwait.c =================================================================== --- head/lib/libkse/thread/thr_sigwait.c (revision 174111) +++ head/lib/libkse/thread/thr_sigwait.c (revision 174112) @@ -1,209 +1,220 @@ //depot/projects/kse/lib/libpthread/thread/thr_sigwait.c#1 - branch change 15154 (text+ko) /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" +int __sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout); +int __sigwaitinfo(const sigset_t *set, siginfo_t *info); +int __sigwait(const sigset_t *set, int *sig); +int _sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout); +int _sigwaitinfo(const sigset_t *set, siginfo_t *info); +int _sigwait(const sigset_t *set, int *sig); + LT10_COMPAT_PRIVATE(__sigwait); LT10_COMPAT_PRIVATE(_sigwait); LT10_COMPAT_DEFAULT(sigwait); LT10_COMPAT_PRIVATE(__sigtimedwait); LT10_COMPAT_PRIVATE(_sigtimedwait); LT10_COMPAT_DEFAULT(sigtimedwait); LT10_COMPAT_PRIVATE(__sigwaitinfo); LT10_COMPAT_PRIVATE(_sigwaitinfo); LT10_COMPAT_DEFAULT(sigwaitinfo); __weak_reference(__sigwait, sigwait); __weak_reference(__sigtimedwait, sigtimedwait); __weak_reference(__sigwaitinfo, sigwaitinfo); static int lib_sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout) + const struct timespec *timeout) { struct pthread *curthread = _get_curthread(); int ret = 0; int i; struct sigwait_data waitdata; sigset_t waitset; kse_critical_t crit; siginfo_t siginfo; if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { if (info == NULL) info = &siginfo; - return (__sys_sigtimedwait((sigset_t *)set, info, - (struct timespec *)timeout)); + return (__sys_sigtimedwait(set, info, timeout)); } /* * Initialize the set of signals that will be waited on: */ waitset = *set; /* These signals can't be waited on. */ SIGDELSET(waitset, SIGKILL); SIGDELSET(waitset, SIGSTOP); /* * POSIX says 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. */ crit = _kse_critical_enter(); KSE_SCHED_LOCK(curthread->kse, curthread->kseg); for (i = 1; i <= _SIG_MAXSIG; ++i) { if (SIGISMEMBER(waitset, i) && SIGISMEMBER(curthread->sigpend, i)) { SIGDELSET(curthread->sigpend, i); siginfo = curthread->siginfo[i - 1]; KSE_SCHED_UNLOCK(curthread->kse, curthread->kseg); _kse_critical_leave(crit); ret = i; goto OUT; } } curthread->timeout = 0; curthread->interrupted = 0; _thr_set_timeout(timeout); /* Wait for a signal: */ siginfo.si_signo = 0; waitdata.waitset = &waitset; waitdata.siginfo = &siginfo; curthread->data.sigwait = &waitdata; THR_SET_STATE(curthread, PS_SIGWAIT); _thr_sched_switch_unlocked(curthread); /* * Return the signal number to the caller: */ if (siginfo.si_signo > 0) { ret = siginfo.si_signo; } else { if (curthread->interrupted) errno = EINTR; else if (curthread->timeout) errno = EAGAIN; ret = -1; } curthread->timeout = 0; curthread->interrupted = 0; /* * Probably unnecessary, but since it's in a union struct * we don't know how it could be used in the future. */ curthread->data.sigwait = NULL; OUT: if (ret > 0 && info != NULL) *info = siginfo; return (ret); } int __sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec * timeout) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = lib_sigtimedwait(set, info, timeout); _thr_cancel_leave(curthread, 1); return (ret); } int _sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec * timeout) { return lib_sigtimedwait(set, info, timeout); } int __sigwaitinfo(const sigset_t *set, siginfo_t *info) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = lib_sigtimedwait(set, info, NULL); _thr_cancel_leave(curthread, 1); return (ret); } int _sigwaitinfo(const sigset_t *set, siginfo_t *info) { return lib_sigtimedwait(set, info, NULL); } int __sigwait(const sigset_t *set, int *sig) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = lib_sigtimedwait(set, NULL, NULL); if (ret > 0) { *sig = ret; ret = 0; } else { ret = errno; } _thr_cancel_leave(curthread, 1); return (ret); } int _sigwait(const sigset_t *set, int *sig) { int ret; ret = lib_sigtimedwait(set, NULL, NULL); if (ret > 0) { *sig = ret; ret = 0; } else { ret = errno; } return (ret); } Index: head/lib/libkse/thread/thr_single_np.c =================================================================== --- head/lib/libkse/thread/thr_single_np.c (revision 174111) +++ head/lib/libkse/thread/thr_single_np.c (revision 174112) @@ -1,51 +1,55 @@ /* * Copyright (c) 1996 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include - +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_single_np); LT10_COMPAT_DEFAULT(pthread_single_np); +int _pthread_single_np(void); + __weak_reference(_pthread_single_np, pthread_single_np); -int _pthread_single_np() +int _pthread_single_np(void) { /* Enter single-threaded (non-POSIX) scheduling mode: */ - pthread_suspend_all_np(); + _pthread_suspend_all_np(); /* * XXX - Do we want to do this? * __is_threaded = 0; */ return (0); } Index: head/lib/libkse/thread/thr_sleep.c =================================================================== --- head/lib/libkse/thread/thr_sleep.c (revision 174111) +++ head/lib/libkse/thread/thr_sleep.c (revision 174112) @@ -1,71 +1,75 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" extern unsigned int __sleep(unsigned int); extern int __usleep(useconds_t); + +unsigned int _sleep(unsigned int seconds); LT10_COMPAT_PRIVATE(_sleep); LT10_COMPAT_DEFAULT(sleep); LT10_COMPAT_PRIVATE(_usleep); LT10_COMPAT_DEFAULT(usleep); __weak_reference(_sleep, sleep); __weak_reference(_usleep, usleep); unsigned int _sleep(unsigned int seconds) { struct pthread *curthread = _get_curthread(); unsigned int ret; _thr_cancel_enter(curthread); ret = __sleep(seconds); _thr_cancel_leave(curthread, 1); return (ret); } int _usleep(useconds_t useconds) { struct pthread *curthread = _get_curthread(); unsigned int ret; _thr_cancel_enter(curthread); ret = __usleep(useconds); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_spec.c =================================================================== --- head/lib/libkse/thread/thr_spec.c (revision 174111) +++ head/lib/libkse/thread/thr_spec.c (revision 174112) @@ -1,244 +1,246 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include #include #include #include - +#include "un-namespace.h" #include "thr_private.h" struct pthread_key _thread_keytable[PTHREAD_KEYS_MAX]; /* * XXX - This breaks the linker if LT10_COMPAT_DEFAULT doesn't * also include a weak reference to the default symbol. */ LT10_COMPAT_PRIVATE(_thread_keytable); LT10_COMPAT_PRIVATE(_pthread_key_create); LT10_COMPAT_DEFAULT(pthread_key_create); LT10_COMPAT_PRIVATE(_pthread_key_delete); LT10_COMPAT_DEFAULT(pthread_key_delete); LT10_COMPAT_PRIVATE(_pthread_getspecific); LT10_COMPAT_DEFAULT(pthread_getspecific); LT10_COMPAT_PRIVATE(_pthread_setspecific); LT10_COMPAT_DEFAULT(pthread_setspecific); __weak_reference(_pthread_key_create, pthread_key_create); __weak_reference(_pthread_key_delete, pthread_key_delete); __weak_reference(_pthread_getspecific, pthread_getspecific); __weak_reference(_pthread_setspecific, pthread_setspecific); int _pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) { struct pthread *curthread; int i; if (_thr_initial == NULL) _libpthread_init(NULL); curthread = _get_curthread(); /* Lock the key table: */ THR_LOCK_ACQUIRE(curthread, &_keytable_lock); for (i = 0; i < PTHREAD_KEYS_MAX; i++) { if (_thread_keytable[i].allocated == 0) { _thread_keytable[i].allocated = 1; _thread_keytable[i].destructor = destructor; _thread_keytable[i].seqno++; /* Unlock the key table: */ THR_LOCK_RELEASE(curthread, &_keytable_lock); *key = i; return (0); } } /* Unlock the key table: */ THR_LOCK_RELEASE(curthread, &_keytable_lock); return (EAGAIN); } int _pthread_key_delete(pthread_key_t key) { struct pthread *curthread = _get_curthread(); int ret = 0; if ((unsigned int)key < PTHREAD_KEYS_MAX) { /* Lock the key table: */ THR_LOCK_ACQUIRE(curthread, &_keytable_lock); if (_thread_keytable[key].allocated) _thread_keytable[key].allocated = 0; else ret = EINVAL; /* Unlock the key table: */ THR_LOCK_RELEASE(curthread, &_keytable_lock); } else ret = EINVAL; return (ret); } void _thread_cleanupspecific(void) { struct pthread *curthread = _get_curthread(); - void (*destructor)( void *); - void *data = NULL; + const_key_destructor_t destructor; + const void *data = NULL; int key; int i; if (curthread->specific == NULL) return; /* Lock the key table: */ THR_LOCK_ACQUIRE(curthread, &_keytable_lock); for (i = 0; (i < PTHREAD_DESTRUCTOR_ITERATIONS) && (curthread->specific_data_count > 0); i++) { for (key = 0; (key < PTHREAD_KEYS_MAX) && (curthread->specific_data_count > 0); key++) { destructor = NULL; if (_thread_keytable[key].allocated && (curthread->specific[key].data != NULL)) { if (curthread->specific[key].seqno == _thread_keytable[key].seqno) { - data = (void *) - curthread->specific[key].data; - destructor = _thread_keytable[key].destructor; + data = curthread->specific[key].data; + destructor = (const_key_destructor_t) + _thread_keytable[key].destructor; } curthread->specific[key].data = NULL; curthread->specific_data_count--; } /* * If there is a destructore, call it * with the key table entry unlocked: */ if (destructor != NULL) { /* * Don't hold the lock while calling the * destructor: */ THR_LOCK_RELEASE(curthread, &_keytable_lock); destructor(data); THR_LOCK_ACQUIRE(curthread, &_keytable_lock); } } } THR_LOCK_RELEASE(curthread, &_keytable_lock); free(curthread->specific); curthread->specific = NULL; if (curthread->specific_data_count > 0) stderr_debug("Thread %p has exited with leftover " "thread-specific data after %d destructor iterations\n", curthread, PTHREAD_DESTRUCTOR_ITERATIONS); } static inline struct pthread_specific_elem * pthread_key_allocate_data(void) { struct pthread_specific_elem *new_data; new_data = (struct pthread_specific_elem *) malloc(sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); if (new_data != NULL) { memset((void *) new_data, 0, sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); } return (new_data); } int _pthread_setspecific(pthread_key_t key, const void *value) { struct pthread *pthread; int ret = 0; /* Point to the running thread: */ pthread = _get_curthread(); if ((pthread->specific) || (pthread->specific = pthread_key_allocate_data())) { if ((unsigned int)key < PTHREAD_KEYS_MAX) { if (_thread_keytable[key].allocated) { if (pthread->specific[key].data == NULL) { if (value != NULL) pthread->specific_data_count++; } else if (value == NULL) pthread->specific_data_count--; - pthread->specific[key].data = value; + *(const void **)&pthread->specific[key].data = value; pthread->specific[key].seqno = _thread_keytable[key].seqno; ret = 0; } else ret = EINVAL; } else ret = EINVAL; } else ret = ENOMEM; return (ret); } void * _pthread_getspecific(pthread_key_t key) { struct pthread *pthread; void *data; /* Point to the running thread: */ pthread = _get_curthread(); /* Check if there is specific data: */ if (pthread->specific != NULL && (unsigned int)key < PTHREAD_KEYS_MAX) { /* Check if this key has been used before: */ if (_thread_keytable[key].allocated && (pthread->specific[key].seqno == _thread_keytable[key].seqno)) { /* Return the value: */ - data = (void *) pthread->specific[key].data; + data = pthread->specific[key].data; } else { /* * This key has not been used before, so return NULL * instead: */ data = NULL; } } else /* No specific data has been created, so just return NULL: */ data = NULL; return (data); } Index: head/lib/libkse/thread/thr_spinlock.c =================================================================== --- head/lib/libkse/thread/thr_spinlock.c (revision 174111) +++ head/lib/libkse/thread/thr_spinlock.c (revision 174112) @@ -1,149 +1,159 @@ /* * Copyright (c) 1997 John Birrell . * 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. 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 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$ * */ +#include "namespace.h" #include #include - +#include #include +#include "un-namespace.h" #include "spinlock.h" #include "thr_private.h" #define MAX_SPINLOCKS 72 struct spinlock_extra { spinlock_t *owner; pthread_mutex_t lock; }; +struct nv_spinlock { + long access_lock; + long lock_owner; + struct spinlock_extra *extra; /* overlays fname in spinlock_t */ + int lineno; +}; +typedef struct nv_spinlock nv_spinlock_t; + static void init_spinlock(spinlock_t *lck); static struct pthread_mutex_attr static_mutex_attr = PTHREAD_MUTEXATTR_STATIC_INITIALIZER; static pthread_mutexattr_t static_mattr = &static_mutex_attr; static pthread_mutex_t spinlock_static_lock; static struct spinlock_extra extra[MAX_SPINLOCKS]; static int spinlock_count = 0; static int initialized = 0; LT10_COMPAT_PRIVATE(_spinlock); LT10_COMPAT_PRIVATE(_spinlock_debug); LT10_COMPAT_PRIVATE(_spinunlock); /* * These are for compatability only. Spinlocks of this type * are deprecated. */ void _spinunlock(spinlock_t *lck) { - struct spinlock_extra *extra; + struct spinlock_extra *sl_extra; - extra = (struct spinlock_extra *)lck->fname; - _pthread_mutex_unlock(&extra->lock); + sl_extra = ((nv_spinlock_t *)lck)->extra; + _pthread_mutex_unlock(&sl_extra->lock); } /* * Lock a location for the running thread. Yield to allow other * threads to run if this thread is blocked because the lock is * not available. Note that this function does not sleep. It * assumes that the lock will be available very soon. */ void _spinlock(spinlock_t *lck) { - struct spinlock_extra *extra; + struct spinlock_extra *sl_extra; if (!__isthreaded) PANIC("Spinlock called when not threaded."); if (!initialized) PANIC("Spinlocks not initialized."); /* * Try to grab the lock and loop if another thread grabs * it before we do. */ if (lck->fname == NULL) init_spinlock(lck); - extra = (struct spinlock_extra *)lck->fname; - _pthread_mutex_lock(&extra->lock); + sl_extra = ((nv_spinlock_t *)lck)->extra; + _pthread_mutex_lock(&sl_extra->lock); } /* * Lock a location for the running thread. Yield to allow other * threads to run if this thread is blocked because the lock is * not available. Note that this function does not sleep. It * assumes that the lock will be available very soon. * * This function checks if the running thread has already locked the * location, warns if this occurs and creates a thread dump before * returning. */ void -_spinlock_debug(spinlock_t *lck, char *fname, int lineno) +_spinlock_debug(spinlock_t *lck, char *fname __unused, int lineno __unused) { _spinlock(lck); } static void init_spinlock(spinlock_t *lck) { _pthread_mutex_lock(&spinlock_static_lock); if ((lck->fname == NULL) && (spinlock_count < MAX_SPINLOCKS)) { lck->fname = (char *)&extra[spinlock_count]; extra[spinlock_count].owner = lck; spinlock_count++; } _pthread_mutex_unlock(&spinlock_static_lock); if (lck->fname == NULL) PANIC("Exceeded max spinlocks"); } void _thr_spinlock_init(void) { int i; if (initialized != 0) { _thr_mutex_reinit(&spinlock_static_lock); for (i = 0; i < spinlock_count; i++) _thr_mutex_reinit(&extra[i].lock); } else { if (_pthread_mutex_init(&spinlock_static_lock, &static_mattr)) PANIC("Cannot initialize spinlock_static_lock"); for (i = 0; i < MAX_SPINLOCKS; i++) { if (_pthread_mutex_init(&extra[i].lock, &static_mattr)) PANIC("Cannot initialize spinlock extra"); } initialized = 1; } } Index: head/lib/libkse/thread/thr_stack.c =================================================================== --- head/lib/libkse/thread/thr_stack.c (revision 174111) +++ head/lib/libkse/thread/thr_stack.c (revision 174112) @@ -1,258 +1,264 @@ /* * Copyright (c) 2001 Daniel Eischen * Copyright (c) 2000-2001 Jason Evans * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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$ */ + +#include "namespace.h" #include #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" /* Spare thread stack. */ struct stack { LIST_ENTRY(stack) qe; /* Stack queue linkage. */ size_t stacksize; /* Stack size (rounded up). */ size_t guardsize; /* Guard size. */ void *stackaddr; /* Stack address. */ }; /* * Default sized (stack and guard) spare stack queue. Stacks are cached * to avoid additional complexity managing mmap()ed stack regions. Spare * stacks are used in LIFO order to increase cache locality. */ static LIST_HEAD(, stack) dstackq = LIST_HEAD_INITIALIZER(dstackq); /* * Miscellaneous sized (non-default stack and/or guard) spare stack queue. * Stacks are cached to avoid additional complexity managing mmap()ed * stack regions. This list is unordered, since ordering on both stack * size and guard size would be more trouble than it's worth. Stacks are * allocated from this cache on a first size match basis. */ static LIST_HEAD(, stack) mstackq = LIST_HEAD_INITIALIZER(mstackq); /** * Base address of the last stack allocated (including its red zone, if * there is one). Stacks are allocated contiguously, starting beyond the * top of the main stack. When a new stack is created, a red zone is * typically created (actually, the red zone is mapped with PROT_NONE) above * the top of the stack, such that the stack will not be able to grow all * the way to the bottom of the next stack. This isn't fool-proof. It is * possible for a stack to grow by a large amount, such that it grows into * the next stack, and as long as the memory within the red zone is never * accessed, nothing will prevent one thread stack from trouncing all over * the next. * * low memory * . . . . . . . . . . . . . . . . . . * | | * | stack 3 | start of 3rd thread stack * +-----------------------------------+ * | | * | Red Zone (guard page) | red zone for 2nd thread * | | * +-----------------------------------+ * | stack 2 - PTHREAD_STACK_DEFAULT | top of 2nd thread stack * | | * | | * | | * | | * | stack 2 | * +-----------------------------------+ <-- start of 2nd thread stack * | | * | Red Zone | red zone for 1st thread * | | * +-----------------------------------+ * | stack 1 - PTHREAD_STACK_DEFAULT | top of 1st thread stack * | | * | | * | | * | | * | stack 1 | * +-----------------------------------+ <-- start of 1st thread stack * | | (initial value of last_stack) * | Red Zone | * | | red zone for main thread * +-----------------------------------+ * | USRSTACK - PTHREAD_STACK_INITIAL | top of main thread stack * | | ^ * | | | * | | | * | | | stack growth * | | * +-----------------------------------+ <-- start of main thread stack * (USRSTACK) * high memory * */ static void *last_stack = NULL; /* * Round size up to the nearest multiple of * _thr_page_size. */ static inline size_t round_up(size_t size) { if (size % _thr_page_size != 0) size = ((size / _thr_page_size) + 1) * _thr_page_size; - return size; + return (size); } int _thr_stack_alloc(struct pthread_attr *attr) { struct stack *spare_stack; struct kse *curkse; kse_critical_t crit; size_t stacksize; size_t guardsize; char *stackaddr; /* * Round up stack size to nearest multiple of _thr_page_size so * that mmap() * will work. If the stack size is not an even * multiple, we end up initializing things such that there is * unused space above the beginning of the stack, so the stack * sits snugly against its guard. */ stacksize = round_up(attr->stacksize_attr); guardsize = round_up(attr->guardsize_attr); attr->stackaddr_attr = NULL; attr->flags &= ~THR_STACK_USER; /* * Use the garbage collector lock for synchronization of the * spare stack lists and allocations from usrstack. */ crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); /* * If the stack and guard sizes are default, try to allocate a stack * from the default-size stack cache: */ if ((stacksize == _thr_stack_default) && (guardsize == _thr_guard_default)) { if ((spare_stack = LIST_FIRST(&dstackq)) != NULL) { /* Use the spare stack. */ LIST_REMOVE(spare_stack, qe); attr->stackaddr_attr = spare_stack->stackaddr; } } /* * The user specified a non-default stack and/or guard size, so try to * allocate a stack from the non-default size stack cache, using the * rounded up stack size (stack_size) in the search: */ else { LIST_FOREACH(spare_stack, &mstackq, qe) { if (spare_stack->stacksize == stacksize && spare_stack->guardsize == guardsize) { LIST_REMOVE(spare_stack, qe); attr->stackaddr_attr = spare_stack->stackaddr; break; } } } if (attr->stackaddr_attr != NULL) { /* A cached stack was found. Release the lock. */ KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); } else { /* Allocate a stack from usrstack. */ if (last_stack == NULL) - last_stack = _usrstack - _thr_stack_initial - - _thr_guard_default; + last_stack = (void *)((uintptr_t)_usrstack - + (uintptr_t)_thr_stack_initial - + (uintptr_t)_thr_guard_default); /* Allocate a new stack. */ - stackaddr = last_stack - stacksize - guardsize; + stackaddr = (void *)((uintptr_t)last_stack - + (uintptr_t)stacksize - (uintptr_t)guardsize); /* * Even if stack allocation fails, we don't want to try to * use this location again, so unconditionally decrement * last_stack. Under normal operating conditions, the most * likely reason for an mmap() error is a stack overflow of * the adjacent thread stack. */ - last_stack -= (stacksize + guardsize); + last_stack = (void *)((uintptr_t)last_stack - + (uintptr_t)(stacksize + guardsize)); /* Release the lock before mmap'ing it. */ KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); /* Map the stack and guard page together, and split guard page from allocated space: */ if ((stackaddr = mmap(stackaddr, stacksize+guardsize, PROT_READ | PROT_WRITE, MAP_STACK, -1, 0)) != MAP_FAILED && (guardsize == 0 || mprotect(stackaddr, guardsize, PROT_NONE) == 0)) { stackaddr += guardsize; } else { if (stackaddr != MAP_FAILED) munmap(stackaddr, stacksize + guardsize); stackaddr = NULL; } attr->stackaddr_attr = stackaddr; } if (attr->stackaddr_attr != NULL) return (0); else return (-1); } /* This function must be called with _thread_list_lock held. */ void _thr_stack_free(struct pthread_attr *attr) { struct stack *spare_stack; if ((attr != NULL) && ((attr->flags & THR_STACK_USER) == 0) && (attr->stackaddr_attr != NULL)) { - spare_stack = (attr->stackaddr_attr + attr->stacksize_attr - - sizeof(struct stack)); + spare_stack = (struct stack *)((uintptr_t)attr->stackaddr_attr + + (uintptr_t)attr->stacksize_attr - sizeof(struct stack)); spare_stack->stacksize = round_up(attr->stacksize_attr); spare_stack->guardsize = round_up(attr->guardsize_attr); spare_stack->stackaddr = attr->stackaddr_attr; if (spare_stack->stacksize == _thr_stack_default && spare_stack->guardsize == _thr_guard_default) { /* Default stack/guard size. */ LIST_INSERT_HEAD(&dstackq, spare_stack, qe); } else { /* Non-default stack/guard size. */ LIST_INSERT_HEAD(&mstackq, spare_stack, qe); } attr->stackaddr_attr = NULL; } } Index: head/lib/libkse/thread/thr_suspend_np.c =================================================================== --- head/lib/libkse/thread/thr_suspend_np.c (revision 174111) +++ head/lib/libkse/thread/thr_suspend_np.c (revision 174112) @@ -1,111 +1,117 @@ /* * Copyright (c) 1995-1998 John Birrell . * 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. 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 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$ */ + +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" + +int _pthread_suspend_np(pthread_t thread); +void _pthread_suspend_all_np(void); static void suspend_common(struct pthread *thread); LT10_COMPAT_PRIVATE(_pthread_suspend_np); LT10_COMPAT_DEFAULT(pthread_suspend_np); LT10_COMPAT_PRIVATE(_pthread_suspend_all_np); LT10_COMPAT_DEFAULT(pthread_suspend_all_np); __weak_reference(_pthread_suspend_np, pthread_suspend_np); __weak_reference(_pthread_suspend_all_np, pthread_suspend_all_np); /* Suspend a thread: */ int _pthread_suspend_np(pthread_t thread) { struct pthread *curthread = _get_curthread(); int ret; /* Suspending the current thread doesn't make sense. */ if (thread == _get_curthread()) ret = EDEADLK; /* Add a reference to the thread: */ else if ((ret = _thr_ref_add(curthread, thread, /*include dead*/0)) == 0) { /* Lock the threads scheduling queue: */ THR_SCHED_LOCK(curthread, thread); suspend_common(thread); /* Unlock the threads scheduling queue: */ THR_SCHED_UNLOCK(curthread, thread); /* Don't forget to remove the reference: */ _thr_ref_delete(curthread, thread); } return (ret); } void _pthread_suspend_all_np(void) { struct pthread *curthread = _get_curthread(); struct pthread *thread; kse_critical_t crit; /* Take the thread list lock: */ crit = _kse_critical_enter(); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock); TAILQ_FOREACH(thread, &_thread_list, tle) { if (thread != curthread) { THR_SCHED_LOCK(curthread, thread); suspend_common(thread); THR_SCHED_UNLOCK(curthread, thread); } } /* Release the thread list lock: */ KSE_LOCK_RELEASE(curthread->kse, &_thread_list_lock); _kse_critical_leave(crit); } void suspend_common(struct pthread *thread) { if ((thread->state != PS_DEAD) && (thread->state != PS_DEADLOCK) && ((thread->flags & THR_FLAGS_EXITING) == 0)) { thread->flags |= THR_FLAGS_SUSPENDED; if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0) { THR_RUNQ_REMOVE(thread); THR_SET_STATE(thread, PS_SUSPENDED); } #ifdef NOT_YET if ((thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0) /* ??? */ #endif } } Index: head/lib/libkse/thread/thr_switch_np.c =================================================================== --- head/lib/libkse/thread/thr_switch_np.c (revision 174111) +++ head/lib/libkse/thread/thr_switch_np.c (revision 174112) @@ -1,57 +1,60 @@ /* * Copyright (c) 1998 Daniel Eischen . * 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 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$ */ + +#include "namespace.h" #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_pthread_switch_add_np); LT10_COMPAT_DEFAULT(pthread_switch_add_np); LT10_COMPAT_PRIVATE(_pthread_switch_delete_np); LT10_COMPAT_DEFAULT(pthread_switch_delete_np); __weak_reference(_pthread_switch_add_np, pthread_switch_add_np); __weak_reference(_pthread_switch_delete_np, pthread_switch_delete_np); int -_pthread_switch_add_np(pthread_switch_routine_t routine) +_pthread_switch_add_np(pthread_switch_routine_t routine __unused) { return (ENOTSUP); } int -_pthread_switch_delete_np(pthread_switch_routine_t routine) +_pthread_switch_delete_np(pthread_switch_routine_t routine __unused) { return (ENOTSUP); } Index: head/lib/libkse/thread/thr_symbols.c =================================================================== --- head/lib/libkse/thread/thr_symbols.c (revision 174111) +++ head/lib/libkse/thread/thr_symbols.c (revision 174112) @@ -1,78 +1,80 @@ /* * Copyright (c) 2004 David Xu * 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. 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 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$ */ +#include "namespace.h" #include #include #include #include +#include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(_thread_off_tcb); LT10_COMPAT_PRIVATE(_thread_off_tmbx); LT10_COMPAT_PRIVATE(_thread_off_next); LT10_COMPAT_PRIVATE(_thread_off_attr_flags); LT10_COMPAT_PRIVATE(_thread_off_kse); LT10_COMPAT_PRIVATE(_thread_off_kse_locklevel); LT10_COMPAT_PRIVATE(_thread_off_thr_locklevel); LT10_COMPAT_PRIVATE(_thread_off_linkmap); LT10_COMPAT_PRIVATE(_thread_off_tlsindex); LT10_COMPAT_PRIVATE(_thread_size_key); LT10_COMPAT_PRIVATE(_thread_off_key_allocated); LT10_COMPAT_PRIVATE(_thread_off_key_destructor); LT10_COMPAT_PRIVATE(_thread_max_keys); LT10_COMPAT_PRIVATE(_thread_off_dtv); LT10_COMPAT_PRIVATE(_thread_off_state); LT10_COMPAT_PRIVATE(_thread_state_running); LT10_COMPAT_PRIVATE(_thread_state_zoombie); /* A collection of symbols needed by debugger */ /* int _libkse_debug */ int _thread_off_tcb = offsetof(struct pthread, tcb); int _thread_off_tmbx = offsetof(struct tcb, tcb_tmbx); int _thread_off_next = offsetof(struct pthread, tle.tqe_next); int _thread_off_attr_flags = offsetof(struct pthread, attr.flags); int _thread_off_kse = offsetof(struct pthread, kse); int _thread_off_kse_locklevel = offsetof(struct kse, k_locklevel); int _thread_off_thr_locklevel = offsetof(struct pthread, locklevel); int _thread_off_linkmap = offsetof(Obj_Entry, linkmap); int _thread_off_tlsindex = offsetof(Obj_Entry, tlsindex); int _thread_size_key = sizeof(struct pthread_key); int _thread_off_key_allocated = offsetof(struct pthread_key, allocated); int _thread_off_key_destructor = offsetof(struct pthread_key, destructor); int _thread_max_keys = PTHREAD_KEYS_MAX; int _thread_off_dtv = DTV_OFFSET; int _thread_off_state = offsetof(struct pthread, state); int _thread_state_running = PS_RUNNING; int _thread_state_zoombie = PS_DEAD; int _thread_off_sigmask = offsetof(struct pthread, sigmask); int _thread_off_sigpend = offsetof(struct pthread, sigpend); Index: head/lib/libkse/thread/thr_system.c =================================================================== --- head/lib/libkse/thread/thr_system.c (revision 174111) +++ head/lib/libkse/thread/thr_system.c (revision 174112) @@ -1,54 +1,58 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" + +int _system(const char *string); extern int __system(const char *); LT10_COMPAT_PRIVATE(_system); LT10_COMPAT_DEFAULT(system); __weak_reference(_system, system); int _system(const char *string) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __system(string); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_tcdrain.c =================================================================== --- head/lib/libkse/thread/thr_tcdrain.c (revision 174111) +++ head/lib/libkse/thread/thr_tcdrain.c (revision 174112) @@ -1,54 +1,57 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ +#include "namespace.h" #include #include +#include "un-namespace.h" #include "thr_private.h" +int _tcdrain(int fd); extern int __tcdrain(int); LT10_COMPAT_PRIVATE(_tcdrain); LT10_COMPAT_DEFAULT(tcdrain); __weak_reference(_tcdrain, tcdrain); int _tcdrain(int fd) { struct pthread *curthread = _get_curthread(); int ret; _thr_cancel_enter(curthread); ret = __tcdrain(fd); _thr_cancel_leave(curthread, 1); return (ret); } Index: head/lib/libkse/thread/thr_vfork.c =================================================================== --- head/lib/libkse/thread/thr_vfork.c (revision 174111) +++ head/lib/libkse/thread/thr_vfork.c (revision 174112) @@ -1,17 +1,19 @@ /* * $FreeBSD$ */ -#include +#include #include "thr_private.h" LT10_COMPAT_PRIVATE(_vfork); LT10_COMPAT_DEFAULT(vfork); + +int _vfork(void); __weak_reference(_vfork, vfork); int _vfork(void) { return (fork()); } Index: head/lib/libkse/thread/thr_wait.c =================================================================== --- head/lib/libkse/thread/thr_wait.c (revision 174111) +++ head/lib/libkse/thread/thr_wait.c (revision 174112) @@ -1,53 +1,55 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ #include #include "thr_private.h" -extern int __wait(int *); - LT10_COMPAT_PRIVATE(_wait); LT10_COMPAT_DEFAULT(wait); + +extern int __wait(int *); + +pid_t _wait(int *istat); __weak_reference(_wait, wait); pid_t _wait(int *istat) { struct pthread *curthread = _get_curthread(); pid_t ret; _thr_cancel_enter(curthread); ret = __wait(istat); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_wait4.c =================================================================== --- head/lib/libkse/thread/thr_wait4.c (revision 174111) +++ head/lib/libkse/thread/thr_wait4.c (revision 174112) @@ -1,57 +1,59 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ */ -#include #include "namespace.h" +#include #include #include #include #include "un-namespace.h" #include "thr_private.h" LT10_COMPAT_PRIVATE(__wait4); LT10_COMPAT_DEFAULT(wait4); + +pid_t __wait4(pid_t pid, int *istat, int options, struct rusage *rusage); __weak_reference(__wait4, wait4); pid_t __wait4(pid_t pid, int *istat, int options, struct rusage *rusage) { struct pthread *curthread = _get_curthread(); pid_t ret; _thr_cancel_enter(curthread); ret = _wait4(pid, istat, options, rusage); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_waitpid.c =================================================================== --- head/lib/libkse/thread/thr_waitpid.c (revision 174111) +++ head/lib/libkse/thread/thr_waitpid.c (revision 174112) @@ -1,55 +1,57 @@ /* * Copyright (C) 2000 Jason Evans . * 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(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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$ */ #include #include #include #include "thr_private.h" LT10_COMPAT_PRIVATE(_waitpid); LT10_COMPAT_DEFAULT(waitpid); extern int __waitpid(pid_t, int *, int); +pid_t _waitpid(pid_t wpid, int *status, int options); + __weak_reference(_waitpid, waitpid); pid_t _waitpid(pid_t wpid, int *status, int options) { struct pthread *curthread = _get_curthread(); pid_t ret; _thr_cancel_enter(curthread); ret = __waitpid(wpid, status, options); _thr_cancel_leave(curthread, 1); - return ret; + return (ret); } Index: head/lib/libkse/thread/thr_write.c =================================================================== --- head/lib/libkse/thread/thr_write.c (revision 174111) +++ head/lib/libkse/thread/thr_write.c (revision 174112) @@ -1,56 +1,58 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ * */ #include #include #include #include #include #include #include "thr_private.h" LT10_COMPAT_PRIVATE(__write); LT10_COMPAT_DEFAULT(write); +__ssize_t __write(int fd, const void *buf, size_t nbytes); + __weak_reference(__write, write); ssize_t __write(int fd, const void *buf, size_t nbytes) { struct pthread *curthread = _get_curthread(); ssize_t ret; _thr_cancel_enter(curthread); ret = __sys_write(fd, buf, nbytes); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_writev.c =================================================================== --- head/lib/libkse/thread/thr_writev.c (revision 174111) +++ head/lib/libkse/thread/thr_writev.c (revision 174112) @@ -1,58 +1,60 @@ /* * Copyright (c) 1995-1998 John Birrell * 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. 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 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$ * */ #include #include #include #include #include #include #include #include #include "thr_private.h" LT10_COMPAT_PRIVATE(__writev); LT10_COMPAT_DEFAULT(writev); +ssize_t __writev(int fd, const struct iovec *iov, int iovcnt); + __weak_reference(__writev, writev); ssize_t __writev(int fd, const struct iovec *iov, int iovcnt) { struct pthread *curthread = _get_curthread(); ssize_t ret; _thr_cancel_enter(curthread); ret = __sys_writev(fd, iov, iovcnt); _thr_cancel_leave(curthread, 1); return ret; } Index: head/lib/libkse/thread/thr_yield.c =================================================================== --- head/lib/libkse/thread/thr_yield.c (revision 174111) +++ head/lib/libkse/thread/thr_yield.c (revision 174112) @@ -1,75 +1,77 @@ /* * Copyright (c) 1995 John Birrell . * 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. 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 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$ */ #include #include "thr_private.h" LT10_COMPAT_PRIVATE(_sched_yield); LT10_COMPAT_DEFAULT(sched_yield); LT10_COMPAT_PRIVATE(_pthread_yield); LT10_COMPAT_DEFAULT(pthread_yield); +int _sched_yield(void); + __weak_reference(_sched_yield, sched_yield); __weak_reference(_pthread_yield, pthread_yield); int _sched_yield(void) { struct pthread *curthread = _get_curthread(); if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) return (__sys_sched_yield()); /* Reset the accumulated time slice value for the current thread: */ curthread->slice_usec = -1; /* Schedule the next thread: */ _thr_sched_switch(curthread); /* Always return no error. */ return(0); } /* Draft 4 yield */ void _pthread_yield(void) { struct pthread *curthread = _get_curthread(); if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { __sys_sched_yield(); return; } /* Reset the accumulated time slice value for the current thread: */ curthread->slice_usec = -1; /* Schedule the next thread: */ _thr_sched_switch(curthread); }