diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile new file mode 100644 index 000000000..94e537b6e --- /dev/null +++ b/lib/libpthread/Makefile @@ -0,0 +1,245 @@ +# $NetBSD: Makefile,v 1.85 2014/12/16 20:05:54 pooka Exp $ +# + +WARNS?= 5 +LIB= pthread + +.include + +.if defined(PTHREAD_MACHINE_ARCH) && !empty(PTHREAD_MACHINE_ARCH) && \ + exists(${.CURDIR}/arch/${PTHREAD_MACHINE_ARCH}) +ARCHSUBDIR= ${PTHREAD_MACHINE_ARCH} +.elif defined(PTHREAD_MACHINE_CPU) && !empty(PTHREAD_MACHINE_CPU) && \ + exists(${.CURDIR}/arch/${PTHREAD_MACHINE_CPU}) +ARCHSUBDIR= ${PTHREAD_MACHINE_CPU} +.elif exists(${.CURDIR}/arch/${MACHINE_ARCH}) +ARCHSUBDIR= ${MACHINE_ARCH} +.elif exists(${.CURDIR}/arch/${MACHINE_CPU}) +ARCHSUBDIR= ${MACHINE_CPU} +.else +.BEGIN: + @echo "WARNING: no ARCHSUBDIR for ${MACHINE_ARCH}/${MACHINE_CPU}; skipping..." +.endif + +INCS= pthread.h pthread_types.h pthread_queue.h +INCSDIR=/usr/include + +.if defined(ARCHSUBDIR) + +ARCHDIR= ${.CURDIR}/arch/${ARCHSUBDIR} +.PATH: ${ARCHDIR} + +CPPFLAGS+= -I${ARCHDIR} -I${.CURDIR} -I${.OBJDIR} -D_LIBC -D_REENTRANT +CPPFLAGS+= -I${.CURDIR}/../libc/include +CPPFLAGS+= -D__LIBPTHREAD_SOURCE__ -D__LIBC_THREAD_STUBS + +# XXX: This crappy poke at libc's internals needs to be fixed. +CPPFLAGS+=-I${NETBSDSRCDIR}/sys -I${.CURDIR}/../libc + +# providing alternative MI implementations for creating an lwp is +# possible by setting PTHREAD_MAKELWP. Currently, alternatives are +# set by the rumprun software stacks (see repo.rumpkernel.org) +PTHREAD_MAKELWP?= pthread_makelwp_netbsd.c + +# +# NOTE: When you create a new file for libpthread, make sure that pthread.c +# gets a reference to a symbol in that file. Otherwise, Unix's stupid static +# library semantics will end up discarding potentially important objects. +# +SRCS= pthread.c +SRCS+= pthread_attr.c +SRCS+= pthread_barrier.c +# used by rumprun-posix to work around symbol collisions +.if ${PTHREAD_CANCELSTUB:Uyes} != "no" +SRCS+= pthread_cancelstub.c +.endif +SRCS+= pthread_cond.c +SRCS+= pthread_lock.c +SRCS+= ${PTHREAD_MAKELWP} +SRCS+= pthread_misc.c +SRCS+= pthread_mutex.c +SRCS+= pthread_once.c +SRCS+= pthread_rwlock.c +SRCS+= pthread_specific.c +SRCS+= pthread_spin.c +SRCS+= pthread_tsd.c +SRCS+= res_state.c +SRCS+= sem.c +# Architecture-dependent files +.if exists(${ARCHDIR}/pthread_md.S) +SRCS+= pthread_md.S +.endif +.if exists(${ARCHDIR}/Makefile.inc) +.include "${ARCHDIR}/Makefile.inc" +.endif + +# The PTHREAD__COMPAT flag builds a libpthread that can be dropped +# into a NetBSD 2/3/4 chroot with a NetBSD 5 or later kernel. +# This makes threading work in the chroot, no other modifications +# required. +# +.if defined(PTHREAD__COMPAT) +SRCS+= pthread_compat.c +.PATH.c: ${.CURDIR}/../../common/lib/libc/arch/${ARCHSUBDIR}/atomic +.PATH.S: ${.CURDIR}/../../common/lib/libc/arch/${ARCHSUBDIR}/atomic +.PATH.c: ${.CURDIR}/../../common/lib/libc/atomic +.PATH.c: ${.CURDIR}/../libc/misc +.include "../../common/lib/libc/arch/${ARCHSUBDIR}/atomic/Makefile.inc" +.endif + +ALIGN_FUNCTIONS= ${${ACTIVE_CC} == "gcc":? -falign-functions=32 :} + +.if ${MACHINE_CPU} != "m68k" && ${MACHINE_CPU} != "sh3" && ${MACHINE_ARCH} != "vax" +OMIT_FRAME_POINTER= -fomit-frame-pointer +.else +OMIT_FRAME_POINTER= +.endif + +# The TSD routines are used in the implementation of profiling, and so +# can't be profiled themselves. +COPTS.pthread_specific.c+= ${OMIT_FRAME_POINTER} ${ALIGN_FUNCTIONS} +pthread_specific.po: pthread_specific.o + ${_MKTARGET_CREATE} + cp pthread_specific.o pthread_specific.po + +# Internal spinlock routines are performance critical. Don't profile them, +# it's incompatibile with -fomit-frame-pointer. +COPTS.pthread_lock.c+= ${OMIT_FRAME_POINTER} ${ALIGN_FUNCTIONS} +pthread_lock.po: pthread_lock.o + ${_MKTARGET_CREATE} + cp pthread_lock.o pthread_lock.po + +COPTS.pthread_mutex.c+= ${OMIT_FRAME_POINTER} ${ALIGN_FUNCTIONS} +pthread_mutex.po: pthread_mutex.o + ${_MKTARGET_CREATE} + cp pthread_mutex.o pthread_mutex.po + +COPTS.pthread.c += -Wno-stack-protector -Wno-format-nonliteral +COPTS.pthread_attr.c += -Wno-format-nonliteral + +MAN+= affinity.3 pthread.3 \ + pthread_attr.3 \ + pthread_attr_get_np.3 \ + pthread_attr_getdetachstate.3 \ + pthread_attr_getguardsize.3 \ + pthread_attr_getinheritsched.3 \ + pthread_attr_getname_np.3 \ + pthread_attr_getschedparam.3 \ + pthread_attr_getscope.3 \ + pthread_attr_getstack.3 \ + pthread_attr_setcreatesuspend_np.3 \ + pthread_barrier.3 pthread_barrierattr.3 \ + pthread_cancel.3 pthread_cleanup_push.3 \ + pthread_cond.3 pthread_condattr.3 \ + pthread_create.3 pthread_detach.3 pthread_equal.3 \ + pthread_curcpu_np.3 \ + pthread_exit.3 \ + pthread_getname_np.3 \ + pthread_getspecific.3 pthread_join.3 \ + pthread_key_create.3 pthread_kill.3 \ + pthread_mutex.3 pthread_mutexattr.3 \ + pthread_once.3 pthread_rwlock.3 pthread_rwlockattr.3 \ + pthread_schedparam.3 pthread_self.3 \ + pthread_sigmask.3 pthread_spin.3 \ + pthread_suspend_np.3 pthread_testcancel.3 + +MLINKS+= pthread_attr_get_np.3 pthread_getattr_np.3 +MLINKS+= affinity.3 pthread_setaffinity_np.3 +MLINKS+= affinity.3 pthread_getaffinity_np.3 + +MLINKS+= pthread_attr.3 pthread_attr_init.3 +MLINKS+= pthread_attr.3 pthread_attr_destroy.3 + +MLINKS+= pthread_attr_getdetachstate.3 pthread_attr_setdetachstate.3 +MLINKS+= pthread_attr_getguardsize.3 pthread_attr_setguardsize.3 +MLINKS+= pthread_attr_getinheritsched.3 pthread_attr_setinheritsched.3 +MLINKS+= pthread_attr_getname_np.3 pthread_attr_setname_np.3 + +MLINKS+= pthread_attr_getschedparam.3 pthread_attr_setschedparam.3 \ + pthread_attr_getschedparam.3 pthread_attr_getschedpolicy.3 \ + pthread_attr_getschedparam.3 pthread_attr_setschedpolicy.3 + +MLINKS+= pthread_attr_getscope.3 pthread_attr_setscope.3 + +MLINKS+= pthread_attr_getstack.3 pthread_attr_setstack.3 \ + pthread_attr_getstack.3 pthread_attr_getstacksize.3 \ + pthread_attr_getstack.3 pthread_attr_setstacksize.3 \ + pthread_attr_getstack.3 pthread_attr_getstackaddr.3 \ + pthread_attr_getstack.3 pthread_attr_setstackaddr.3 + +MLINKS+= pthread_cleanup_push.3 pthread_cleanup_pop.3 + +MLINKS+= pthread_barrier.3 pthread_barrier_init.3 +MLINKS+= pthread_barrier.3 pthread_barrier_destroy.3 +MLINKS+= pthread_barrier.3 pthread_barrier_wait.3 + +MLINKS+= pthread_barrierattr.3 pthread_barrierattr_init.3 +MLINKS+= pthread_barrierattr.3 pthread_barrierattr_destroy.3 + +MLINKS+= pthread_cond.3 pthread_cond_init.3 +MLINKS+= pthread_cond.3 pthread_cond_destroy.3 +MLINKS+= pthread_cond.3 pthread_cond_broadcast.3 +MLINKS+= pthread_cond.3 pthread_cond_wait.3 +MLINKS+= pthread_cond.3 pthread_cond_signal.3 +MLINKS+= pthread_cond.3 pthread_cond_timedwait.3 + +MLINKS+= pthread_condattr.3 pthread_condattr_init.3 +MLINKS+= pthread_condattr.3 pthread_condattr_destroy.3 +MLINKS+= pthread_condattr.3 pthread_condattr_setclock.3 + +MLINKS+= pthread_getname_np.3 pthread_setname_np.3 +MLINKS+= pthread_getspecific.3 pthread_setspecific.3 +MLINKS+= pthread_key_create.3 pthread_key_delete.3 + +MLINKS+= pthread_mutex.3 pthread_mutex_init.3 +MLINKS+= pthread_mutex.3 pthread_mutex_destroy.3 +MLINKS+= pthread_mutex.3 pthread_mutex_lock.3 +MLINKS+= pthread_mutex.3 pthread_mutex_trylock.3 +MLINKS+= pthread_mutex.3 pthread_mutex_unlock.3 + +MLINKS+= pthread_mutexattr.3 pthread_mutexattr_init.3 +MLINKS+= pthread_mutexattr.3 pthread_mutexattr_destroy.3 +MLINKS+= pthread_mutexattr.3 pthread_mutexattr_settype.3 +MLINKS+= pthread_mutexattr.3 pthread_mutexattr_gettype.3 + +MLINKS+= pthread_rwlock.3 pthread_rwlock_init.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_destroy.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_rdlock.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_wrlock.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_unlock.3 + +MLINKS+= pthread_rwlock.3 pthread_rwlock_timedrdlock.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_timedwrlock.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_tryrdlock.3 +MLINKS+= pthread_rwlock.3 pthread_rwlock_trywrlock.3 + +MLINKS+= pthread_rwlockattr.3 pthread_rwlockattr_init.3 +MLINKS+= pthread_rwlockattr.3 pthread_rwlockattr_destroy.3 + +MLINKS+= pthread_spin.3 pthread_spin_init.3 +MLINKS+= pthread_spin.3 pthread_spin_destroy.3 +MLINKS+= pthread_spin.3 pthread_spin_lock.3 +MLINKS+= pthread_spin.3 pthread_spin_trylock.3 +MLINKS+= pthread_spin.3 pthread_spin_unlock.3 + +MLINKS+= pthread_schedparam.3 pthread_setschedparam.3 +MLINKS+= pthread_schedparam.3 pthread_getschedparam.3 +MLINKS+= pthread_suspend_np.3 pthread_resume_np.3 +MLINKS+= pthread_testcancel.3 pthread_setcancelstate.3 +MLINKS+= pthread_testcancel.3 pthread_setcanceltype.3 + +.include + +.else + +.include +.include +.include + +.endif + +# WARNS=2 sets -Wcast-qual. This causes problems for one of +# pthread_setspecific() and pthread_getspecific(), since the constness +# of the argument to setspecific() has to be discarded *somewhere* +# before returning it from getspecific(). +CWARNFLAGS+= -Wno-cast-qual diff --git a/lib/libpthread/README b/lib/libpthread/README new file mode 100644 index 000000000..a9e8e84c5 --- /dev/null +++ b/lib/libpthread/README @@ -0,0 +1,9 @@ +$NetBSD: README,v 1.6 2009/04/16 18:37:30 wiz Exp $ + +When making changes to libpthread, please ensure that libpthread_dbg +still compiles. + +Due to limitations in the current pthread implementation, makecontext(3) +and sigaltstack(2) should not be used in programs which link against +libpthread (whether threads are used or not). This has been noted in the +makecontext(3), sigaltstack(2), and pthread(3) man pages. diff --git a/lib/libpthread/TODO b/lib/libpthread/TODO new file mode 100644 index 000000000..1a4003090 --- /dev/null +++ b/lib/libpthread/TODO @@ -0,0 +1,12 @@ +$NetBSD: TODO,v 1.17 2012/02/03 21:11:17 joerg Exp $ + +Interfaces/features to implement: + +- Realtime extensions: priority inheritance. + +- Allow threads to change their stack size. + +- Allow threads to modify the red zone size; cf. pthread_attr_setguardsize(3). + +- Keep a pool of dead LWPs so that we do not have take the full hit of + _lwp_create() every time pthread_create() is called. diff --git a/lib/libpthread/affinity.3 b/lib/libpthread/affinity.3 new file mode 100644 index 000000000..b8eae499d --- /dev/null +++ b/lib/libpthread/affinity.3 @@ -0,0 +1,140 @@ +.\" $NetBSD: affinity.3,v 1.8 2011/12/05 10:27:40 wiz Exp $ +.\" +.\" Copyright (c) 2008 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Mindaugas Rasiukevicius . +.\" +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd December 4, 2011 +.Dt AFFINITY 3 +.Os +.Sh NAME +.Nm pthread_setaffinity_np , +.Nm pthread_getaffinity_np +.Nd affinity of threads +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.In sched.h +.Ft int +.Fn pthread_setaffinity_np "pthread_t thread" "size_t size" "cpuset_t *set" +.Ft int +.Fn pthread_getaffinity_np "pthread_t thread" "size_t size" "cpuset_t *set" +.Sh DESCRIPTION +Thread affinity allows to run the thread on specified CPU or CPUs only. +.Pp +The +.Fn pthread_setaffinity_np +function sets the affinity mask +.Fa set +for +.Fa thread . +At least one valid CPU must be set in the mask. +.Pp +The +.Fn pthread_getaffinity_np +function gets the affinity mask of +.Fa thread +into +.Fa set . +Note that +.Fa set +must be created and initialized using the +.Xr cpuset 3 +functions. +.Sh IMPLEMENTATION NOTES +Setting CPU +.Nm +requires super-user privileges. +Ordinary users can be allowed to control CPU affinity +of their threads via the +.Pa security.models.extensions.user_set_cpu_affinity +.Xr sysctl 7 . +See +.Xr secmodel_extensions 9 . +.Pp +Portable applications should not use the +.Fn pthread_setaffinity_np +and +.Fn pthread_getaffinity_np +functions. +.Sh RETURN VALUES +The +.Fn pthread_setaffinity_np +and +.Fn pthread_getaffinity_np +functions return 0 on success. +Otherwise, an error number is returned to indicate the error. +.Sh EXAMPLES +An example of code fragment, which sets the affinity for the current +thread to the CPU whose ID is 0: +.Bd -literal + cpuset_t *cset; + pthread_t pth; + cpuid_t ci; + + cset = cpuset_create(); + if (cset == NULL) { + err(EXIT_FAILURE, "cpuset_create"); + } + ci = 0; + cpuset_set(ci, cset); + + pth = pthread_self(); + error = pthread_setaffinity_np(pth, cpuset_size(cset), cset); + if (error) { + ... + } + cpuset_destroy(cset); +.Ed +.Sh COMPATIBILITY +Both functions are non-standard extensions. +.Sh ERRORS +Both functions may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The specified +.Fa set +was invalid. +.It Bq Er EPERM +The calling process lacks the appropriate privileges to perform +the operation. +.It Bq Er ESRCH +No thread could be found corresponding to the one specified by +.Fa thread . +.El +.Sh NOTES +There is an alternative processor sets interface, see +.Xr pset 3 . +However, thread affinity and processor sets are mutually exclusive, +hence mixing of these interfaces is prohibited. +.Sh SEE ALSO +.Xr cpuset 3 , +.Xr pset 3 , +.Xr pthread_getschedparam 3 , +.Xr pthread_setschedparam 3 , +.Xr sched 3 , +.Xr schedctl 8 diff --git a/lib/libpthread/arch/aarch64/pthread_md.h b/lib/libpthread/arch/aarch64/pthread_md.h new file mode 100644 index 000000000..d15f74e9e --- /dev/null +++ b/lib/libpthread/arch/aarch64/pthread_md.h @@ -0,0 +1,57 @@ +/* $NetBSD: pthread_md.h,v 1.1 2014/08/10 05:47:37 matt Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_AARCH64_MD_H +#define _LIB_PTHREAD_AARCH64_MD_H + +static inline uintptr_t +pthread__sp(void) +{ + uintptr_t ret; + + __asm __volatile("mov %0, sp" : "=r" (ret)); + + return ret; +} + +#define pthread__smt_pause() __asm __volatile("wfe") /* wfe */ +#define pthread__smt_wake() __asm __volatile("sev") /* sev */ + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_SPSR] = 0; + +#endif /* _LIB_PTHREAD_AARCH64_MD_H */ diff --git a/lib/libpthread/arch/alpha/pthread_md.S b/lib/libpthread/arch/alpha/pthread_md.S new file mode 100644 index 000000000..6ea5c5e54 --- /dev/null +++ b/lib/libpthread/arch/alpha/pthread_md.S @@ -0,0 +1,57 @@ +/* $NetBSD: pthread_md.S,v 1.1 2009/05/18 13:03:35 njoly Exp $ */ + +/*- + * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nick Hudson. + + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 + + .align 2 +LEAF(pthread__ras_simple_lock_init, 1) + stl zero, 0(a0) + nop + RET +END(pthread__ras_simple_lock_init) + + .align 2 +LEAF(pthread__ras_simple_lock_try, 1) + ldiq t0, 1 +pthread__lock_ras_start: .globl pthread__lock_ras_start + ldl v0, 0(a0) + stl t0, 0(a0) +pthread__lock_ras_end: .globl pthread__lock_ras_end + cmpeq v0, 0, v0 + RET +END(pthread__ras_simple_lock_try) + + .align 2 +LEAF(pthread__ras_simple_unlock, 1) + stl zero, 0(a0) + nop + RET +END(pthread__ras_simple_unlock) diff --git a/lib/libpthread/arch/alpha/pthread_md.h b/lib/libpthread/arch/alpha/pthread_md.h new file mode 100644 index 000000000..4ea370e1a --- /dev/null +++ b/lib/libpthread/arch/alpha/pthread_md.h @@ -0,0 +1,57 @@ +/* $NetBSD: pthread_md.h,v 1.7 2011/01/25 19:12:04 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_ALPHA_MD_H +#define _LIB_PTHREAD_ALPHA_MD_H + +#define PTHREAD__ASM_RASOPS + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("mov $30, %0" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + * 0x0008 is ALPHA_PSL_USERSET from arch/alpha/include/alpha_cpu.h + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_PS] = 0x0008; + +#endif /* _LIB_PTHREAD_ALPHA_MD_H */ diff --git a/lib/libpthread/arch/arm/pthread_md.h b/lib/libpthread/arch/arm/pthread_md.h new file mode 100644 index 000000000..153c39fad --- /dev/null +++ b/lib/libpthread/arch/arm/pthread_md.h @@ -0,0 +1,80 @@ +/* $NetBSD: pthread_md.h,v 1.9 2013/08/15 22:37:29 matt Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_ARM_MD_H +#define _LIB_PTHREAD_ARM_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm volatile("mov %0, sp" + : "=r" (ret)); + + return (ret); +} + +#if defined(__thumb__) && defined(_ARM_ARCH_6) +#define pthread__smt_pause() __asm __volatile(".inst.n 0xbf20") /* wfe */ +#define pthread__smt_wake() __asm __volatile(".inst.n 0xbf40") /* sev */ +#elif !defined(__thumb__) +#define pthread__smt_pause() __asm __volatile(".inst 0xe320f002") /* wfe */ +#define pthread__smt_wake() __asm __volatile(".inst 0xe320f004") /* sev */ +#else +#define pthread__smt_pause() +#define pthread__smt_wake() +#endif + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + */ +#ifdef __APCS_26__ +#define _INITCONTEXT_U_MD(ucp) \ +/* Set R15_MODE_USR in the PC */ \ + (ucp)->uc_mcontext.__gregs[_REG_PC] = \ + ((ucp)->uc_mcontext.__gregs[_REG_PC] & 0x3fffffc) | 0x0; +#else +/* Set CPSR to PSR_USE32_MODE (0x10) from arm/armreg.h */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_CPSR] = 0x10; +#endif + +#endif /* _LIB_PTHREAD_ARM_MD_H */ diff --git a/lib/libpthread/arch/hppa/pthread_md.S b/lib/libpthread/arch/hppa/pthread_md.S new file mode 100644 index 000000000..b388c0b22 --- /dev/null +++ b/lib/libpthread/arch/hppa/pthread_md.S @@ -0,0 +1,67 @@ +/* $NetBSD: pthread_md.S,v 1.1 2009/05/16 22:20:40 ad Exp $ */ + +/* + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Wayne Knowles + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 + +LEAF_ENTRY(pthread__ras_simple_lock_init) + ldi 1,%ret0 /* 1 == unlocked */ + stw %ret0,0(%arg0) + stw %ret0,4(%arg0) + stw %ret0,8(%arg0) + stw %ret0,12(%arg0) + bv,n %r0(%rp) +EXIT(pthread__ras_simple_lock_init) + + .global pthread__lock_ras_start + .global pthread__lock_ras_end + +LEAF_ENTRY(pthread__ras_simple_lock_try) + ldo 15(%arg0),%arg0 + depi 0,31,4,%arg0 + +pthread__lock_ras_start: + ldw 0(%arg0),%ret0 + stw %r0,0(%arg0) /* 0 == locked */ +pthread__lock_ras_end: + + comiclr,= 0,%ret0,%ret0 /* if locked return 0 */ + ldi 1,%ret0 /* else return 1 */ + bv,n %r0(%rp) +EXIT(pthread__ras_simple_lock_try) + + +LEAF_ENTRY(pthread__ras_simple_unlock) + ldo 15(%arg0),%arg0 + depi 0,31,4,%arg0 + ldi 1,%ret0 /* 1 == unlocked */ + bv %r0(%rp) + stw %ret0,0(%arg0) +EXIT(pthread__ras_simple_unlock) diff --git a/lib/libpthread/arch/hppa/pthread_md.h b/lib/libpthread/arch/hppa/pthread_md.h new file mode 100644 index 000000000..566a2599c --- /dev/null +++ b/lib/libpthread/arch/hppa/pthread_md.h @@ -0,0 +1,64 @@ +/* $NetBSD: pthread_md.h,v 1.8 2011/01/25 19:12:05 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_HPPA_MD_H +#define _LIB_PTHREAD_HPPA_MD_H + +#include + +#define PTHREAD__ASM_RASOPS + +static inline unsigned long +pthread__sp(void) +{ + register unsigned long sp __asm("r30"); + + return sp; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_PSW] = 0x4000f; + +/* + * Usable stack space below the ucontext_t. + */ +#define STACKSPACE (HPPA_FRAME_SIZE) + +/* Don't need additional memory barriers. */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +#endif /* !_LIB_PTHREAD_HPPA_MD_H */ diff --git a/lib/libpthread/arch/i386/pthread_md.h b/lib/libpthread/arch/i386/pthread_md.h new file mode 100644 index 000000000..1fd734586 --- /dev/null +++ b/lib/libpthread/arch/i386/pthread_md.h @@ -0,0 +1,94 @@ +/* $NetBSD: pthread_md.h,v 1.20 2012/03/02 23:19:47 joerg Exp $ */ + +/*- + * Copyright (c) 2001, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams, and by Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_I386_MD_H +#define _LIB_PTHREAD_I386_MD_H + +#include +#include + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + __asm("movl %%esp, %0" : "=g" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_UESP]) + +static inline void +_initcontext_u_md(ucontext_t *ucp) +{ + __asm ("pushfl; popl %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_EFL])); + __asm ("pushl %%cs; popl %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_CS])); + __asm ("movl %%ds, %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_DS])); + __asm ("movl %%es, %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_ES])); + __asm ("movl %%fs, %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_FS])); + __asm ("movl %%gs, %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_GS])); + __asm ("movl %%ss, %0" : "=a" (ucp->uc_mcontext.__gregs[_REG_SS])); +} + +#define _INITCONTEXT_U_MD(ucp) _initcontext_u_md(ucp); + +#define pthread__smt_pause() __asm __volatile("rep; nop" ::: "memory") + +/* Don't need additional memory barriers. */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +static inline void * +_atomic_cas_ptr(volatile void *ptr, void *old, void *new) +{ + volatile uintptr_t *cast = ptr; + void *ret; + + __asm __volatile ("lock; cmpxchgl %2, %1" + : "=a" (ret), "=m" (*cast) + : "r" (new), "m" (*cast), "0" (old)); + + return ret; +} + +static inline void * +_atomic_cas_ptr_ni(volatile void *ptr, void *old, void *new) +{ + volatile uintptr_t *cast = ptr; + void *ret; + + __asm __volatile ("cmpxchgl %2, %1" + : "=a" (ret), "=m" (*cast) + : "r" (new), "m" (*cast), "0" (old)); + + return ret; +} + +#endif /* _LIB_PTHREAD_I386_MD_H */ diff --git a/lib/libpthread/arch/ia64/pthread_md.h b/lib/libpthread/arch/ia64/pthread_md.h new file mode 100644 index 000000000..056e68bef --- /dev/null +++ b/lib/libpthread/arch/ia64/pthread_md.h @@ -0,0 +1,45 @@ +/* $NetBSD: pthread_md.h,v 1.1 2015/04/17 13:14:19 martin Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_IA64_MD_H +#define _LIB_PTHREAD_IA64_MD_H + +// #define PTHREAD__ASM_RASOPS + +static inline unsigned long +pthread__sp(void) +{ + return 0; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +#endif /* _LIB_PTHREAD_IA64_MD_H */ diff --git a/lib/libpthread/arch/m68k/pthread_md.h b/lib/libpthread/arch/m68k/pthread_md.h new file mode 100644 index 000000000..2ba7566a1 --- /dev/null +++ b/lib/libpthread/arch/m68k/pthread_md.h @@ -0,0 +1,49 @@ +/* $NetBSD: pthread_md.h,v 1.8 2011/01/25 19:12:05 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_M68K_MD_H +#define _LIB_PTHREAD_M68K_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + __asm("movl %%sp, %0" : "=g" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_A7]) + +/* m68k will not go SMP */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +#endif /* _LIB_PTHREAD_M68K_MD_H */ diff --git a/lib/libpthread/arch/mips/pthread_md.h b/lib/libpthread/arch/mips/pthread_md.h new file mode 100644 index 000000000..143567ea0 --- /dev/null +++ b/lib/libpthread/arch/mips/pthread_md.h @@ -0,0 +1,47 @@ +/* $NetBSD: pthread_md.h,v 1.9 2011/01/25 19:12:05 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_MIPS_MD_H +#define _LIB_PTHREAD_MIPS_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("move %0, $sp" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +#endif /* !_LIB_PTHREAD_MIPS_MD_H */ diff --git a/lib/libpthread/arch/or1k/pthread_md.h b/lib/libpthread/arch/or1k/pthread_md.h new file mode 100644 index 000000000..f99616d9b --- /dev/null +++ b/lib/libpthread/arch/or1k/pthread_md.h @@ -0,0 +1,47 @@ +/* $NetBSD: pthread_md.h,v 1.1 2014/09/03 19:34:26 matt Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_OR1K_MD_H +#define _LIB_PTHREAD_OR1K_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("l.ori %0, r0, 0" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[1]) + +#endif /* _LIB_PTHREAD_OR1K_MD_H */ diff --git a/lib/libpthread/arch/powerpc/pthread_md.h b/lib/libpthread/arch/powerpc/pthread_md.h new file mode 100644 index 000000000..7bccf588e --- /dev/null +++ b/lib/libpthread/arch/powerpc/pthread_md.h @@ -0,0 +1,61 @@ +/* $NetBSD: pthread_md.h,v 1.7 2011/01/25 19:12:05 christos Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Allen Briggs for Wasabi Systems, Inc. + * + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_POWERPC_MD_H +#define _LIB_PTHREAD_POWERPC_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("mr %0,1" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[1]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + * 0xd032 is PSL_USERSET from arch/powerpc/include/psl.h + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_MSR] = 0xd032; + +#endif /* _LIB_PTHREAD_POWERPC_MD_H */ diff --git a/lib/libpthread/arch/riscv/pthread_md.h b/lib/libpthread/arch/riscv/pthread_md.h new file mode 100644 index 000000000..de99c52ea --- /dev/null +++ b/lib/libpthread/arch/riscv/pthread_md.h @@ -0,0 +1,47 @@ +/* $NetBSD: pthread_md.h,v 1.2 2015/03/31 01:36:27 matt Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_RISCV_MD_H +#define _LIB_PTHREAD_RISCV_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("move\t%0, sp" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +#endif /* _LIB_PTHREAD_RISCV_MD_H */ diff --git a/lib/libpthread/arch/sh3/pthread_md.h b/lib/libpthread/arch/sh3/pthread_md.h new file mode 100644 index 000000000..525b66d9e --- /dev/null +++ b/lib/libpthread/arch/sh3/pthread_md.h @@ -0,0 +1,62 @@ +/* $NetBSD: pthread_md.h,v 1.8 2011/01/25 19:12:06 christos Exp $ */ + +/* + * Copyright 2003 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Steve C. Woodford for Wasabi Systems, Inc. + * + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_SH3_MD_H +#define _LIB_PTHREAD_SH3_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + __asm("mov r15, %0" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_R15]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_SR] = 0; + +/* sh3 will not go SMP */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +#endif /* _LIB_PTHREAD_SH3_MD_H */ diff --git a/lib/libpthread/arch/sparc/pthread_md.h b/lib/libpthread/arch/sparc/pthread_md.h new file mode 100644 index 000000000..85d61bc07 --- /dev/null +++ b/lib/libpthread/arch/sparc/pthread_md.h @@ -0,0 +1,50 @@ +/* $NetBSD: pthread_md.h,v 1.8 2011/01/25 19:12:06 christos Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_SPARC_MD_H +#define _LIB_PTHREAD_SPARC_MD_H + +/* + * pthread__sp used for identifying thread + */ +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("mov %%sp, %0" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_O6]) + +/* Don't need additional memory barriers. */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +#endif /* _LIB_PTHREAD_SPARC_MD_H */ diff --git a/lib/libpthread/arch/sparc64/pthread_md.h b/lib/libpthread/arch/sparc64/pthread_md.h new file mode 100644 index 000000000..4cf88edb7 --- /dev/null +++ b/lib/libpthread/arch/sparc64/pthread_md.h @@ -0,0 +1,47 @@ +/* $NetBSD: pthread_md.h,v 1.7 2011/01/25 19:12:06 christos Exp $ */ + +/*- + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_SPARC64_MD_H +#define _LIB_PTHREAD_SPARC64_MD_H + +/* + * pthread__sp used for identifying thread + */ +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("mov %%sp, %0" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_O6]) + +#endif /* _LIB_PTHREAD_SPARC64_MD_H */ diff --git a/lib/libpthread/arch/vax/pthread_md.h b/lib/libpthread/arch/vax/pthread_md.h new file mode 100644 index 000000000..cd1f814be --- /dev/null +++ b/lib/libpthread/arch/vax/pthread_md.h @@ -0,0 +1,58 @@ +/* $NetBSD: pthread_md.h,v 1.8 2011/01/25 19:12:06 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_VAX_MD_H +#define _LIB_PTHREAD_VAX_MD_H + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + + __asm("movl %%sp,%0" : "=r" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_SP]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + * 0x03c00000 is PSL_U|PSL_PREVU from arch/vax/include/psl.h + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_PSL] = 0x03c00000; + +/* Don't need additional memory barriers. */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +#endif /* _LIB_PTHREAD_VAX_MD_H */ diff --git a/lib/libpthread/arch/x86_64/pthread_md.h b/lib/libpthread/arch/x86_64/pthread_md.h new file mode 100644 index 000000000..4b5321883 --- /dev/null +++ b/lib/libpthread/arch/x86_64/pthread_md.h @@ -0,0 +1,97 @@ +/* $NetBSD: pthread_md.h,v 1.12 2011/01/25 19:12:06 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + * + * Adapted for x86_64 by fvdl@NetBSD.org + */ + +#ifndef _LIB_PTHREAD_X86_64_MD_H +#define _LIB_PTHREAD_X86_64_MD_H + +#include + +static inline unsigned long +pthread__sp(void) +{ + unsigned long ret; + __asm("movq %%rsp, %0" : "=g" (ret)); + + return ret; +} + +#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_URSP]) + +/* + * Set initial, sane values for registers whose values aren't just + * "don't care". + * 0x23 is GSEL(GUDATA_SEL, SEL_UPL), and + * 0x1b is GSEL(GUCODE_SEL, SEL_UPL). + * 0x202 is PSL_USERSET. + */ +#define _INITCONTEXT_U_MD(ucp) \ + (ucp)->uc_mcontext.__gregs[_REG_GS] = 0x23, \ + (ucp)->uc_mcontext.__gregs[_REG_FS] = 0x23, \ + (ucp)->uc_mcontext.__gregs[_REG_ES] = 0x23, \ + (ucp)->uc_mcontext.__gregs[_REG_DS] = 0x23, \ + (ucp)->uc_mcontext.__gregs[_REG_CS] = 0x1b, \ + (ucp)->uc_mcontext.__gregs[_REG_SS] = 0x23, \ + (ucp)->uc_mcontext.__gregs[_REG_RFL] = 0x202; + +#define pthread__smt_pause() __asm __volatile("rep; nop" ::: "memory") + +/* Don't need additional memory barriers. */ +#define PTHREAD__ATOMIC_IS_MEMBAR + +static inline void * +_atomic_cas_ptr(volatile void *ptr, void *old, void *new) +{ + volatile uintptr_t *cast = ptr; + void *ret; + + __asm __volatile ("lock; cmpxchgq %2, %1" + : "=a" (ret), "=m" (*cast) + : "r" (new), "m" (*cast), "0" (old)); + + return ret; +} + +static inline void * +_atomic_cas_ptr_ni(volatile void *ptr, void *old, void *new) +{ + volatile uintptr_t *cast = ptr; + void *ret; + + __asm __volatile ("cmpxchgq %2, %1" + : "=a" (ret), "=m" (*cast) + : "r" (new), "m" (*cast), "0" (old)); + + return ret; +} + +#endif /* _LIB_PTHREAD_X86_64_MD_H */ diff --git a/lib/libpthread/pthread.3 b/lib/libpthread/pthread.3 new file mode 100644 index 000000000..19afc808a --- /dev/null +++ b/lib/libpthread/pthread.3 @@ -0,0 +1,178 @@ +.\" $NetBSD: pthread.3,v 1.14 2010/05/16 12:23:32 jruoho Exp $ +.\" +.\" Copyright (c) 2003, 2007, 2009 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Hubert Feyrer and Thomas Klausner . +.\" +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd May 16, 2010 +.Dt PTHREAD 3 +.Os +.Sh NAME +.Nm pthread +.Nd POSIX Threads Library +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Pp +.Nm cc +.Op Ar flags +.Ar files +.Fl lpthread +.Op Ar libraries +.Sh DESCRIPTION +The +.Nm +library provides an implementation of the standard +.Tn POSIX +threads library. +.Pp +The +.Nx +implementation is based on 1:1 thread model, therefore each +.Nm +has a kernel thread, called a light-weight process (LWP). +.Pp +Note that the system private thread interfaces upon which the +.Nm +library is built are subject to change without notice. +In order to remain compatible with future +.Nx +releases, programs must be linked against the dynamic version of the +thread library. +Statically linked programs using the +.Tn POSIX +threads framework may not work when run on a future version of the system. +.Sh FUNCTIONS +The following functions comprise the core of the +.Nm +library: +.Bl -column -offset indent "pthread_barrier_destroy(3)" "XXX" +.It Sy Function Ta Sy Description +.It Xr pthread_attr 3 Ta thread attribute operations +.It Xr pthread_barrier_destroy 3 Ta destroy a barrier +.It Xr pthread_barrier_init 3 Ta create a barrier +.It Xr pthread_barrier_wait 3 Ta wait for a barrier +.It Xr pthread_barrierattr 3 Ta barrier attribute operations +.It Xr pthread_cancel 3 Ta cancel the execution of a thread +.It Xr pthread_cleanup_push 3 Ta add or remove cleanup functions +.It Xr pthread_cond_broadcast 3 Ta unblock one or more threads +.It Xr pthread_cond_destroy 3 Ta destroy a condition variable +.It Xr pthread_cond_init 3 Ta create a condition variable +.It Xr pthread_cond_wait 3 Ta wait for a condition variable +.It Xr pthread_condattr 3 Ta condition attribute operations +.It Xr pthread_create 3 Ta create a new thread +.It Xr pthread_detach 3 Ta detach a thread +.It Xr pthread_equal 3 Ta compare thread identifiers +.It Xr pthread_exit 3 Ta terminate the calling thread +.It Xr pthread_getspecific 3 Ta get a thread-specific data value +.It Xr pthread_join 3 Ta wait for thread termination +.It Xr pthread_key_create 3 Ta thread-specific data key creation +.It Xr pthread_key_delete 3 Ta delete a thread-specific data key +.It Xr pthread_kill 3 Ta send a signal to a specific thread +.It Xr pthread_mutex_destroy 3 Ta free a mutex +.It Xr pthread_mutex_init 3 Ta create a mutex +.It Xr pthread_mutex_lock 3 Ta acquire a lock on a mutex +.It Xr pthread_mutex_unlock 3 Ta unlock a mutex +.It Xr pthread_mutexattr 3 Ta mutex attribute operations +.It Xr pthread_once 3 Ta dynamic package initialization +.It Xr pthread_rwlock_destroy 3 Ta destroy a read/write lock +.It Xr pthread_rwlock_init 3 Ta initialize a read/write lock +.It Xr pthread_rwlock_rdlock 3 Ta acquire a read/write lock for reading +.It Xr pthread_rwlock_unlock 3 Ta release a read/write lock +.It Xr pthread_rwlock_wrlock 3 Ta acquire a read/write lock for writing +.It Xr pthread_rwlockattr 3 Ta read/write lock attribute operations +.It Xr pthread_schedparam 3 Ta thread scheduling manipulation +.It Xr pthread_self 3 Ta get the ID of the calling thread +.It Xr pthread_setspecific 3 Ta get a thread-specific data value +.It Xr pthread_sigmask 3 Ta manipulate a thread's signal mask +.It Xr pthread_spin_destroy 3 Ta destroy a spin lock +.It Xr pthread_spin_init 3 Ta initialize a spin lock +.It Xr pthread_spin_lock 3 Ta acquire a spin lock +.It Xr pthread_spin_unlock 3 Ta release a spin lock +.It Xr pthread_testcancel 3 Ta set cancelability state +.El +.Sh ENVIRONMENT +The following environment variables affect the behavior of the library: +.Bl -tag -width "XXX" +.It Ev PTHREAD_DIAGASSERT +Possible values are any combinations of: +.Pp +.Bl -tag -width "X " -offset 1n -compact +.It Em A +Report errors to application by error return, but do not abort. +.It Em a +Abort on errors, creating a core dump for further debugging. +.It Em E +Do not log errors to stdout. +.It Em e +Log errors to stdout. +.It Em L +Do not log errors via +.Xr syslogd 8 . +.It Em l +Log errors via +.Xr syslogd 8 . +.El +.Pp +If not set in the environment, the +.Nm +library behaves as if +.Em AEL +has been specified. +.It Ev PTHREAD_STACKSIZE +Integer value giving the stack size in kilobytes. +This allows to set a smaller stack size than the default stack size. +The default stack size is the current limit on the stack size as +set with the shell's command to change limits +.Ic ( limit +for +.Xr csh 1 , +or +.Ic ulimit +for +.Xr sh 1 ) . +.El +.Sh SEE ALSO +.Rs +.%A David R. Butenhof +.%T Programming with POSIX(R) Threads +.%D 1997 +.%I Addison-Wesley +.Re +.Sh STANDARDS +The +.Nm +library conforms to +.St -p1003.1-2001 . +.Sh CAVEATS +Due to limitations in the current pthread implementation, +.Xr makecontext 3 +and +.Xr sigaltstack 2 +should not be used in programs which link against the +.Nm +library (whether threads are used or not). diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c new file mode 100644 index 000000000..f5b1e4044 --- /dev/null +++ b/lib/libpthread/pthread.c @@ -0,0 +1,1396 @@ +/* $NetBSD: pthread.c,v 1.147 2015/05/29 16:05:13 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread.c,v 1.147 2015/05/29 16:05:13 christos Exp $"); + +#define __EXPOSE_STACK 1 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "pthread_makelwp.h" +#include "reentrant.h" + +pthread_rwlock_t pthread__alltree_lock = PTHREAD_RWLOCK_INITIALIZER; +static rb_tree_t pthread__alltree; + +static signed int pthread__cmp(void *, const void *, const void *); + +static const rb_tree_ops_t pthread__alltree_ops = { + .rbto_compare_nodes = pthread__cmp, + .rbto_compare_key = pthread__cmp, + .rbto_node_offset = offsetof(struct __pthread_st, pt_alltree), + .rbto_context = NULL +}; + +static void pthread__create_tramp(void *); +static void pthread__initthread(pthread_t); +static void pthread__scrubthread(pthread_t, char *, int); +static void pthread__initmain(pthread_t *); +static void pthread__fork_callback(void); +static void pthread__reap(pthread_t); +static void pthread__child_callback(void); +static void pthread__start(void); + +void pthread__init(void); + +int pthread__started; +int __uselibcstub = 1; +pthread_mutex_t pthread__deadqueue_lock = PTHREAD_MUTEX_INITIALIZER; +pthread_queue_t pthread__deadqueue; +pthread_queue_t pthread__allqueue; + +static pthread_attr_t pthread_default_attr; +static lwpctl_t pthread__dummy_lwpctl = { .lc_curcpu = LWPCTL_CPU_NONE }; + +enum { + DIAGASSERT_ABORT = 1<<0, + DIAGASSERT_STDERR = 1<<1, + DIAGASSERT_SYSLOG = 1<<2 +}; + +static int pthread__diagassert; + +int pthread__concurrency; +int pthread__nspins; +int pthread__unpark_max = PTHREAD__UNPARK_MAX; +int pthread__dbg; /* set by libpthread_dbg if active */ + +/* + * We have to initialize the pthread_stack* variables here because + * mutexes are used before pthread_init() and thus pthread__initmain() + * are called. Since mutexes only save the stack pointer and not a + * pointer to the thread data, it is safe to change the mapping from + * stack pointer to thread data afterwards. + */ +size_t pthread__stacksize; +size_t pthread__pagesize; +static struct __pthread_st *pthread__main; +static size_t __pthread_st_size; + +int _sys___sigprocmask14(int, const sigset_t *, sigset_t *); + +__strong_alias(__libc_thr_self,pthread_self) +__strong_alias(__libc_thr_create,pthread_create) +__strong_alias(__libc_thr_exit,pthread_exit) +__strong_alias(__libc_thr_errno,pthread__errno) +__strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate) +__strong_alias(__libc_thr_equal,pthread_equal) +__strong_alias(__libc_thr_init,pthread__init) + +/* + * Static library kludge. Place a reference to a symbol any library + * file which does not already have a reference here. + */ +extern int pthread__cancel_stub_binder; + +void *pthread__static_lib_binder[] = { + &pthread__cancel_stub_binder, + pthread_cond_init, + pthread_mutex_init, + pthread_rwlock_init, + pthread_barrier_init, + pthread_key_create, + pthread_setspecific, +}; + +#define NHASHLOCK 64 + +static union hashlock { + pthread_mutex_t mutex; + char pad[64]; +} hashlocks[NHASHLOCK] __aligned(64); + +/* + * This needs to be started by the library loading code, before main() + * gets to run, for various things that use the state of the initial thread + * to work properly (thread-specific data is an application-visible example; + * spinlock counts for mutexes is an internal example). + */ +void +pthread__init(void) +{ + pthread_t first; + char *p; + int i; + extern int __isthreaded; + + /* + * Allocate pthread_keys descriptors before + * reseting __uselibcstub because otherwise + * malloc() will call pthread_keys_create() + * while pthread_keys descriptors are not + * yet allocated. + */ + pthread__main = pthread_tsd_init(&__pthread_st_size); + if (pthread__main == NULL) + err(EXIT_FAILURE, "Cannot allocate pthread storage"); + + __uselibcstub = 0; + + pthread__pagesize = (size_t)sysconf(_SC_PAGESIZE); + pthread__concurrency = (int)sysconf(_SC_NPROCESSORS_CONF); + + /* Initialize locks first; they're needed elsewhere. */ + pthread__lockprim_init(); + for (i = 0; i < NHASHLOCK; i++) { + pthread_mutex_init(&hashlocks[i].mutex, NULL); + } + + /* Fetch parameters. */ + i = (int)_lwp_unpark_all(NULL, 0, NULL); + if (i == -1) + err(EXIT_FAILURE, "_lwp_unpark_all"); + if (i < pthread__unpark_max) + pthread__unpark_max = i; + + /* Basic data structure setup */ + pthread_attr_init(&pthread_default_attr); + PTQ_INIT(&pthread__allqueue); + PTQ_INIT(&pthread__deadqueue); + + rb_tree_init(&pthread__alltree, &pthread__alltree_ops); + + /* Create the thread structure corresponding to main() */ + pthread__initmain(&first); + pthread__initthread(first); + pthread__scrubthread(first, NULL, 0); + + first->pt_lid = _lwp_self(); + PTQ_INSERT_HEAD(&pthread__allqueue, first, pt_allq); + (void)rb_tree_insert_node(&pthread__alltree, first); + + if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &first->pt_lwpctl) != 0) { + err(EXIT_FAILURE, "_lwp_ctl"); + } + + /* Start subsystems */ + PTHREAD_MD_INIT + + for (p = pthread__getenv("PTHREAD_DIAGASSERT"); p && *p; p++) { + switch (*p) { + case 'a': + pthread__diagassert |= DIAGASSERT_ABORT; + break; + case 'A': + pthread__diagassert &= ~DIAGASSERT_ABORT; + break; + case 'e': + pthread__diagassert |= DIAGASSERT_STDERR; + break; + case 'E': + pthread__diagassert &= ~DIAGASSERT_STDERR; + break; + case 'l': + pthread__diagassert |= DIAGASSERT_SYSLOG; + break; + case 'L': + pthread__diagassert &= ~DIAGASSERT_SYSLOG; + break; + } + } + + /* Tell libc that we're here and it should role-play accordingly. */ + pthread_atfork(NULL, NULL, pthread__fork_callback); + __isthreaded = 1; +} + +static void +pthread__fork_callback(void) +{ + struct __pthread_st *self = pthread__self(); + + /* lwpctl state is not copied across fork. */ + if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &self->pt_lwpctl)) { + err(EXIT_FAILURE, "_lwp_ctl"); + } + self->pt_lid = _lwp_self(); +} + +static void +pthread__child_callback(void) +{ + + /* + * Clean up data structures that a forked child process might + * trip over. Note that if threads have been created (causing + * this handler to be registered) the standards say that the + * child will trigger undefined behavior if it makes any + * pthread_* calls (or any other calls that aren't + * async-signal-safe), so we don't really have to clean up + * much. Anything that permits some pthread_* calls to work is + * merely being polite. + */ + pthread__started = 0; +} + +static void +pthread__start(void) +{ + + /* + * Per-process timers are cleared by fork(); despite the + * various restrictions on fork() and threads, it's legal to + * fork() before creating any threads. + */ + pthread_atfork(NULL, NULL, pthread__child_callback); +} + + +/* General-purpose thread data structure sanitization. */ +/* ARGSUSED */ +static void +pthread__initthread(pthread_t t) +{ + + t->pt_self = t; + t->pt_magic = PT_MAGIC; + t->pt_willpark = 0; + t->pt_unpark = 0; + t->pt_nwaiters = 0; + t->pt_sleepobj = NULL; + t->pt_signalled = 0; + t->pt_havespecific = 0; + t->pt_early = NULL; + t->pt_lwpctl = &pthread__dummy_lwpctl; + t->pt_blocking = 0; + t->pt_droplock = NULL; + + memcpy(&t->pt_lockops, pthread__lock_ops, sizeof(t->pt_lockops)); + pthread_mutex_init(&t->pt_lock, NULL); + PTQ_INIT(&t->pt_cleanup_stack); + pthread_cond_init(&t->pt_joiners, NULL); +} + +static void +pthread__scrubthread(pthread_t t, char *name, int flags) +{ + + t->pt_state = PT_STATE_RUNNING; + t->pt_exitval = NULL; + t->pt_flags = flags; + t->pt_cancel = 0; + t->pt_errno = 0; + t->pt_name = name; + t->pt_lid = 0; +} + +static int +pthread__getstack(pthread_t newthread, const pthread_attr_t *attr) +{ + void *stackbase, *stackbase2, *redzone; + size_t stacksize, guardsize; + bool allocated; + + if (attr != NULL) { + pthread_attr_getstack(attr, &stackbase, &stacksize); + } else { + stackbase = NULL; + stacksize = 0; + } + if (stacksize == 0) + stacksize = pthread__stacksize; + + if (newthread->pt_stack_allocated) { + if (stackbase == NULL && + newthread->pt_stack.ss_size == stacksize) + return 0; + stackbase2 = newthread->pt_stack.ss_sp; +#ifndef __MACHINE_STACK_GROWS_UP + stackbase2 = (char *)stackbase2 - newthread->pt_guardsize; +#endif + munmap(stackbase2, + newthread->pt_stack.ss_size + newthread->pt_guardsize); + newthread->pt_stack.ss_sp = NULL; + newthread->pt_stack.ss_size = 0; + newthread->pt_guardsize = 0; + newthread->pt_stack_allocated = false; + } + + newthread->pt_stack_allocated = false; + + if (stackbase == NULL) { + stacksize = ((stacksize - 1) | (pthread__pagesize - 1)) + 1; + guardsize = pthread__pagesize; + stackbase = mmap(NULL, stacksize + guardsize, + PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, (off_t)0); + if (stackbase == MAP_FAILED) + return ENOMEM; + allocated = true; + } else { + guardsize = 0; + allocated = false; + } +#ifdef __MACHINE_STACK_GROWS_UP + redzone = (char *)stackbase + stacksize; + stackbase2 = (char *)stackbase; +#else + redzone = (char *)stackbase; + stackbase2 = (char *)stackbase + guardsize; +#endif + if (allocated && guardsize && + mprotect(redzone, guardsize, PROT_NONE) == -1) { + munmap(stackbase, stacksize + guardsize); + return EPERM; + } + newthread->pt_stack.ss_size = stacksize; + newthread->pt_stack.ss_sp = stackbase2; + newthread->pt_guardsize = guardsize; + newthread->pt_stack_allocated = allocated; + return 0; +} + +int +pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*startfunc)(void *), void *arg) +{ + pthread_t newthread; + pthread_attr_t nattr; + struct pthread_attr_private *p; + char * volatile name; + unsigned long flag; + void *private_area; + int ret; + + if (__predict_false(__uselibcstub)) { + pthread__errorfunc(__FILE__, __LINE__, __func__, + "pthread_create() requires linking with -lpthread"); + return __libc_thr_create_stub(thread, attr, startfunc, arg); + } + + /* + * It's okay to check this without a lock because there can + * only be one thread before it becomes true. + */ + if (pthread__started == 0) { + pthread__start(); + pthread__started = 1; + } + + if (attr == NULL) + nattr = pthread_default_attr; + else if (attr->pta_magic == PT_ATTR_MAGIC) + nattr = *attr; + else + return EINVAL; + + /* Fetch misc. attributes from the attr structure. */ + name = NULL; + if ((p = nattr.pta_private) != NULL) + if (p->ptap_name[0] != '\0') + if ((name = strdup(p->ptap_name)) == NULL) + return ENOMEM; + + newthread = NULL; + + /* + * Try to reclaim a dead thread. + */ + if (!PTQ_EMPTY(&pthread__deadqueue)) { + pthread_mutex_lock(&pthread__deadqueue_lock); + PTQ_FOREACH(newthread, &pthread__deadqueue, pt_deadq) { + /* Still running? */ + if (newthread->pt_lwpctl->lc_curcpu == + LWPCTL_CPU_EXITED || + (_lwp_kill(newthread->pt_lid, 0) == -1 && + errno == ESRCH)) + break; + } + if (newthread) + PTQ_REMOVE(&pthread__deadqueue, newthread, pt_deadq); + pthread_mutex_unlock(&pthread__deadqueue_lock); +#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) + if (newthread && newthread->pt_tls) { + _rtld_tls_free(newthread->pt_tls); + newthread->pt_tls = NULL; + } +#endif + } + + /* + * If necessary set up a stack, allocate space for a pthread_st, + * and initialize it. + */ + if (newthread == NULL) { + newthread = calloc(1, __pthread_st_size); + if (newthread == NULL) { + free(name); + return ENOMEM; + } + newthread->pt_stack_allocated = false; + + if (pthread__getstack(newthread, attr)) { + free(newthread); + free(name); + return ENOMEM; + } + +#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) + newthread->pt_tls = NULL; +#endif + + /* Add to list of all threads. */ + pthread_rwlock_wrlock(&pthread__alltree_lock); + PTQ_INSERT_TAIL(&pthread__allqueue, newthread, pt_allq); + (void)rb_tree_insert_node(&pthread__alltree, newthread); + pthread_rwlock_unlock(&pthread__alltree_lock); + + /* Will be reset by the thread upon exit. */ + pthread__initthread(newthread); + } else { + if (pthread__getstack(newthread, attr)) { + pthread_mutex_lock(&pthread__deadqueue_lock); + PTQ_INSERT_TAIL(&pthread__deadqueue, newthread, pt_deadq); + pthread_mutex_unlock(&pthread__deadqueue_lock); + return ENOMEM; + } + } + + /* + * Create the new LWP. + */ + pthread__scrubthread(newthread, name, nattr.pta_flags); + newthread->pt_func = startfunc; + newthread->pt_arg = arg; +#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) + private_area = newthread->pt_tls = _rtld_tls_allocate(); + newthread->pt_tls->tcb_pthread = newthread; +#else + private_area = newthread; +#endif + + flag = LWP_DETACHED; + if ((newthread->pt_flags & PT_FLAG_SUSPENDED) != 0 || + (nattr.pta_flags & PT_FLAG_EXPLICIT_SCHED) != 0) + flag |= LWP_SUSPENDED; + + ret = pthread__makelwp(pthread__create_tramp, newthread, private_area, + newthread->pt_stack.ss_sp, newthread->pt_stack.ss_size, + flag, &newthread->pt_lid); + if (ret != 0) { + ret = errno; + pthread_mutex_lock(&newthread->pt_lock); + /* Will unlock and free name. */ + pthread__reap(newthread); + return ret; + } + + if ((nattr.pta_flags & PT_FLAG_EXPLICIT_SCHED) != 0) { + if (p != NULL) { + (void)pthread_setschedparam(newthread, p->ptap_policy, + &p->ptap_sp); + } + if ((newthread->pt_flags & PT_FLAG_SUSPENDED) == 0) { + (void)_lwp_continue(newthread->pt_lid); + } + } + + *thread = newthread; + + return 0; +} + + +__dead static void +pthread__create_tramp(void *cookie) +{ + pthread_t self; + void *retval; + + self = cookie; + + /* + * Throw away some stack in a feeble attempt to reduce cache + * thrash. May help for SMT processors. XXX We should not + * be allocating stacks on fixed 2MB boundaries. Needs a + * thread register or decent thread local storage. + * + * Note that we may race with the kernel in _lwp_create(), + * and so pt_lid can be unset at this point, but we don't + * care. + */ + (void)alloca(((unsigned)self->pt_lid & 7) << 8); + + if (self->pt_name != NULL) { + pthread_mutex_lock(&self->pt_lock); + if (self->pt_name != NULL) + (void)_lwp_setname(0, self->pt_name); + pthread_mutex_unlock(&self->pt_lock); + } + + if (_lwp_ctl(LWPCTL_FEATURE_CURCPU, &self->pt_lwpctl)) { + err(EXIT_FAILURE, "_lwp_ctl"); + } + + retval = (*self->pt_func)(self->pt_arg); + + pthread_exit(retval); + + /*NOTREACHED*/ + pthread__abort(); +} + +int +pthread_suspend_np(pthread_t thread) +{ + pthread_t self; + + self = pthread__self(); + if (self == thread) { + return EDEADLK; + } + if (pthread__find(thread) != 0) + return ESRCH; + if (_lwp_suspend(thread->pt_lid) == 0) + return 0; + return errno; +} + +int +pthread_resume_np(pthread_t thread) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + if (_lwp_continue(thread->pt_lid) == 0) + return 0; + return errno; +} + +void +pthread_exit(void *retval) +{ + pthread_t self; + struct pt_clean_t *cleanup; + char *name; + + if (__predict_false(__uselibcstub)) { + __libc_thr_exit_stub(retval); + goto out; + } + + self = pthread__self(); + + /* Disable cancellability. */ + pthread_mutex_lock(&self->pt_lock); + self->pt_flags |= PT_FLAG_CS_DISABLED; + self->pt_cancel = 0; + + /* Call any cancellation cleanup handlers */ + if (!PTQ_EMPTY(&self->pt_cleanup_stack)) { + pthread_mutex_unlock(&self->pt_lock); + while (!PTQ_EMPTY(&self->pt_cleanup_stack)) { + cleanup = PTQ_FIRST(&self->pt_cleanup_stack); + PTQ_REMOVE(&self->pt_cleanup_stack, cleanup, ptc_next); + (*cleanup->ptc_cleanup)(cleanup->ptc_arg); + } + pthread_mutex_lock(&self->pt_lock); + } + + /* Perform cleanup of thread-specific data */ + pthread__destroy_tsd(self); + + /* Signal our exit. */ + self->pt_exitval = retval; + if (self->pt_flags & PT_FLAG_DETACHED) { + self->pt_state = PT_STATE_DEAD; + name = self->pt_name; + self->pt_name = NULL; + pthread_mutex_unlock(&self->pt_lock); + if (name != NULL) + free(name); + pthread_mutex_lock(&pthread__deadqueue_lock); + PTQ_INSERT_TAIL(&pthread__deadqueue, self, pt_deadq); + pthread_mutex_unlock(&pthread__deadqueue_lock); + _lwp_exit(); + } else { + self->pt_state = PT_STATE_ZOMBIE; + pthread_cond_broadcast(&self->pt_joiners); + pthread_mutex_unlock(&self->pt_lock); + /* Note: name will be freed by the joiner. */ + _lwp_exit(); + } + +out: + /*NOTREACHED*/ + pthread__abort(); + exit(1); +} + + +int +pthread_join(pthread_t thread, void **valptr) +{ + pthread_t self; + int error; + + self = pthread__self(); + + if (pthread__find(thread) != 0) + return ESRCH; + + if (thread->pt_magic != PT_MAGIC) + return EINVAL; + + if (thread == self) + return EDEADLK; + + self->pt_droplock = &thread->pt_lock; + pthread_mutex_lock(&thread->pt_lock); + for (;;) { + if (thread->pt_state == PT_STATE_ZOMBIE) + break; + if (thread->pt_state == PT_STATE_DEAD) { + pthread_mutex_unlock(&thread->pt_lock); + self->pt_droplock = NULL; + return ESRCH; + } + if ((thread->pt_flags & PT_FLAG_DETACHED) != 0) { + pthread_mutex_unlock(&thread->pt_lock); + self->pt_droplock = NULL; + return EINVAL; + } + error = pthread_cond_wait(&thread->pt_joiners, + &thread->pt_lock); + if (error != 0) { + pthread__errorfunc(__FILE__, __LINE__, + __func__, "unexpected return from cond_wait()"); + } + + } + pthread__testcancel(self); + if (valptr != NULL) + *valptr = thread->pt_exitval; + /* pthread__reap() will drop the lock. */ + pthread__reap(thread); + self->pt_droplock = NULL; + + return 0; +} + +static void +pthread__reap(pthread_t thread) +{ + char *name; + + name = thread->pt_name; + thread->pt_name = NULL; + thread->pt_state = PT_STATE_DEAD; + pthread_mutex_unlock(&thread->pt_lock); + + pthread_mutex_lock(&pthread__deadqueue_lock); + PTQ_INSERT_HEAD(&pthread__deadqueue, thread, pt_deadq); + pthread_mutex_unlock(&pthread__deadqueue_lock); + + if (name != NULL) + free(name); +} + +int +pthread_equal(pthread_t t1, pthread_t t2) +{ + if (__predict_false(__uselibcstub)) + return __libc_thr_equal_stub(t1, t2); + + /* Nothing special here. */ + return (t1 == t2); +} + + +int +pthread_detach(pthread_t thread) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + + if (thread->pt_magic != PT_MAGIC) + return EINVAL; + + pthread_mutex_lock(&thread->pt_lock); + thread->pt_flags |= PT_FLAG_DETACHED; + if (thread->pt_state == PT_STATE_ZOMBIE) { + /* pthread__reap() will drop the lock. */ + pthread__reap(thread); + } else { + /* + * Not valid for threads to be waiting in + * pthread_join() (there are intractable + * sync issues from the application + * perspective), but give those threads + * a chance anyway. + */ + pthread_cond_broadcast(&thread->pt_joiners); + pthread_mutex_unlock(&thread->pt_lock); + } + + return 0; +} + + +int +pthread_getname_np(pthread_t thread, char *name, size_t len) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + + if (thread->pt_magic != PT_MAGIC) + return EINVAL; + + pthread_mutex_lock(&thread->pt_lock); + if (thread->pt_name == NULL) + name[0] = '\0'; + else + strlcpy(name, thread->pt_name, len); + pthread_mutex_unlock(&thread->pt_lock); + + return 0; +} + + +int +pthread_setname_np(pthread_t thread, const char *name, void *arg) +{ + char *oldname, *cp, newname[PTHREAD_MAX_NAMELEN_NP]; + int namelen; + + if (pthread__find(thread) != 0) + return ESRCH; + + if (thread->pt_magic != PT_MAGIC) + return EINVAL; + + namelen = snprintf(newname, sizeof(newname), name, arg); + if (namelen >= PTHREAD_MAX_NAMELEN_NP) + return EINVAL; + + cp = strdup(newname); + if (cp == NULL) + return ENOMEM; + + pthread_mutex_lock(&thread->pt_lock); + oldname = thread->pt_name; + thread->pt_name = cp; + (void)_lwp_setname(thread->pt_lid, cp); + pthread_mutex_unlock(&thread->pt_lock); + + if (oldname != NULL) + free(oldname); + + return 0; +} + + + +/* + * XXX There should be a way for applications to use the efficent + * inline version, but there are opacity/namespace issues. + */ +pthread_t +pthread_self(void) +{ + if (__predict_false(__uselibcstub)) + return (pthread_t)__libc_thr_self_stub(); + + return pthread__self(); +} + + +int +pthread_cancel(pthread_t thread) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + pthread_mutex_lock(&thread->pt_lock); + thread->pt_flags |= PT_FLAG_CS_PENDING; + if ((thread->pt_flags & PT_FLAG_CS_DISABLED) == 0) { + thread->pt_cancel = 1; + pthread_mutex_unlock(&thread->pt_lock); + _lwp_wakeup(thread->pt_lid); + } else + pthread_mutex_unlock(&thread->pt_lock); + + return 0; +} + + +int +pthread_setcancelstate(int state, int *oldstate) +{ + pthread_t self; + int retval; + + if (__predict_false(__uselibcstub)) + return __libc_thr_setcancelstate_stub(state, oldstate); + + self = pthread__self(); + retval = 0; + + pthread_mutex_lock(&self->pt_lock); + + if (oldstate != NULL) { + if (self->pt_flags & PT_FLAG_CS_DISABLED) + *oldstate = PTHREAD_CANCEL_DISABLE; + else + *oldstate = PTHREAD_CANCEL_ENABLE; + } + + if (state == PTHREAD_CANCEL_DISABLE) { + self->pt_flags |= PT_FLAG_CS_DISABLED; + if (self->pt_cancel) { + self->pt_flags |= PT_FLAG_CS_PENDING; + self->pt_cancel = 0; + } + } else if (state == PTHREAD_CANCEL_ENABLE) { + self->pt_flags &= ~PT_FLAG_CS_DISABLED; + /* + * If a cancellation was requested while cancellation + * was disabled, note that fact for future + * cancellation tests. + */ + if (self->pt_flags & PT_FLAG_CS_PENDING) { + self->pt_cancel = 1; + /* This is not a deferred cancellation point. */ + if (self->pt_flags & PT_FLAG_CS_ASYNC) { + pthread_mutex_unlock(&self->pt_lock); + pthread__cancelled(); + } + } + } else + retval = EINVAL; + + pthread_mutex_unlock(&self->pt_lock); + + return retval; +} + + +int +pthread_setcanceltype(int type, int *oldtype) +{ + pthread_t self; + int retval; + + self = pthread__self(); + retval = 0; + + pthread_mutex_lock(&self->pt_lock); + + if (oldtype != NULL) { + if (self->pt_flags & PT_FLAG_CS_ASYNC) + *oldtype = PTHREAD_CANCEL_ASYNCHRONOUS; + else + *oldtype = PTHREAD_CANCEL_DEFERRED; + } + + if (type == PTHREAD_CANCEL_ASYNCHRONOUS) { + self->pt_flags |= PT_FLAG_CS_ASYNC; + if (self->pt_cancel) { + pthread_mutex_unlock(&self->pt_lock); + pthread__cancelled(); + } + } else if (type == PTHREAD_CANCEL_DEFERRED) + self->pt_flags &= ~PT_FLAG_CS_ASYNC; + else + retval = EINVAL; + + pthread_mutex_unlock(&self->pt_lock); + + return retval; +} + + +void +pthread_testcancel(void) +{ + pthread_t self; + + self = pthread__self(); + if (self->pt_cancel) + pthread__cancelled(); +} + + +/* + * POSIX requires that certain functions return an error rather than + * invoking undefined behavior even when handed completely bogus + * pthread_t values, e.g. stack garbage. + */ +int +pthread__find(pthread_t id) +{ + pthread_t target; + int error; + + pthread_rwlock_rdlock(&pthread__alltree_lock); + target = rb_tree_find_node(&pthread__alltree, id); + error = (target && target->pt_state != PT_STATE_DEAD) ? 0 : ESRCH; + pthread_rwlock_unlock(&pthread__alltree_lock); + + return error; +} + + +void +pthread__testcancel(pthread_t self) +{ + + if (self->pt_cancel) + pthread__cancelled(); +} + + +void +pthread__cancelled(void) +{ + pthread_mutex_t *droplock; + pthread_t self; + + self = pthread__self(); + droplock = self->pt_droplock; + self->pt_droplock = NULL; + + if (droplock != NULL && pthread_mutex_held_np(droplock)) + pthread_mutex_unlock(droplock); + + pthread_exit(PTHREAD_CANCELED); +} + + +void +pthread__cleanup_push(void (*cleanup)(void *), void *arg, void *store) +{ + pthread_t self; + struct pt_clean_t *entry; + + self = pthread__self(); + entry = store; + entry->ptc_cleanup = cleanup; + entry->ptc_arg = arg; + PTQ_INSERT_HEAD(&self->pt_cleanup_stack, entry, ptc_next); +} + + +void +pthread__cleanup_pop(int ex, void *store) +{ + pthread_t self; + struct pt_clean_t *entry; + + self = pthread__self(); + entry = store; + + PTQ_REMOVE(&self->pt_cleanup_stack, entry, ptc_next); + if (ex) + (*entry->ptc_cleanup)(entry->ptc_arg); +} + + +int * +pthread__errno(void) +{ + pthread_t self; + + if (__predict_false(__uselibcstub)) { + pthread__errorfunc(__FILE__, __LINE__, __func__, + "pthread__errno() requires linking with -lpthread"); + return __libc_thr_errno_stub(); + } + + self = pthread__self(); + + return &(self->pt_errno); +} + +ssize_t _sys_write(int, const void *, size_t); + +void +pthread__assertfunc(const char *file, int line, const char *function, + const char *expr) +{ + char buf[1024]; + int len; + + /* + * snprintf should not acquire any locks, or we could + * end up deadlocked if the assert caller held locks. + */ + len = snprintf(buf, 1024, + "assertion \"%s\" failed: file \"%s\", line %d%s%s%s\n", + expr, file, line, + function ? ", function \"" : "", + function ? function : "", + function ? "\"" : ""); + + _sys_write(STDERR_FILENO, buf, (size_t)len); + (void)kill(getpid(), SIGABRT); + + _exit(1); +} + + +void +pthread__errorfunc(const char *file, int line, const char *function, + const char *msg) +{ + char buf[1024]; + size_t len; + + if (pthread__diagassert == 0) + return; + + /* + * snprintf should not acquire any locks, or we could + * end up deadlocked if the assert caller held locks. + */ + len = snprintf(buf, 1024, + "%s: Error detected by libpthread: %s.\n" + "Detected by file \"%s\", line %d%s%s%s.\n" + "See pthread(3) for information.\n", + getprogname(), msg, file, line, + function ? ", function \"" : "", + function ? function : "", + function ? "\"" : ""); + + if (pthread__diagassert & DIAGASSERT_STDERR) + _sys_write(STDERR_FILENO, buf, len); + + if (pthread__diagassert & DIAGASSERT_SYSLOG) + syslog(LOG_DEBUG | LOG_USER, "%s", buf); + + if (pthread__diagassert & DIAGASSERT_ABORT) { + (void)kill(getpid(), SIGABRT); + _exit(1); + } +} + +/* + * Thread park/unpark operations. The kernel operations are + * modelled after a brief description from "Multithreading in + * the Solaris Operating Environment": + * + * http://www.sun.com/software/whitepapers/solaris9/multithread.pdf + */ + +#define OOPS(msg) \ + pthread__errorfunc(__FILE__, __LINE__, __func__, msg) + +int +pthread__park(pthread_t self, pthread_mutex_t *lock, + pthread_queue_t *queue, const struct timespec *abstime, + int cancelpt, const void *hint) +{ + int rv, error; + void *obj; + + /* + * For non-interlocked release of mutexes we need a store + * barrier before incrementing pt_blocking away from zero. + * This is provided by pthread_mutex_unlock(). + */ + self->pt_willpark = 1; + pthread_mutex_unlock(lock); + self->pt_willpark = 0; + self->pt_blocking++; + + /* + * Wait until we are awoken by a pending unpark operation, + * a signal, an unpark posted after we have gone asleep, + * or an expired timeout. + * + * It is fine to test the value of pt_sleepobj without + * holding any locks, because: + * + * o Only the blocking thread (this thread) ever sets them + * to a non-NULL value. + * + * o Other threads may set them NULL, but if they do so they + * must also make this thread return from _lwp_park. + * + * o _lwp_park, _lwp_unpark and _lwp_unpark_all are system + * calls and all make use of spinlocks in the kernel. So + * these system calls act as full memory barriers, and will + * ensure that the calling CPU's store buffers are drained. + * In combination with the spinlock release before unpark, + * this means that modification of pt_sleepobj/onq by another + * thread will become globally visible before that thread + * schedules an unpark operation on this thread. + * + * Note: the test in the while() statement dodges the park op if + * we have already been awoken, unless there is another thread to + * awaken. This saves a syscall - if we were already awakened, + * the next call to _lwp_park() would need to return early in order + * to eat the previous wakeup. + */ + rv = 0; + do { + /* + * If we deferred unparking a thread, arrange to + * have _lwp_park() restart it before blocking. + */ + error = _lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, abstime, + self->pt_unpark, hint, hint); + self->pt_unpark = 0; + if (error != 0) { + switch (rv = errno) { + case EINTR: + case EALREADY: + rv = 0; + break; + case ETIMEDOUT: + break; + default: + OOPS("_lwp_park failed"); + break; + } + } + /* Check for cancellation. */ + if (cancelpt && self->pt_cancel) + rv = EINTR; + } while (self->pt_sleepobj != NULL && rv == 0); + + /* + * If we have been awoken early but are still on the queue, + * then remove ourself. Again, it's safe to do the test + * without holding any locks. + */ + if (__predict_false(self->pt_sleepobj != NULL)) { + pthread_mutex_lock(lock); + if ((obj = self->pt_sleepobj) != NULL) { + PTQ_REMOVE(queue, self, pt_sleep); + self->pt_sleepobj = NULL; + if (obj != NULL && self->pt_early != NULL) + (*self->pt_early)(obj); + } + pthread_mutex_unlock(lock); + } + self->pt_early = NULL; + self->pt_blocking--; + membar_sync(); + + return rv; +} + +void +pthread__unpark(pthread_queue_t *queue, pthread_t self, + pthread_mutex_t *interlock) +{ + pthread_t target; + u_int max; + size_t nwaiters; + + max = pthread__unpark_max; + nwaiters = self->pt_nwaiters; + target = PTQ_FIRST(queue); + if (nwaiters == max) { + /* Overflow. */ + (void)_lwp_unpark_all(self->pt_waiters, nwaiters, + __UNVOLATILE(&interlock->ptm_waiters)); + nwaiters = 0; + } + target->pt_sleepobj = NULL; + self->pt_waiters[nwaiters++] = target->pt_lid; + PTQ_REMOVE(queue, target, pt_sleep); + self->pt_nwaiters = nwaiters; + pthread__mutex_deferwake(self, interlock); +} + +void +pthread__unpark_all(pthread_queue_t *queue, pthread_t self, + pthread_mutex_t *interlock) +{ + pthread_t target; + u_int max; + size_t nwaiters; + + max = pthread__unpark_max; + nwaiters = self->pt_nwaiters; + PTQ_FOREACH(target, queue, pt_sleep) { + if (nwaiters == max) { + /* Overflow. */ + (void)_lwp_unpark_all(self->pt_waiters, nwaiters, + __UNVOLATILE(&interlock->ptm_waiters)); + nwaiters = 0; + } + target->pt_sleepobj = NULL; + self->pt_waiters[nwaiters++] = target->pt_lid; + } + self->pt_nwaiters = nwaiters; + PTQ_INIT(queue); + pthread__mutex_deferwake(self, interlock); +} + +#undef OOPS + +static void +pthread__initmainstack(void) +{ + struct rlimit slimit; + const AuxInfo *aux; + size_t size; + + _DIAGASSERT(_dlauxinfo() != NULL); + + if (getrlimit(RLIMIT_STACK, &slimit) == -1) + err(EXIT_FAILURE, + "Couldn't get stack resource consumption limits"); + size = slimit.rlim_cur; + pthread__main->pt_stack.ss_size = size; + + for (aux = _dlauxinfo(); aux->a_type != AT_NULL; ++aux) { + if (aux->a_type == AT_STACKBASE) { + pthread__main->pt_stack.ss_sp = (void *)aux->a_v; +#ifdef __MACHINE_STACK_GROWS_UP + pthread__main->pt_stack.ss_sp = (void *)aux->a_v; +#else + pthread__main->pt_stack.ss_sp = (char *)aux->a_v - size; +#endif + break; + } + } +} + +/* + * Set up the slightly special stack for the "initial" thread, which + * runs on the normal system stack, and thus gets slightly different + * treatment. + */ +static void +pthread__initmain(pthread_t *newt) +{ + char *value; + + pthread__initmainstack(); + + value = pthread__getenv("PTHREAD_STACKSIZE"); + if (value != NULL) { + pthread__stacksize = atoi(value) * 1024; + if (pthread__stacksize > pthread__main->pt_stack.ss_size) + pthread__stacksize = pthread__main->pt_stack.ss_size; + } + if (pthread__stacksize == 0) + pthread__stacksize = pthread__main->pt_stack.ss_size; + pthread__stacksize += pthread__pagesize - 1; + pthread__stacksize &= ~(pthread__pagesize - 1); + if (pthread__stacksize < 4 * pthread__pagesize) + errx(1, "Stacksize limit is too low, minimum %zd kbyte.", + 4 * pthread__pagesize / 1024); + + *newt = pthread__main; +#if defined(_PTHREAD_GETTCB_EXT) + pthread__main->pt_tls = _PTHREAD_GETTCB_EXT(); +#elif defined(__HAVE___LWP_GETTCB_FAST) + pthread__main->pt_tls = __lwp_gettcb_fast(); +#else + pthread__main->pt_tls = _lwp_getprivate(); +#endif + pthread__main->pt_tls->tcb_pthread = pthread__main; +} + +static signed int +/*ARGSUSED*/ +pthread__cmp(void *ctx, const void *n1, const void *n2) +{ + const uintptr_t p1 = (const uintptr_t)n1; + const uintptr_t p2 = (const uintptr_t)n2; + + if (p1 < p2) + return -1; + if (p1 > p2) + return 1; + return 0; +} + +/* Because getenv() wants to use locks. */ +char * +pthread__getenv(const char *name) +{ + extern char **environ; + size_t l_name, offset; + + l_name = strlen(name); + for (offset = 0; environ[offset] != NULL; offset++) { + if (strncmp(name, environ[offset], l_name) == 0 && + environ[offset][l_name] == '=') { + return environ[offset] + l_name + 1; + } + } + + return NULL; +} + +pthread_mutex_t * +pthread__hashlock(volatile const void *p) +{ + uintptr_t v; + + v = (uintptr_t)p; + return &hashlocks[((v >> 9) ^ (v >> 3)) & (NHASHLOCK - 1)].mutex; +} + +int +pthread__checkpri(int pri) +{ + static int havepri; + static long min, max; + + if (!havepri) { + min = sysconf(_SC_SCHED_PRI_MIN); + max = sysconf(_SC_SCHED_PRI_MAX); + havepri = 1; + } + return (pri < min || pri > max) ? EINVAL : 0; +} diff --git a/lib/libpthread/pthread.h b/lib/libpthread/pthread.h new file mode 100644 index 000000000..3d3519925 --- /dev/null +++ b/lib/libpthread/pthread.h @@ -0,0 +1,384 @@ +/* $NetBSD: pthread.h,v 1.35 2012/11/03 03:10:50 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_H +#define _LIB_PTHREAD_H + +#include + +#include /* For timespec */ +#include +#include + +#include + +__BEGIN_DECLS +int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); +int pthread_create(pthread_t * __restrict, + const pthread_attr_t * __restrict, void *(*)(void *), + void * __restrict); +void pthread_exit(void *) __attribute__((__noreturn__)); +int pthread_join(pthread_t, void **); +int pthread_equal(pthread_t, pthread_t); +pthread_t pthread_self(void); +int pthread_detach(pthread_t); + +int pthread_getrrtimer_np(void); +int pthread_setrrtimer_np(int); + +int pthread_attr_init(pthread_attr_t *); +int pthread_attr_destroy(pthread_attr_t *); +int pthread_attr_get_np(pthread_t, pthread_attr_t *); +int pthread_attr_getguardsize(const pthread_attr_t * __restrict, + size_t * __restrict); +int pthread_attr_setguardsize(pthread_attr_t *, size_t); +int pthread_attr_getinheritsched(const pthread_attr_t * __restrict, + int * __restrict); +int pthread_attr_setinheritsched(pthread_attr_t *, int); +int pthread_attr_getschedparam(const pthread_attr_t * __restrict, + struct sched_param * __restrict); +int pthread_attr_setschedparam(pthread_attr_t * __restrict, + const struct sched_param * __restrict); +int pthread_attr_getschedpolicy(const pthread_attr_t * __restrict, + int * __restrict); +int pthread_attr_setschedpolicy(pthread_attr_t *, int); +int pthread_attr_getscope(const pthread_attr_t * __restrict, + int * __restrict); +int pthread_attr_setscope(pthread_attr_t *, int); +int pthread_attr_getstack(const pthread_attr_t * __restrict, + void ** __restrict, size_t * __restrict); +int pthread_attr_setstack(pthread_attr_t *, void *, size_t); +int pthread_attr_getstacksize(const pthread_attr_t * __restrict, + size_t * __restrict); +int pthread_attr_setstacksize(pthread_attr_t *, size_t); +int pthread_attr_getstackaddr(const pthread_attr_t * __restrict, + void ** __restrict); +int pthread_attr_setstackaddr(pthread_attr_t *, void *); +int pthread_attr_getdetachstate(const pthread_attr_t *, int *); +int pthread_attr_setdetachstate(pthread_attr_t *, int); +int pthread_attr_getname_np(const pthread_attr_t *, char *, + size_t, void **); +int pthread_attr_setname_np(pthread_attr_t *, const char *, void *); + +int pthread_mutex_init(pthread_mutex_t * __restrict, + const pthread_mutexattr_t * __restrict); +int pthread_mutex_destroy(pthread_mutex_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_gettype(const pthread_mutexattr_t * __restrict, + int * __restrict); +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int); + +int pthread_cond_init(pthread_cond_t * __restrict, + const pthread_condattr_t * __restrict); +int pthread_cond_destroy(pthread_cond_t *); +int pthread_cond_wait(pthread_cond_t * __restrict, + pthread_mutex_t * __restrict); +#ifndef __LIBC12_SOURCE__ +int pthread_cond_timedwait(pthread_cond_t * __restrict, + pthread_mutex_t * __restrict, const struct timespec * __restrict); +#endif +int pthread_cond_signal(pthread_cond_t *); +int pthread_cond_broadcast(pthread_cond_t *); +int pthread_condattr_init(pthread_condattr_t *); +#if defined(_NETBSD_SOURCE) +int pthread_condattr_setclock(pthread_condattr_t *, clockid_t); +#endif +int pthread_condattr_destroy(pthread_condattr_t *); + +int pthread_once(pthread_once_t *, void (*)(void)); + +int pthread_key_create(pthread_key_t *, void (*)(void *)); +int pthread_key_delete(pthread_key_t); +int pthread_setspecific(pthread_key_t, const void *); +void* pthread_getspecific(pthread_key_t); + +int pthread_cancel(pthread_t); +int pthread_setcancelstate(int, int *); +int pthread_setcanceltype(int, int *); +void pthread_testcancel(void); + +int pthread_getname_np(pthread_t, char *, size_t); +int pthread_setname_np(pthread_t, const char *, void *); + +int pthread_attr_setcreatesuspend_np(pthread_attr_t *); +int pthread_suspend_np(pthread_t); +int pthread_resume_np(pthread_t); + +unsigned int pthread_curcpu_np(void); + +struct pthread_cleanup_store { + void *pad[4]; +}; + +#define pthread_cleanup_push(routine, arg) \ + { \ + struct pthread_cleanup_store __store; \ + pthread__cleanup_push((routine),(arg), &__store); + +#define pthread_cleanup_pop(execute) \ + pthread__cleanup_pop((execute), &__store); \ + } + +void pthread__cleanup_push(void (*)(void *), void *, void *); +void pthread__cleanup_pop(int, void *); + +int pthread_spin_init(pthread_spinlock_t *, int); +int pthread_spin_destroy(pthread_spinlock_t *); +int pthread_spin_lock(pthread_spinlock_t *); +int pthread_spin_trylock(pthread_spinlock_t *); +int pthread_spin_unlock(pthread_spinlock_t *); + +int pthread_rwlock_init(pthread_rwlock_t * __restrict, + const pthread_rwlockattr_t * __restrict); +int pthread_rwlock_destroy(pthread_rwlock_t *); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlock_trywrlock(pthread_rwlock_t *); +#ifndef __LIBC12_SOURCE__ +int pthread_rwlock_timedrdlock(pthread_rwlock_t * __restrict, + const struct timespec * __restrict); +int pthread_rwlock_timedwrlock(pthread_rwlock_t * __restrict, + const struct timespec * __restrict); +#endif +int pthread_rwlock_unlock(pthread_rwlock_t *); +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); + +int pthread_barrier_init(pthread_barrier_t * __restrict, + const pthread_barrierattr_t * __restrict, unsigned int); +int pthread_barrier_wait(pthread_barrier_t *); +int pthread_barrier_destroy(pthread_barrier_t *); +int pthread_barrierattr_init(pthread_barrierattr_t *); +int pthread_barrierattr_destroy(pthread_barrierattr_t *); + +int pthread_getschedparam(pthread_t, int * __restrict, + struct sched_param * __restrict); +int pthread_setschedparam(pthread_t, int, const struct sched_param *); +int pthread_setschedprio(pthread_t, int); + +int *pthread__errno(void); + +#if defined(_NETBSD_SOURCE) +int pthread_getaffinity_np(pthread_t, size_t, cpuset_t *); +int pthread_setaffinity_np(pthread_t, size_t, cpuset_t *); +int pthread_getattr_np(pthread_t, pthread_attr_t *); + +int pthread_mutex_held_np(pthread_mutex_t *); +pthread_t pthread_mutex_owner_np(pthread_mutex_t *); + +int pthread_rwlock_held_np(pthread_rwlock_t *); +int pthread_rwlock_wrheld_np(pthread_rwlock_t *); +int pthread_rwlock_rdheld_np(pthread_rwlock_t *); + +int pthread_cond_has_waiters_np(pthread_cond_t *); +#endif /* _NETBSD_SOURCE */ + +__END_DECLS + +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_CREATE_DETACHED 1 + +#define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_EXPLICIT_SCHED 1 + +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_SCOPE_SYSTEM 1 + +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 1 + +#define PTHREAD_BARRIER_SERIAL_THREAD 1234567 + +/* + * POSIX 1003.1-2001, section 2.5.9.3: "The symbolic constant + * PTHREAD_CANCELED expands to a constant expression of type (void *) + * whose value matches no pointer to an object in memory nor the value + * NULL." + */ +#define PTHREAD_CANCELED ((void *) 1) + +/* + * Maximum length of a thread's name, including the terminating NUL. + */ +#define PTHREAD_MAX_NAMELEN_NP 32 + +/* + * Mutex attributes. + */ +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_ERRORCHECK 1 +#define PTHREAD_MUTEX_RECURSIVE 2 +#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL + +#define PTHREAD_COND_INITIALIZER _PTHREAD_COND_INITIALIZER +#define PTHREAD_MUTEX_INITIALIZER _PTHREAD_MUTEX_INITIALIZER +#define PTHREAD_ONCE_INIT _PTHREAD_ONCE_INIT +#define PTHREAD_RWLOCK_INITIALIZER _PTHREAD_RWLOCK_INITIALIZER +#define PTHREAD_SPINLOCK_INITIALIZER _PTHREAD_SPINLOCK_INITIALIZER + +/* + * Use macros to rename many pthread functions to the corresponding + * libc symbols which are either trivial/no-op stubs or the real + * thing, depending on whether libpthread is linked in to the + * program. This permits code, particularly libraries that do not + * directly use threads but want to be thread-safe in the presence of + * threaded callers, to use pthread mutexes and the like without + * unnecessairly including libpthread in their linkage. + * + * Left out of this list are functions that can't sensibly be trivial + * or no-op stubs in a single-threaded process (pthread_create, + * pthread_kill, pthread_detach), functions that normally block and + * wait for another thread to do something (pthread_join), and + * functions that don't make sense without the previous functions + * (pthread_attr_*). The pthread_cond_wait and pthread_cond_timedwait + * functions are useful in implementing certain protection mechanisms, + * though a non-buggy app shouldn't end up calling them in + * single-threaded mode. + * + * The rename is done as: + * #define pthread_foo __libc_foo + * instead of + * #define pthread_foo(x) __libc_foo((x)) + * in order that taking the address of the function ("func = + * &pthread_foo;") continue to work. + * + * POSIX/SUSv3 requires that its functions exist as functions (even if + * macro versions exist) and specifically that "#undef pthread_foo" is + * legal and should not break anything. Code that does such will not + * successfully get the stub behavior implemented here and will + * require libpthread to be linked in. + */ + +#ifndef __LIBPTHREAD_SOURCE__ +__BEGIN_DECLS +int __libc_mutex_init(pthread_mutex_t * __restrict, const pthread_mutexattr_t * __restrict); +int __libc_mutex_lock(pthread_mutex_t *); +int __libc_mutex_trylock(pthread_mutex_t *); +int __libc_mutex_unlock(pthread_mutex_t *); +int __libc_mutex_destroy(pthread_mutex_t *); + +int __libc_mutexattr_init(pthread_mutexattr_t *); +int __libc_mutexattr_settype(pthread_mutexattr_t *, int); +int __libc_mutexattr_destroy(pthread_mutexattr_t *); +__END_DECLS + +#define pthread_mutex_init __libc_mutex_init +#define pthread_mutex_lock __libc_mutex_lock +#define pthread_mutex_trylock __libc_mutex_trylock +#define pthread_mutex_unlock __libc_mutex_unlock +#define pthread_mutex_destroy __libc_mutex_destroy + +#define pthread_mutexattr_init __libc_mutexattr_init +#define pthread_mutexattr_settype __libc_mutexattr_settype +#define pthread_mutexattr_destroy __libc_mutexattr_destroy + +__BEGIN_DECLS +int __libc_cond_init(pthread_cond_t * __restrict, + const pthread_condattr_t * __restrict); +int __libc_cond_signal(pthread_cond_t *); +int __libc_cond_broadcast(pthread_cond_t *); +int __libc_cond_wait(pthread_cond_t * __restrict, + pthread_mutex_t * __restrict); +#ifndef __LIBC12_SOURCE__ +int __libc_cond_timedwait(pthread_cond_t * __restrict, + pthread_mutex_t * __restrict, const struct timespec * __restrict); +#endif +int __libc_cond_destroy(pthread_cond_t *); +__END_DECLS + +#define pthread_cond_init __libc_cond_init +#define pthread_cond_signal __libc_cond_signal +#define pthread_cond_broadcast __libc_cond_broadcast +#define pthread_cond_wait __libc_cond_wait +#define pthread_cond_timedwait __libc_cond_timedwait +#define pthread_cond_destroy __libc_cond_destroy + +__BEGIN_DECLS +int __libc_rwlock_init(pthread_rwlock_t * __restrict, + const pthread_rwlockattr_t * __restrict); +int __libc_rwlock_rdlock(pthread_rwlock_t *); +int __libc_rwlock_wrlock(pthread_rwlock_t *); +int __libc_rwlock_tryrdlock(pthread_rwlock_t *); +int __libc_rwlock_trywrlock(pthread_rwlock_t *); +int __libc_rwlock_unlock(pthread_rwlock_t *); +int __libc_rwlock_destroy(pthread_rwlock_t *); +__END_DECLS + +#define pthread_rwlock_init __libc_rwlock_init +#define pthread_rwlock_rdlock __libc_rwlock_rdlock +#define pthread_rwlock_wrlock __libc_rwlock_wrlock +#define pthread_rwlock_tryrdlock __libc_rwlock_tryrdlock +#define pthread_rwlock_trywrlock __libc_rwlock_trywrlock +#define pthread_rwlock_unlock __libc_rwlock_unlock +#define pthread_rwlock_destroy __libc_rwlock_destroy + +__BEGIN_DECLS +int __libc_thr_keycreate(pthread_key_t *, void (*)(void *)); +int __libc_thr_setspecific(pthread_key_t, const void *); +void *__libc_thr_getspecific(pthread_key_t); +int __libc_thr_keydelete(pthread_key_t); +__END_DECLS + +#define pthread_key_create __libc_thr_keycreate +#define pthread_setspecific __libc_thr_setspecific +#define pthread_getspecific __libc_thr_getspecific +#define pthread_key_delete __libc_thr_keydelete + +__BEGIN_DECLS +int __libc_thr_once(pthread_once_t *, void (*)(void)); +pthread_t __libc_thr_self(void); +void __libc_thr_exit(void *) __attribute__((__noreturn__)); +int __libc_thr_setcancelstate(int, int *); +int __libc_thr_equal(pthread_t, pthread_t); +unsigned int __libc_thr_curcpu(void); +__END_DECLS + +#define pthread_once __libc_thr_once +#define pthread_self __libc_thr_self +#define pthread_exit __libc_thr_exit +#define pthread_setcancelstate __libc_thr_setcancelstate +#define pthread_equal __libc_thr_equal +#define pthread_curcpu_np __libc_thr_curcpu + +#endif /* __LIBPTHREAD_SOURCE__ */ + +#endif /* _LIB_PTHREAD_H */ diff --git a/lib/libpthread/pthread_attr.3 b/lib/libpthread/pthread_attr.3 new file mode 100644 index 000000000..f5900527e --- /dev/null +++ b/lib/libpthread/pthread_attr.3 @@ -0,0 +1,155 @@ +.\" $NetBSD: pthread_attr.3,v 1.22 2012/11/10 23:12:36 uwe Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_attr.3,v 1.11 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_ATTR 3 +.Os +.Sh NAME +.Nm pthread_attr_init , +.Nm pthread_attr_destroy +.Nd thread attribute operations +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_init "pthread_attr_t *attr" +.Ft int +.Fn pthread_attr_destroy "pthread_attr_t *attr" +.Sh DESCRIPTION +Thread attributes are used to specify parameters to +.Fn pthread_create . +One attribute object can be used in multiple calls to +.Fn pthread_create , +with or without modifications between the calls. +The +.Vt pthread_attr_t +type is an opaque representation of the thread attributes; +any access to the object other than via the described +.Fn pthread_attr_* +functions may result in undefined behavior. +.Pp +The +.Fn pthread_attr_init +function initializes +.Fa attr +with the default thread attributes used in the implementation. +Depending on the implementation, undefined behavior may follow +if an uninitialized thread attribute object is used with some of +the thread attribute functions. +It is therefore a good practice to always use +.Fn pthread_attr_init , +even if this might be unnecessary. +Undefined behavior may also follow if an already initialized +.Fa attr +is used with +.Fn pthread_attr_init . +.Pp +When the attribute object is no longer needed, +it should be destroyed by using +.Fn pthread_attr_destroy . +The function has no effect on threads that +were created by using a given attribute object. +A destroyed +.Fa attr +can be reinitialized using +.Fn pthread_attr_init , +but all other actions with the destroyed object are unspecified. +.Pp +The following standard thread attribute functions are available: +.Bl -column -offset indent "pthread_attr_getinheritsched " "XXX" +.It Sy Function Ta Sy Description +.It Xr pthread_attr_getdetachstate 3 Ta thread detach state +.It Xr pthread_attr_getguardsize 3 Ta thread guard size +.It Xr pthread_attr_getinheritsched 3 Ta inherit scheduler attribute +.It Xr pthread_attr_getschedparam 3 Ta thread scheduling parameter +.It Xr pthread_attr_getschedpolicy 3 Ta thread scheduling policy +.It Xr pthread_attr_getscope 3 Ta thread contention scope +.It Xr pthread_attr_getstack 3 Ta thread stack +.It Xr pthread_attr_getstacksize 3 Ta thread stack size +.It Xr pthread_attr_getstackaddr 3 Ta thread stack address +.El +.Pp +Each listed +.Fn pthread_attr_get* +function has a +.Fn pthread_attr_set* +counterpart. +In addition, the following +.Nx +specific extensions are available: +.Bl -column -offset indent "pthread_attr_getinheritsched " "XXX" +.It Sy Function Ta Sy Description +.It Xr pthread_attr_get_np 3 Ta attributes of a running thread +.It Xr pthread_attr_getname_np 3 Ta descriptive name of an attribute +.El +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +No errors are defined for +.Fn pthread_attr_init +and +.Fn pthread_attr_destroy . +.Sh SEE ALSO +.Xr pthread_create 3 , +.Xr pthread_join 3 +.Sh STANDARDS +Both +.Fn pthread_attr_init +and +.Fn pthread_attr_destroy +conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_attr.c b/lib/libpthread/pthread_attr.c new file mode 100644 index 000000000..d0b861e2f --- /dev/null +++ b/lib/libpthread/pthread_attr.c @@ -0,0 +1,464 @@ +/* $NetBSD: pthread_attr.c,v 1.16 2012/03/02 18:06:05 joerg Exp $ */ + +/*- + * Copyright (c) 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_attr.c,v 1.16 2012/03/02 18:06:05 joerg Exp $"); + +#include +#include +#include +#include +#include + +#ifndef __lint__ +#define pthread_attr_get_np _pthread_attr_get_np +#endif + +#include "pthread.h" +#include "pthread_int.h" + +__weak_alias(pthread_attr_get_np, _pthread_attr_get_np) + +static struct pthread_attr_private *pthread__attr_init_private( + pthread_attr_t *); + +static struct pthread_attr_private * +pthread__attr_init_private(pthread_attr_t *attr) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) != NULL) + return p; + + p = malloc(sizeof(*p)); + if (p != NULL) { + memset(p, 0, sizeof(*p)); + attr->pta_private = p; + p->ptap_policy = SCHED_OTHER; + } + return p; +} + + +int +pthread_attr_init(pthread_attr_t *attr) +{ + + attr->pta_magic = PT_ATTR_MAGIC; + attr->pta_flags = 0; + attr->pta_private = NULL; + + return 0; +} + + +int +pthread_attr_destroy(pthread_attr_t *attr) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) != NULL) + free(p); + + return 0; +} + + +int +pthread_attr_get_np(pthread_t thread, pthread_attr_t *attr) +{ + struct pthread_attr_private *p; + + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + + attr->pta_flags = thread->pt_flags & + (PT_FLAG_DETACHED | PT_FLAG_SCOPE_SYSTEM | PT_FLAG_EXPLICIT_SCHED); + + p->ptap_namearg = thread->pt_name; + p->ptap_stackaddr = thread->pt_stack.ss_sp; + p->ptap_stacksize = thread->pt_stack.ss_size; + p->ptap_guardsize = pthread__pagesize; + return pthread_getschedparam(thread, &p->ptap_policy, &p->ptap_sp); +} + + +int +pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + + if (attr->pta_flags & PT_FLAG_DETACHED) + *detachstate = PTHREAD_CREATE_DETACHED; + else + *detachstate = PTHREAD_CREATE_JOINABLE; + + return 0; +} + + +int +pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + + switch (detachstate) { + case PTHREAD_CREATE_JOINABLE: + attr->pta_flags &= ~PT_FLAG_DETACHED; + break; + case PTHREAD_CREATE_DETACHED: + attr->pta_flags |= PT_FLAG_DETACHED; + break; + default: + return EINVAL; + } + + return 0; +} + + +int +pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guard) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) == NULL) + *guard = (size_t)sysconf(_SC_PAGESIZE); + else + *guard = p->ptap_guardsize; + + return 0; +} + + +int +pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard) +{ + struct pthread_attr_private *p; + + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + + p->ptap_guardsize = guard; + + return 0; +} + + +int +pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + + if (attr->pta_flags & PT_FLAG_EXPLICIT_SCHED) + *inherit = PTHREAD_EXPLICIT_SCHED; + else + *inherit = PTHREAD_INHERIT_SCHED; + + return 0; +} + + +int +pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + + switch (inherit) { + case PTHREAD_INHERIT_SCHED: + attr->pta_flags &= ~PT_FLAG_EXPLICIT_SCHED; + break; + case PTHREAD_EXPLICIT_SCHED: + attr->pta_flags |= PT_FLAG_EXPLICIT_SCHED; + break; + default: + return EINVAL; + } + + return 0; +} + + +int +pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + + if (attr->pta_flags & PT_FLAG_SCOPE_SYSTEM) + *scope = PTHREAD_SCOPE_SYSTEM; + else + *scope = PTHREAD_SCOPE_PROCESS; + + return 0; +} + + +int +pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + + switch (scope) { + case PTHREAD_SCOPE_PROCESS: + attr->pta_flags &= ~PT_FLAG_SCOPE_SYSTEM; + break; + case PTHREAD_SCOPE_SYSTEM: + attr->pta_flags |= PT_FLAG_SCOPE_SYSTEM; + break; + default: + return EINVAL; + } + + return 0; +} + + +int +pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) +{ + struct pthread_attr_private *p; + int error; + + if (param == NULL) + return EINVAL; + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + error = pthread__checkpri(param->sched_priority); + if (error == 0) + p->ptap_sp = *param; + return error; +} + + +int +pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) +{ + struct pthread_attr_private *p; + + if (param == NULL) + return EINVAL; + p = attr->pta_private; + if (p == NULL) + memset(param, 0, sizeof(*param)); + else + *param = p->ptap_sp; + return 0; +} + + +int +pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + struct pthread_attr_private *p; + + + switch (policy) { + case SCHED_OTHER: + case SCHED_FIFO: + case SCHED_RR: + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + p->ptap_policy = policy; + return 0; + default: + return ENOTSUP; + } +} + + +int +pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + struct pthread_attr_private *p; + + p = attr->pta_private; + if (p == NULL) { + *policy = SCHED_OTHER; + return 0; + } + *policy = p->ptap_policy; + return 0; +} + + +int +pthread_attr_getstack(const pthread_attr_t *attr, void **addr, size_t *size) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) == NULL) { + *addr = NULL; + *size = pthread__stacksize; + } else { + *addr = p->ptap_stackaddr; + *size = p->ptap_stacksize; + } + + return 0; +} + + +int +pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size) +{ + struct pthread_attr_private *p; + + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + + p->ptap_stackaddr = addr; + p->ptap_stacksize = size; + + return 0; +} + + +int +pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) == NULL) + *size = pthread__stacksize; + else + *size = p->ptap_stacksize; + + return 0; +} + + +int +pthread_attr_setstacksize(pthread_attr_t *attr, size_t size) +{ + struct pthread_attr_private *p; + + if (size < (size_t)sysconf(_SC_THREAD_STACK_MIN)) + return EINVAL; + + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + + p->ptap_stacksize = size; + + return 0; +} + + +int +pthread_attr_getstackaddr(const pthread_attr_t *attr, void **addr) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) == NULL) + *addr = NULL; + else + *addr = p->ptap_stackaddr; + + return 0; +} + + +int +pthread_attr_setstackaddr(pthread_attr_t *attr, void *addr) +{ + struct pthread_attr_private *p; + + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + + p->ptap_stackaddr = addr; + + return 0; +} + + +int +pthread_attr_getname_np(const pthread_attr_t *attr, char *name, size_t len, + void **argp) +{ + struct pthread_attr_private *p; + + if ((p = attr->pta_private) == NULL) { + name[0] = '\0'; + if (argp != NULL) + *argp = NULL; + } else { + strlcpy(name, p->ptap_name, len); + if (argp != NULL) + *argp = p->ptap_namearg; + } + + return 0; +} + + +int +pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg) +{ + struct pthread_attr_private *p; + int namelen; + + p = pthread__attr_init_private(attr); + if (p == NULL) + return ENOMEM; + + namelen = snprintf(p->ptap_name, PTHREAD_MAX_NAMELEN_NP, name, arg); + if (namelen >= PTHREAD_MAX_NAMELEN_NP) { + p->ptap_name[0] = '\0'; + return EINVAL; + } + p->ptap_namearg = arg; + + return 0; +} + +int +pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) +{ + attr->pta_flags |= PT_FLAG_SUSPENDED; + return 0; +} + +int +pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) +{ + int error; + if ((error = pthread_attr_init(attr)) != 0) + return error; + if ((error = pthread_attr_get_np(thread, attr)) != 0) { + (void)pthread_attr_destroy(attr); + return error; + } + return 0; +} diff --git a/lib/libpthread/pthread_attr_get_np.3 b/lib/libpthread/pthread_attr_get_np.3 new file mode 100644 index 000000000..d34aaa751 --- /dev/null +++ b/lib/libpthread/pthread_attr_get_np.3 @@ -0,0 +1,121 @@ +.\" $NetBSD: pthread_attr_get_np.3,v 1.4 2010/08/06 05:35:42 christos Exp $ +.\" +.\" Copyright (c) 2010 Jukka Ruohonen +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd August 6, 2010 +.Dt PTHREAD_ATTR_GET_NP 3 +.Os +.Sh NAME +.Nm pthread_attr_get_np +.Nd get attributes of existing thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_get_np "pthread_t thread" "pthread_attr_t *attr" +.Ft int +.Fn pthread_getattr_np "pthread_t thread" "pthread_attr_t *attr" +.Sh DESCRIPTION +The +.Fn pthread_attr_get_np +and +.Fn pthread_getattr_np +functions can be used to retrieve attributes of a running +.Fa thread . +The result is stored to +.Fa attr . +.Pp +For +.Fn pthread_attr_get_np +.Fa attr +should be initialized prior to the call by using +.Xr pthread_attr_init 3 . +.Fn pthread_getattr_np +does this automatically. +.Pp +For both functions +.Fa attr +should be freed when it is not in use anymore with +.Xr pthread_attr_destroy 3 . +.Pp +Most fields of +.Fa attr +are the same ones provided during thread creation time as a parameter to +.Xr pthread_create 3 . +The exceptions include: +.Bl -bullet -offset indent +.It +The detach state -- a joinable thread +may have detached itself after the creation. +.It +The guard size, which may vary if the application +has allocated its own thread stack. +.It +The stack address and size; +.Fn pthread_attr_get_np +will always return the thread's real stack address and size, +regardless of the values in the original attributes structure. +.El +.Pp +The returned +.Vt pthread_attr_t +structure is supposed to be used in conjunction with the +.Fn pthread_attr_get* +functions to retrieve individual values from the structure. +When the returned +.Fa attr +is no longer needed, it should be destroyed by using +.Xr pthread_attr_destroy 3 . +.Sh RETURN VALUES +Upon successful completion, +.Fn pthread_attr_get_np +and +.Fn pthread_getattr_np +return 0. +Otherwise an error number is returned to indicate the error. +.Sh COMPATIBILITY +The +.Fn pthread_attr_get_np +and +.Fn pthread_getattr_np +functions are non-standard extensions. +.Sh ERRORS +The +.Fn pthread_attr_get_np +and +.Fn pthread_getattr_np +functions will fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +Insufficient memory. +.It Bq Er ESRCH +Non-existent +.Fa thread . +.El +.Sh SEE ALSO +.Xr pthread 3 , +.Xr pthread_attr 3 diff --git a/lib/libpthread/pthread_attr_getdetachstate.3 b/lib/libpthread/pthread_attr_getdetachstate.3 new file mode 100644 index 000000000..aaf2a9def --- /dev/null +++ b/lib/libpthread/pthread_attr_getdetachstate.3 @@ -0,0 +1,119 @@ +.\" $NetBSD: pthread_attr_getdetachstate.3,v 1.2 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_attr.3,v 1.11 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_ATTR_GETDETACHSTATE 3 +.Os +.Sh NAME +.Nm pthread_attr_getdetachstate +.Nd get and set the +.Dq detach state +attribute +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getdetachstate "const pthread_attr_t *attr" "int *detachstate" +.Ft int +.Fn pthread_attr_setdetachstate "pthread_attr_t *attr" "int detachstate" +.Sh DESCRIPTION +The attribute parameters for the +.Fn pthread_attr_getdetachstate +and +.Fn pthread_attr_setdetachstate +functions are mutually exclusive and must be one of: +.Bl -tag -width PTHREAD_CREATE_DETACHED -offset 2n +.It Dv PTHREAD_CREATE_JOINABLE +The threads must explicitly be waited for using the +.Xr pthread_join 3 +function once they exit for their status to be received and their resources +to be freed. +This is the default. +.It Dv PTHREAD_CREATE_DETACHED +The thread's resources will automatically be freed once the thread exits, +and the thread will not be joined. +.El +.Pp +If the thread is created as detached, +it is an error to use the thread +.Tn ID +with +.Xr pthread_detach 3 +or +.Xr pthread_join 3 . +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +No errors are defined for +.Fn pthread_attr_getdetachstate . +.Pp +The +.Fn pthread_attr_setdetachstate +function should fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa detachstate +is invalid. +.El +.Sh SEE ALSO +.Xr pthread_attr 3 , +.Xr pthread_detach 3 , +.Xr pthread_join 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_attr_getguardsize.3 b/lib/libpthread/pthread_attr_getguardsize.3 new file mode 100644 index 000000000..88e3143f3 --- /dev/null +++ b/lib/libpthread/pthread_attr_getguardsize.3 @@ -0,0 +1,124 @@ +.\" $NetBSD: pthread_attr_getguardsize.3,v 1.2 2010/07/08 18:24:34 wiz Exp $ +.\" +.\" Copyright (c) 2010 Jukka Ruohonen +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 7, 2010 +.Dt PTHREAD_ATTR_GETGUARDSIZE 3 +.Os +.Sh NAME +.Nm pthread_attr_getguardsize +.Nd get and set thread guard size +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getguardsize \ +"const pthread_attr_t * restrict attr" "size_t * restrict guardsize" +.Ft int +.Fn pthread_attr_setguardsize "pthread_attr_t *attr" "size_t guardsize" +.Sh DESCRIPTION +The +.Fn pthread_attr_getguardsize +and +.Fn pthread_attr_setguardsize +functions get and set +.Fa guardsize +in the +.Fa attr +object. +If +.Fa guardsize +is larger than 0, the system reserves +an additional region of guarded memory of at least +.Fa guardsize +bytes at the end of the thread's stack for each new thread created by using +.Fa attr . +.Pp +The guarded area is understood to be pages of memory +that are protected from read and write access. +While the guarded area should be rounded by the system page size, +the actual default size is implementation-defined. +In +.Nx +the default +.Fa guardsize +is +.Dv _SC_PAGESIZE , +the system page size. +.Pp +The rationale behind +.Fa guardsize +is two-fold: +.Bl -enum -offset 2n +.It +On the one hand, it provides protection against overflow of the stack pointer. +If there is a guard area and a thread overflows its +stack pointer into this extra memory area, it should receive a +.Dv SIGSEGV +signal or experience other comparable fatal error condition. +Note that if a thread allocates large data structures on stack, +it may be necessary to raise the default +.Fa guardsize +in order to detect stack overflows. +.It +On the other hand, the overflow protection may waste system resources +if an application that creates a large number of threads knows that it +will never overflow the stack. +In this case it is possible to set +.Fa guardsize +to 0. +.El +.Pp +If +.Xr pthread_attr_setstack 3 +or +.Xr pthread_attr_setstackaddr 3 +is used to set the stack address attribute in +.Fa attr , +the guard size attribute is ignored and no guard area will be allocated; +it is the responsibility of the application to handle the overflow conditions. +.Sh RETURN VALUES +If successful, both functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +No errors are defined for +.Fn pthread_attr_getguardsize . +.Pp +The +.Fn pthread_attr_setguardsize +may fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +There was insufficient memory. +.El +.Sh SEE ALSO +.Xr pthread_attr 3 , +.Xr pthread_attr_setstack 3 , +.Xr sysconf 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2008 . diff --git a/lib/libpthread/pthread_attr_getinheritsched.3 b/lib/libpthread/pthread_attr_getinheritsched.3 new file mode 100644 index 000000000..83211bca6 --- /dev/null +++ b/lib/libpthread/pthread_attr_getinheritsched.3 @@ -0,0 +1,112 @@ +.\" $NetBSD: pthread_attr_getinheritsched.3,v 1.3 2013/05/10 21:06:14 christos Exp $ +.\" +.\" Copyright (c) 2010 Jukka Ruohonen +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd May 10, 2013 +.Dt PTHREAD_ATTR_GETINHERITSCHED 3 +.Os +.Sh NAME +.Nm pthread_attr_getinheritsched +.Nd get and set +.Dq inheritsched +attribute +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getinheritsched \ +"const pthread_attr_t * restrict attr" "int * restrict inheritsched" +.Ft int +.Fn pthread_attr_setinheritsched "pthread_attr_t *attr" "int inheritsched" +.Sh DESCRIPTION +The +.Fn pthread_attr_getinheritsched +and +.Fn pthread_attr_setinheritsched +functions get and set, respectively, the inherit scheduler attribute, +.Fa inheritsched , +in the +.Fa attr +object. +The +.Fa inheritsched +parameter specifies whether a tread created by using +.Fa attr +will obtain its scheduling attributes directly from +.Fa attr +or whether it will inherit these from the calling thread. +.Pp +Two values are possible for +.Fa inheritsched : +.Bl -tag -width PTHREAD_EXPLICIT_SCHED -offset indent +.It Dv PTHREAD_INHERIT_SCHED +The thread scheduling attributes will be +inherited from the creating thread and the ones in +.Fa attr +are ignored. +.It Dv PTHREAD_EXPLICIT_SCHED +The thread scheduling attributes will be set to the corresponding values in +.Fa attr . +.El +.Pp +The following thread scheduling attributes are affected by +.Fa inheritsched : +.Bl -bullet -offset indent +.It +Scheduling policy; see +.Xr pthread_attr_setschedpolicy 3 . +.It +Scheduling parameter; see +.Xr pthread_attr_getschedparam 3 . +.It +Scheduling contention scope; see +.Xr pthread_attr_getscope 3 . +.El +.Sh RETURN VALUES +If successful, both functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh COMPATIBILITY +The standard leaves it unspecified which (if any) is the default +inherit scheduler attribute in a newly initialized attribute object. +.Sh ERRORS +No errors are defined for +.Fn pthread_attr_getinheritsched . +.Pp +The +.Fn pthread_attr_setinheritsched +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa inheritsched +is invalid. +.El +.Sh SEE ALSO +.Xr pthread_attr 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2008 . diff --git a/lib/libpthread/pthread_attr_getname_np.3 b/lib/libpthread/pthread_attr_getname_np.3 new file mode 100644 index 000000000..0eb22662c --- /dev/null +++ b/lib/libpthread/pthread_attr_getname_np.3 @@ -0,0 +1,109 @@ +.\" $NetBSD: pthread_attr_getname_np.3,v 1.6 2010/07/09 10:55:57 jruoho Exp $ +.\" +.\" Copyright (c)2007 YAMAMOTO Takashi, +.\" 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. +.\" +.\" ------------------------------------------------------------ +.Dd July 7, 2010 +.Dt PTHREAD_ATTR_GETNAME_NP 3 +.Os +.Sh NAME +.Nm pthread_attr_getname_np +.Nd get and set descriptive name of an attribute +.\" ------------------------------------------------------------ +.Sh LIBRARY +.Lb libpthread +.\" ------------------------------------------------------------ +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getname_np \ +"const pthread_attr_t attr" "char *name" "size_t len" +.Ft int +.Fn pthread_attr_setname_np \ +"pthread_attr_t attr" "const char *name" "void *arg" +.\" ------------------------------------------------------------ +.Sh DESCRIPTION +The +.Fn pthread_attr_getname_np +function gets the descriptive name of a thread attribute. +It takes the following arguments: +.Bl -tag -width target -offset indent +.It Fa attr +The attribute whose descriptive name will be obtained. +.It Fa name +The buffer to be filled with the descriptive name of the attribute. +.It Fa len +The size of the buffer +.Fa name +in bytes. +.El +.Pp +The +.Fn pthread_attr_setname_np +function sets the descriptive name of a thread attribute. +It takes the following arguments: +.Bl -tag -width attr -offset indent +.It Fa attr +The attribute whose descriptive name will be set. +.It Fa name +The +.Xr printf 3 +format string to be used to construct the descriptive name of the attribute. +The resulted descriptive name should be shorter than +.Dv PTHREAD_MAX_NAMELEN_NP . +.It Fa arg +The +.Xr printf 3 +argument used with +.Fa name . +.El +.\" ------------------------------------------------------------ +.Sh RETURN VALUES +Both functions return 0 on success. +Otherwise, an error number is returned. +.\" ------------------------------------------------------------ +.Sh COMPATIBILITY +Both functions are non-standard extensions. +.\" ------------------------------------------------------------ +.Sh ERRORS +No errors are defined for +.Fn pthread_attr_getname_np . +.Pp +The +.Fn pthread_attr_setname_np +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The supplied descriptive +.Fa name +was longer than +.Dv PTHREAD_MAX_NAMELEN_NP . +.It Bq Er ENOMEM +There was insufficient memory for the operation. +.El +.\" ------------------------------------------------------------ +.Sh SEE ALSO +.Xr pthread_attr 3 , +.Xr pthread_getname_np 3 diff --git a/lib/libpthread/pthread_attr_getschedparam.3 b/lib/libpthread/pthread_attr_getschedparam.3 new file mode 100644 index 000000000..7269d217a --- /dev/null +++ b/lib/libpthread/pthread_attr_getschedparam.3 @@ -0,0 +1,124 @@ +.\" $NetBSD: pthread_attr_getschedparam.3,v 1.2 2010/07/08 22:19:26 jruoho Exp $ +.\" +.\" Copyright (c) 2010 Jukka Ruohonen +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 7, 2010 +.Dt PTHREAD_ATTR_GETSCHEDPARAM 3 +.Os +.Sh NAME +.Nm pthread_attr_getschedparam +.Nd get and set scheduling attributes +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getschedparam \ +"const pthread_attr_t * restrict attr" "struct sched_param * restrict param" +.Ft int +.Fn pthread_attr_setschedparam \ +"pthread_attr_t *attr" "const struct sched_param *param" +.Ft int +.Fn pthread_attr_getschedpolicy \ +"const pthread_attr_t * restrict attr" "int * restrict policy" +.Ft int +.Fn pthread_attr_setschedpolicy "pthread_attr_t *attr" "int policy" +.Sh DESCRIPTION +The +.Fn pthread_attr_getschedparam +and +.Fn pthread_attr_setschedparam +functions obtain and set the scheduling parameter attribute in the +.Fa attr +object. +The +.Vt sched_param +structure is defined in +.In sched.h . +At minimum this structure contains only a single member, +.Vt sched_priority . +Refer to +.Xr pthread_schedparam 3 +and +.Xr sched 3 +for additional details. +.Pp +The +.Fn pthread_attr_getschedpolicy +and +.Fn pthread_attr_setschedpolicy +functions get and set the scheduling policy attribute, +.Fa policy , +in the +.Fa attr +object. +The supported values of +.Fa policy +are the same ones listed in +.Xr pthread_schedparam 3 . +.Sh RETURN VALUES +If successful, all described functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +The +.Fn pthread_attr_getschedparam +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +An invalid parameter was specified. +.El +.Pp +The +.Fn pthread_attr_setschedparam +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +An invalid parameter was specified. +.It Bq Er ENOMEM +There was insufficient memory. +.El +.Pp +The +.Fn pthread_attr_setschedpolicy +function may fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +There was insufficient memory. +.It Bq Er ENOTSUP +An unsupported +.Fa policy +was specified. +.El +.Pp +No errors are defined for +.Fn pthread_attr_getschedpolicy . +.Sh SEE ALSO +.Xr pthread_attr 3 , +.Xr pthread_schedparam 3 , +.Xr sched 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2008 . diff --git a/lib/libpthread/pthread_attr_getscope.3 b/lib/libpthread/pthread_attr_getscope.3 new file mode 100644 index 000000000..12e4dc671 --- /dev/null +++ b/lib/libpthread/pthread_attr_getscope.3 @@ -0,0 +1,99 @@ +.\" $NetBSD: pthread_attr_getscope.3,v 1.2 2010/07/07 10:22:33 njoly Exp $ +.\" +.\" Copyright (c) 2010 Jukka Ruohonen +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 7, 2010 +.Dt PTHREAD_ATTR_GETSCOPE 3 +.Os +.Sh NAME +.Nm pthread_attr_getscope +.Nd get and set the contention scope attribute +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getscope \ +"const pthread_attr_t * restrict attr" "int * restrict contentionscope" +.Ft int +.Fn pthread_attr_setscope "pthread_attr_t *attr" "int contentionscope" +.Sh DESCRIPTION +The +.Fn pthread_attr_getscope +and +.Fn pthread_attr_setscope +functions get and set, respectively, the contention scope attribute in the +.Fa attr +object. +.Pp +The +.Fa contentionscope +parameter specifies the scheduling contention scope of a thread. +It is only possible to set the scope of a thread before the thread is created. +There are two possible contention scopes: +.Bl -tag -width PTHREAD_SCOPE_PROCESS -offset 2n +.It Dv PTHREAD_SCOPE_SYSTEM +The thread will contend for +.Tn CPU +resources with all other processes and threads in the system. +Generally this means that the user thread is bound directly to the +kernel scheduling for its entire lifetime. +.It Dv PTHREAD_SCOPE_PROCESS +The thread will contend with other threads with the same scope attribute. +In general, this means that all +.Dv PTHREAD_SCOPE_PROCESS +threads are grouped together and this group of threads contends for +.Tn CPU +resources. +This is commonly seen to require a hybrid +.Pq Dq M:N +threading model in order to multiplex the user and kernel space scheduling. +.El +.Pp +Only +.Dv PTHREAD_SCOPE_SYSTEM +is supported in +.Nx . +.Sh RETURN VALUES +Upon successful completion, both functions return 0. +Otherwise an error number is returned to indicate the error. +.Sh ERRORS +No errors are defined for +.Fn pthread_attr_getscope . +.Pp +The +.Fn pthread_attr_setscope +function shall fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +Invalid parameter. +.El +.Sh SEE ALSO +.Xr pthread_attr 3 , +.Xr csf 9 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-96 . diff --git a/lib/libpthread/pthread_attr_getstack.3 b/lib/libpthread/pthread_attr_getstack.3 new file mode 100644 index 000000000..1a2741daa --- /dev/null +++ b/lib/libpthread/pthread_attr_getstack.3 @@ -0,0 +1,175 @@ +.\" $NetBSD: pthread_attr_getstack.3,v 1.5 2010/07/09 17:15:59 jruoho Exp $ +.\" +.\" Copyright (c) 2010 Jukka Ruohonen +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 9, 2010 +.Dt PTHREAD_ATTR_GETSTACK 3 +.Os +.Sh NAME +.Nm pthread_attr_getstack +.Nd get and set thread stack attributes +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_getstack \ +"const pthread_attr_t * restrict attr" \ +"void ** restrict stackaddr, size_t * restrict stacksize" +.Ft int +.Fn pthread_attr_setstack \ +"pthread_attr_t * restrict attr" "void *stackaddr, size_t stacksize" +.Ft int +.Fn pthread_attr_getstacksize \ +"const pthread_attr_t * restrict attr" "size_t * restrict stacksize" +.Ft int +.Fn pthread_attr_setstacksize \ +"pthread_attr_t *attr" "size_t stacksize" +.Ft int +.Fn pthread_attr_getstackaddr \ +"const pthread_attr_t * restrict attr" "void ** restrict stackaddr" +.Ft int +.Fn pthread_attr_setstackaddr \ +"pthread_attr_t *attr" "void *stackaddr" +.Sh DESCRIPTION +The +.Fn pthread_attr_getstack +and +.Fn pthread_attr_setstack +functions get and set, respectively, the thread stack attributes +.Fa stackaddr +and +.Fa stacksize +in the +.Fa attr +object. +The remaining four functions behave similarly, +but instead of getting or setting both +.Fa stackaddr +and +.Fa stacksize , +these get and set the values individually. +.Pp +The +.Fa stacksize +parameter is defined to be the minimum stack size (in bytes) +allocated for the thread's stack during the creation of the thread. +The +.Fa stackaddr +attribute specifies the location of storage to be used for the thread's stack. +All pages within the stack described by +.Fa stackaddr +and +.Fa stacksize +should be both readable and writable by the thread. +.Pp +The behavior is undefined in all functions if the +.Fa attr +parameter does not refer to an attribute object initialized by using +.Xr pthread_attr_init 3 +prior to the call. +In addition, undefined behavior may follow if the +.Fn pthread_attr_getstack +function is called before the +.Fa stackaddr +attribute has been set. +.Ss Rationale +The rationale behind these functions is to address cases where an application +may be used in an environment where the stack of a thread must be placed to +some particular region of memory. +For the majority of applications, this is seldom necessary, +and the use of these functions should be generally avoided. +At least few potential caveats can be mentioned. +.Bl -bullet -offset 2n +.It +There is a certain degree of ambiguity in the +.Tn POSIX +standard with respect to thread stack. +.It +The exact behavior of the functions may vary +both across machines and operating systems. +In particular, the address specified by +.Fa stackaddr +should be suitably aligned. +The system page size, as specified by +.Xr sysconf 3 , +and the use of +.Xr posix_memalign 3 +may guarantee some degree of portability. +Also +.Xr mmap 2 +provides means for alignment. +.It +If the application modifies the stack address, it claims also +the responsibility of allocating the stack area and guarding it against +possible stack overflow. +No default guard area will be allocated (see +.Xr pthread_attr_getguardsize 3 ) . +It may be necessary to manually use +.Xr mprotect 2 +in order to define a guard area at the end of the allocated stack. +.It +Moreover, if +.Fa attr +is used to create multiple threads, the stack address must be changed +by the application between successive calls to +.Xr pthread_create 3 . +.El +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +No errors are defined for the three functions that obtain the stack values. +The three functions that set the stack values may fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +There was insufficient memory to complete the operation. +.El +.Pp +The +.Fn pthread_attr_setstacksize +function may additionally fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The specified +.Fa stacksize +is less than +.Dv PTHREAD_STACK_MIN +or exceeds some system-imposed limit. +.El +.Sh SEE ALSO +.Xr pthread_attr 3 , +.Xr pthread_attr_setguardsize 3 +.Sh STANDARDS +All described functions conform to +.St -p1003.1-2001 . +Note that +.Fn pthread_attr_getstackaddr +and +.Fn pthread_attr_setstackaddr +were however removed from the specification in the +.St -p1003.1-2008 +revision. diff --git a/lib/libpthread/pthread_attr_setcreatesuspend_np.3 b/lib/libpthread/pthread_attr_setcreatesuspend_np.3 new file mode 100644 index 000000000..a285bedbf --- /dev/null +++ b/lib/libpthread/pthread_attr_setcreatesuspend_np.3 @@ -0,0 +1,66 @@ +.\" $NetBSD: pthread_attr_setcreatesuspend_np.3,v 1.4 2010/07/09 09:10:34 jruoho Exp $ +.\" +.\" Copyright (c) 2003 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 9, 2010 +.Dt PTHREAD_ATTR_SETCREATESUSPEND_NP 3 +.Os +.Sh NAME +.Nm pthread_attr_setcreatesuspend_np +.Nd set attribute to create a thread suspended +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_attr_setcreatesuspend_np "pthread_attr_t attr" +.Sh DESCRIPTION +The +.Fn pthread_attr_setcreatesuspend_np +function sets the +.Ar attr +argument, so that if this +.Ar attr +is used in a +.Xr pthread_create 3 +call, then the thread created will not run, but it will remain blocked +in the suspended queue, until +.Xr pthread_resume_np 3 +is called on it. +.Sh RETURN VALUES +The +.Fn pthread_attr_setcreatesuspend_np +function always returns 0. +.Sh COMPATIBILITY +The function is a non-standard extension. +.Sh ERRORS +No errors are defined. +.Sh SEE ALSO +.Xr pthread_create 3 , +.Xr pthread_resume_np 3 , +.Xr pthread_suspend_np 3 diff --git a/lib/libpthread/pthread_barrier.3 b/lib/libpthread/pthread_barrier.3 new file mode 100644 index 000000000..8cbec1012 --- /dev/null +++ b/lib/libpthread/pthread_barrier.3 @@ -0,0 +1,162 @@ +.\" $NetBSD: pthread_barrier.3,v 1.4 2010/07/09 18:07:20 jruoho Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" ---------------------------------------------------------------------------- +.Dd July 8, 2010 +.Dt PTHREAD_BARRIER 3 +.Os +.Sh NAME +.Nm pthread_barrier +.Nd barrier interface +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_barrier_init "pthread_barrier_t * restrict barrier" \ +"const pthread_barrierattr_t * restrict attr" "unsigned int count" +.Ft int +.Fn pthread_barrier_destroy "pthread_barrier_t *barrier" +.Ft int +.Fn pthread_barrier_wait "pthread_barrier_t *barrier" +.\" ---------------------------------------------------------------------------- +.Sh DESCRIPTION +The +.Fn pthread_barrier_init +function creates a new barrier with attributes +.Fa attr +and +.Fa count . +The +.Fa count +parameter indicates the number of threads +which will participate in the barrier. +The +.Xr pthread_barrierattr_init 3 +function may be used to specify the attributes supplied in +.Fa attr . +If +.Fa attr +is +.Dv NULL , +the default attributes are used. +Barriers are most commonly used in the decomposition of parallel loops. +.Pp +.\" ----- +The +.Fn pthread_barrier_destroy +function causes the resources allocated to +.Fa barrier +to be released. +No threads should be blocked on +.Fa barrier . +.Pp +.\" ----- +The +.Fn pthread_barrier_wait +function causes the current thread to wait on the barrier specified. +Once as many threads as specified by the +.Fa count +parameter to the corresponding +.Fn pthread_barrier_init +call have called +.Fn pthread_barrier_wait , +all threads will wake up, return from their respective +.Fn pthread_barrier_wait +calls and continue execution. +.\" ---------------------------------------------------------------------------- +.Sh RETURN VALUES +If successful, +.Fn pthread_barrier_init +will return zero and put the new barrier id into +.Fa barrier , +otherwise an error number will be returned to indicate the error. +.Pp +.\" ----- +If successful, +.Fn pthread_barrier_destroy +will return zero. +Otherwise an error value will be returned. +.Pp +.\" ----- +If successful, +.Fn pthread_barrier_wait +will return zero for all waiting threads except for one. +One thread will receive status +.Dv PTHREAD_BARRIER_SERIAL_THREAD , +which is intended to indicate that this thread may be used to update +shared data. +It is the responsibility of this thread to insure the visibility +and atomicity of any updates to shared data with respect to the +other threads participating in the barrier. +In the case of failure, an error value will be returned. +.\" ---------------------------------------------------------------------------- +.Sh ERRORS +The +.Fn pthread_barrier_init +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa count +is zero or +.Fa attr +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_barrier_destroy +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The +.Fa barrier +still has active threads associated with it. +.It Bq Er EINVAL +The value specified by +.Fa barrier +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_barrier_wait +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa barrier +is invalid. +.El +.\" --------------------------------------------------------------------------- +.Sh SEE ALSO +.Xr pthread_barrierattr 3 , +.Xr pthread_cond 3 , +.Xr pthread_mutex 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_barrier.c b/lib/libpthread/pthread_barrier.c new file mode 100644 index 000000000..4fa5f166e --- /dev/null +++ b/lib/libpthread/pthread_barrier.c @@ -0,0 +1,137 @@ +/* $NetBSD: pthread_barrier.c,v 1.19 2009/01/29 21:19:35 ad Exp $ */ + +/*- + * Copyright (c) 2001, 2003, 2006, 2007, 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams, by Jason R. Thorpe, and by Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_barrier.c,v 1.19 2009/01/29 21:19:35 ad Exp $"); + +#include + +#include "pthread.h" +#include "pthread_int.h" + +int +pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, unsigned int count) +{ + + if (attr != NULL && attr->ptba_magic != _PT_BARRIERATTR_MAGIC) + return EINVAL; + if (count == 0) + return EINVAL; + + barrier->ptb_magic = _PT_BARRIER_MAGIC; + PTQ_INIT(&barrier->ptb_waiters); + barrier->ptb_initcount = count; + barrier->ptb_curcount = 0; + barrier->ptb_generation = 0; + return 0; +} + +int +pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + + if (barrier->ptb_magic != _PT_BARRIER_MAGIC) + return EINVAL; + if (barrier->ptb_curcount != 0) + return EBUSY; + return 0; +} + +int +pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_t *interlock; + pthread_t self; + unsigned int gen; + + if (barrier->ptb_magic != _PT_BARRIER_MAGIC) + return EINVAL; + + /* + * A single arbitrary thread is supposed to return + * PTHREAD_BARRIER_SERIAL_THREAD, and everone else + * is supposed to return 0. Since pthread_barrier_wait() + * is not a cancellation point, this is trivial; we + * simply elect that the thread that causes the barrier + * to be satisfied gets the special return value. Note + * that this final thread does not actually need to block, + * but instead is responsible for waking everyone else up. + */ + self = pthread__self(); + interlock = pthread__hashlock(barrier); + pthread_mutex_lock(interlock); + if (barrier->ptb_curcount + 1 == barrier->ptb_initcount) { + barrier->ptb_generation++; + barrier->ptb_curcount = 0; + pthread__unpark_all(&barrier->ptb_waiters, self, + interlock); + pthread_mutex_unlock(interlock); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + barrier->ptb_curcount++; + gen = barrier->ptb_generation; + for (;;) { + PTQ_INSERT_TAIL(&barrier->ptb_waiters, self, pt_sleep); + self->pt_sleepobj = &barrier->ptb_waiters; + (void)pthread__park(self, interlock, &barrier->ptb_waiters, + NULL, 0, __UNVOLATILE(&interlock->ptm_waiters)); + if (__predict_true(gen != barrier->ptb_generation)) { + break; + } + pthread_mutex_lock(interlock); + if (gen != barrier->ptb_generation) { + pthread_mutex_unlock(interlock); + break; + } + } + + return 0; +} + + +int +pthread_barrierattr_init(pthread_barrierattr_t *attr) +{ + + attr->ptba_magic = _PT_BARRIERATTR_MAGIC; + return 0; +} + +int +pthread_barrierattr_destroy(pthread_barrierattr_t *attr) +{ + + if (attr->ptba_magic != _PT_BARRIERATTR_MAGIC) + return EINVAL; + attr->ptba_magic = _PT_BARRIERATTR_DEAD; + return 0; +} diff --git a/lib/libpthread/pthread_barrierattr.3 b/lib/libpthread/pthread_barrierattr.3 new file mode 100644 index 000000000..38b04f192 --- /dev/null +++ b/lib/libpthread/pthread_barrierattr.3 @@ -0,0 +1,77 @@ +.\" $NetBSD: pthread_barrierattr.3,v 1.9 2010/07/09 10:45:36 wiz Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 9, 2010 +.Dt PTHREAD_BARRIERATTR 3 +.Os +.Sh NAME +.Nm pthread_barrierattr_init , +.Nm pthread_barrierattr_destroy , +.Nd barrier attribute operations +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_barrierattr_init "pthread_barrierattr_t *attr" +.Ft int +.Fn pthread_barrierattr_destroy "pthread_barrierattr_t *attr" +.Sh DESCRIPTION +Barrier attributes are used to specify parameters to be used with +.Xr pthread_barrier_init 3 . +One attribute object can be used in multiple calls to +.Fn pthread_barrier_init , +with or without modifications between calls. +.Pp +The +.Fn pthread_barrierattr_init +function initializes +.Fa attr +with the default barrier attributes. +.Pp +The +.Fn pthread_barrierattr_destroy +function destroys +.Fa attr . +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +No error codes are defined for +.Fn pthread_barrierattr_init . +.Pp +The +.Fn pthread_barrierattr_destroy +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.El +.Sh SEE ALSO +.Xr pthread_barrier_init 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_cancel.3 b/lib/libpthread/pthread_cancel.3 new file mode 100644 index 000000000..b7de992c0 --- /dev/null +++ b/lib/libpthread/pthread_cancel.3 @@ -0,0 +1,134 @@ +.\" $NetBSD: pthread_cancel.3,v 1.6 2014/03/12 07:32:46 dholland Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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: src/lib/libpthread/man/pthread_cancel.3,v 1.7 2002/09/16 19:29:28 mini Exp $ +.Dd July 9, 2010 +.Dt PTHREAD_CANCEL 3 +.Os +.Sh NAME +.Nm pthread_cancel +.Nd cancel execution of a thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_cancel "pthread_t thread" +.Sh DESCRIPTION +The +.Fn pthread_cancel +function requests that +.Fa thread +be canceled. +The target thread's cancelability state and type determines +whether and when the target thread reacts to the cancellation request. +.Bl -enum -offset 2n +.It +The cancelability +.Em state +of a thread is determined by the +.Xr pthread_setcancelstate 3 +function. +The state can be either: +.Bl -bullet -offset 2n +.It +.Dv PTHREAD_CANCEL_ENABLE : +the cancelability type determines when the actual cancellation occurs. +This is the default. +.It +.Dv PTHREAD_CANCEL_DISABLE : +the request from +.Fn pthread_cancel +remains queued until the cancellation is enabled by the thread. +.El +.It +The cancellation +.Em type +of a thread is determined by the +.Xr pthread_setcanceltype 3 +function. +The type can be either: +.Bl -bullet -offset 2n +.It +.Dv PTHREAD_CANCEL_DEFERRED : +the cancellation will be delayed until the thread calls +a function that is a cancellation point. +This is the default. +The available cancellation points are listed in +.Xr pthread_setcanceltype 3 . +.It +.Dv PTHREAD_CANCEL_ASYNCHRONOUS : +the thread can be canceled at any time. +.El +.El +.Pp +When the thread reacts to the cancellation request, the following occur: +.Bl -enum -offset 2n +.It +The cancellation cleanup handlers for the thread are called; see +.Xr pthread_cleanup_push 3 . +.It +When the last cancellation cleanup handler returns, +the thread-specific data destructor functions will be called for the thread. +.It +When the last destructor function returns, the thread will be terminated; see +.Xr pthread_exit 3 . +.El +.Pp +The cancellation processing in the target thread runs asynchronously with +respect to the calling thread returning from +.Fn pthread_cancel . +.Pp +A status of +.Dv PTHREAD_CANCELED +is made available to any threads joining with the target. +The symbolic +constant +.Dv PTHREAD_CANCELED +expands to a constant expression of type +.Ft (void *) , +whose value matches no pointer to an object in memory nor the value +.Dv NULL . +.Sh RETURN VALUES +If successful, the +.Fn pthread_cancel +functions will return zero. +Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +The +.Fn pthread_cancel +function may fail if: +.Bl -tag -width Er +.It Bq Er ESRCH +No thread could be found corresponding to that specified by the given +thread ID. +.El +.Sh SEE ALSO +.Xr pthread_cleanup_pop 3 , +.Xr pthread_join 3 , +.Xr pthread_testcancel 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_cancelstub.c b/lib/libpthread/pthread_cancelstub.c new file mode 100644 index 000000000..369ab39dd --- /dev/null +++ b/lib/libpthread/pthread_cancelstub.c @@ -0,0 +1,641 @@ +/* $NetBSD: pthread_cancelstub.c,v 1.38 2013/03/21 16:49:12 christos Exp $ */ + +/*- + * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* Disable namespace mangling, Fortification is useless here anyway. */ +#undef _FORTIFY_SOURCE + +#include +__RCSID("$NetBSD: pthread_cancelstub.c,v 1.38 2013/03/21 16:49:12 christos Exp $"); + +#ifndef lint + + +/* + * This is necessary because the names are always weak (they are not + * POSIX functions). + */ +#define fsync_range _fsync_range +#define pollts _pollts + +/* + * XXX this is necessary to get the prototypes for the __sigsuspend14 + * XXX and __msync13 internal names, instead of the application-visible + * XXX sigsuspend and msync names. It's kind of gross, but we're pretty + * XXX intimate with libc already. + */ +#define __LIBC12_SOURCE__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +int pthread__cancel_stub_binder; + +int _sys_accept(int, struct sockaddr *, socklen_t *); +int _sys___aio_suspend50(const struct aiocb * const [], int, + const struct timespec *); +int __aio_suspend50(const struct aiocb * const [], int, + const struct timespec *); +int _sys_close(int); +int _sys_connect(int, const struct sockaddr *, socklen_t); +int _sys_fcntl(int, int, ...); +int _sys_fdatasync(int); +int _sys_fsync(int); +int _sys_fsync_range(int, int, off_t, off_t); +int _sys___kevent50(int, const struct kevent *, size_t, struct kevent *, + size_t, const struct timespec *); +int _sys_mq_send(mqd_t, const char *, size_t, unsigned); +ssize_t _sys_mq_receive(mqd_t, char *, size_t, unsigned *); +int _sys___mq_timedsend50(mqd_t, const char *, size_t, unsigned, + const struct timespec *); +ssize_t _sys___mq_timedreceive50(mqd_t, char *, size_t, unsigned *, + const struct timespec *); +ssize_t _sys_msgrcv(int, void *, size_t, long, int); +int _sys_msgsnd(int, const void *, size_t, int); +int _sys___msync13(void *, size_t, int); +int _sys___nanosleep50(const struct timespec *, struct timespec *); +int __nanosleep50(const struct timespec *, struct timespec *); +int _sys_open(const char *, int, ...); +int _sys_poll(struct pollfd *, nfds_t, int); +int _sys___pollts50(struct pollfd *, nfds_t, const struct timespec *, + const sigset_t *); +ssize_t _sys_pread(int, void *, size_t, off_t); +int _sys___pselect50(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const sigset_t *); +ssize_t _sys_pwrite(int, const void *, size_t, off_t); +ssize_t _sys_read(int, void *, size_t); +ssize_t _sys_readv(int, const struct iovec *, int); +int _sys___select50(int, fd_set *, fd_set *, fd_set *, struct timeval *); +int _sys___wait450(pid_t, int *, int, struct rusage *); +ssize_t _sys_write(int, const void *, size_t); +ssize_t _sys_writev(int, const struct iovec *, int); +int _sys___sigsuspend14(const sigset_t *); +int ____sigtimedwait50(const sigset_t * __restrict, siginfo_t * __restrict, + struct timespec * __restrict); +int __sigsuspend14(const sigset_t *); + +#define TESTCANCEL(id) do { \ + if (__predict_true(!__uselibcstub) && \ + __predict_false((id)->pt_cancel)) \ + pthread__cancelled(); \ + } while (/*CONSTCOND*/0) + + +int +accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_accept(s, addr, addrlen); + TESTCANCEL(self); + + return retval; +} + +int +__aio_suspend50(const struct aiocb * const list[], int nent, + const struct timespec *timeout) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___aio_suspend50(list, nent, timeout); + TESTCANCEL(self); + + return retval; +} + +int +__kevent50(int fd, const struct kevent *ev, size_t nev, struct kevent *rev, + size_t nrev, const struct timespec *ts) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___kevent50(fd, ev, nev, rev, nrev, ts); + TESTCANCEL(self); + + return retval; +} + +int +close(int d) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_close(d); + TESTCANCEL(self); + + return retval; +} + +int +connect(int s, const struct sockaddr *addr, socklen_t namelen) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_connect(s, addr, namelen); + TESTCANCEL(self); + + return retval; +} + +int +fcntl(int fd, int cmd, ...) +{ + int retval; + pthread_t self; + va_list ap; + + self = pthread__self(); + TESTCANCEL(self); + va_start(ap, cmd); + retval = _sys_fcntl(fd, cmd, va_arg(ap, void *)); + va_end(ap); + TESTCANCEL(self); + + return retval; +} + +int +fdatasync(int d) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_fdatasync(d); + TESTCANCEL(self); + + return retval; +} + +int +fsync(int d) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_fsync(d); + TESTCANCEL(self); + + return retval; +} + +int +fsync_range(int d, int f, off_t s, off_t e) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_fsync_range(d, f, s, e); + TESTCANCEL(self); + + return retval; +} + +int +mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_mq_send(mqdes, msg_ptr, msg_len, msg_prio); + TESTCANCEL(self); + + return retval; +} + +ssize_t +mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_mq_receive(mqdes, msg_ptr, msg_len, msg_prio); + TESTCANCEL(self); + + return retval; +} + +int +__mq_timedsend50(mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned msg_prio, const struct timespec *abst) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___mq_timedsend50(mqdes, msg_ptr, msg_len, msg_prio, abst); + TESTCANCEL(self); + + return retval; +} + +ssize_t +__mq_timedreceive50(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio, + const struct timespec *abst) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___mq_timedreceive50(mqdes, msg_ptr, msg_len, msg_prio, abst); + TESTCANCEL(self); + + return retval; +} + +ssize_t +msgrcv(int msgid, void *msgp, size_t msgsz, long msgtyp, int msgflg) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_msgrcv(msgid, msgp, msgsz, msgtyp, msgflg); + TESTCANCEL(self); + + return retval; +} + +int +msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_msgsnd(msgid, msgp, msgsz, msgflg); + TESTCANCEL(self); + + return retval; +} + +int +__msync13(void *addr, size_t len, int flags) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___msync13(addr, len, flags); + TESTCANCEL(self); + + return retval; +} + +int +open(const char *path, int flags, ...) +{ + int retval; + pthread_t self; + va_list ap; + + self = pthread__self(); + TESTCANCEL(self); + va_start(ap, flags); + retval = _sys_open(path, flags, va_arg(ap, mode_t)); + va_end(ap); + TESTCANCEL(self); + + return retval; +} + +int +__nanosleep50(const struct timespec *rqtp, struct timespec *rmtp) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + /* + * For now, just nanosleep. In the future, maybe pass a ucontext_t + * to _lwp_nanosleep() and allow it to recycle our kernel stack. + */ + retval = _sys___nanosleep50(rqtp, rmtp); + TESTCANCEL(self); + + return retval; +} + +int +poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_poll(fds, nfds, timeout); + TESTCANCEL(self); + + return retval; +} + +int +__pollts50(struct pollfd *fds, nfds_t nfds, const struct timespec *ts, + const sigset_t *sigmask) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___pollts50(fds, nfds, ts, sigmask); + TESTCANCEL(self); + + return retval; +} + +ssize_t +pread(int d, void *buf, size_t nbytes, off_t offset) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_pread(d, buf, nbytes, offset); + TESTCANCEL(self); + + return retval; +} + +int +__pselect50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___pselect50(nfds, readfds, writefds, exceptfds, timeout, + sigmask); + TESTCANCEL(self); + + return retval; +} + +ssize_t +pwrite(int d, const void *buf, size_t nbytes, off_t offset) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_pwrite(d, buf, nbytes, offset); + TESTCANCEL(self); + + return retval; +} + +ssize_t +read(int d, void *buf, size_t nbytes) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_read(d, buf, nbytes); + TESTCANCEL(self); + + return retval; +} + +ssize_t +readv(int d, const struct iovec *iov, int iovcnt) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_readv(d, iov, iovcnt); + TESTCANCEL(self); + + return retval; +} + +int +__select50(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + int retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___select50(nfds, readfds, writefds, exceptfds, timeout); + TESTCANCEL(self); + + return retval; +} + +pid_t +__wait450(pid_t wpid, int *status, int options, struct rusage *rusage) +{ + pid_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___wait450(wpid, status, options, rusage); + TESTCANCEL(self); + + return retval; +} + +ssize_t +write(int d, const void *buf, size_t nbytes) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_write(d, buf, nbytes); + TESTCANCEL(self); + + return retval; +} + +ssize_t +writev(int d, const struct iovec *iov, int iovcnt) +{ + ssize_t retval; + pthread_t self; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys_writev(d, iov, iovcnt); + TESTCANCEL(self); + + return retval; +} + +int +__sigsuspend14(const sigset_t *sigmask) +{ + pthread_t self; + int retval; + + self = pthread__self(); + TESTCANCEL(self); + retval = _sys___sigsuspend14(sigmask); + TESTCANCEL(self); + + return retval; +} + +int +__sigtimedwait50(const sigset_t * __restrict set, siginfo_t * __restrict info, + const struct timespec * __restrict timeout) +{ + pthread_t self; + int retval; + struct timespec tout, *tp; + + if (timeout) { + tout = *timeout; + tp = &tout; + } else + tp = NULL; + + self = pthread__self(); + TESTCANCEL(self); + retval = ____sigtimedwait50(set, info, tp); + TESTCANCEL(self); + + return retval; +} + +int +sigwait(const sigset_t * __restrict set, int * __restrict sig) +{ + pthread_t self; + int saved_errno; + int new_errno; + int retval; + + self = pthread__self(); + saved_errno = errno; + TESTCANCEL(self); + retval = ____sigtimedwait50(set, NULL, NULL); + TESTCANCEL(self); + new_errno = errno; + errno = saved_errno; + if (retval < 0) { + return new_errno; + } + *sig = retval; + return 0; +} + +__strong_alias(_close, close) +__strong_alias(_fcntl, fcntl) +__strong_alias(_fdatasync, fdatasync) +__strong_alias(_fsync, fsync) +__weak_alias(fsync_range, _fsync_range) +__strong_alias(_mq_send, mq_send) +__strong_alias(_mq_receive, mq_receive) +__strong_alias(_msgrcv, msgrcv) +__strong_alias(_msgsnd, msgsnd) +__strong_alias(___msync13, __msync13) +__strong_alias(___nanosleep50, __nanosleep50) +__strong_alias(_open, open) +__strong_alias(_poll, poll) +__strong_alias(_pread, pread) +__strong_alias(_pwrite, pwrite) +__strong_alias(_read, read) +__strong_alias(_readv, readv) +__strong_alias(_sigwait, sigwait) +__strong_alias(_write, write) +__strong_alias(_writev, writev) + +#endif /* !lint */ diff --git a/lib/libpthread/pthread_cleanup_push.3 b/lib/libpthread/pthread_cleanup_push.3 new file mode 100644 index 000000000..d38f841fd --- /dev/null +++ b/lib/libpthread/pthread_cleanup_push.3 @@ -0,0 +1,118 @@ +.\" $NetBSD: pthread_cleanup_push.3,v 1.6 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" Copyright (c) 1997 Brian Cully +.\" 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 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: src/lib/libpthread/man/pthread_cleanup_push.3,v 1.11 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_CLEANUP 3 +.Os +.Sh NAME +.Nm pthread_cleanup_push , +.Nm pthread_cleanup_pop +.Nd add and remove cleanup functions for thread exit +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft void +.Fn pthread_cleanup_push "void \*[lp]*cleanup_routine\*[rp]\*[lp]void *\*[rp]" "void *arg" +.Ft void +.Fn pthread_cleanup_pop "int execute" +.Sh DESCRIPTION +The +.Fn pthread_cleanup_push +function adds +.Fa cleanup_routine +to the top of the stack of cleanup handlers that +get called when the current thread exits. +.Pp +The +.Fn pthread_cleanup_pop +function pops the top cleanup routine off of the current threads cleanup +routine stack, and, if +.Fa execute +is non-zero, it will execute the function. +.Pp +When +.Fa cleanup_routine +is called, it is passed +.Fa arg +as its only argument. +.Pp +These functions may be implemented as macros which contain scope delimiters; +therefore, there must be a matching +.Fn pthread_cleanup_pop +for every +.Fn pthread_cleanup_push +at the same level of lexical scoping. +.Pp +The effect of calling +.Fn longjmp +or +.Fn siglongjmp +is undefined after a call to +.Fn pthread_cleanup_push +but before the matching call to +.Fn pthread_cleanup_pop +after the jump buffer was filled. +.Sh RETURN VALUES +Neither +.Fn pthread_cleanup_push +nor +.Fn pthread_cleanup_pop +returns a value. +.Sh ERRORS +None. +.Sh SEE ALSO +.Xr pthread_exit 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_compat.c b/lib/libpthread/pthread_compat.c new file mode 100644 index 000000000..97a4bc0ef --- /dev/null +++ b/lib/libpthread/pthread_compat.c @@ -0,0 +1,208 @@ +/* $NetBSD: pthread_compat.c,v 1.3 2014/01/31 20:44:01 christos Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software developed for The NetBSD Foundation + * by Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * libc symbols that are not present before NetBSD 5.0. + */ + +#include +__RCSID("$NetBSD: pthread_compat.c,v 1.3 2014/01/31 20:44:01 christos Exp $"); + +#include +#include +#include + +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" + +static void __pthread_init(void) __attribute__((__constructor__, __used__)); + +void __libc_thr_init(void); +void __libc_atomic_init(void); + +int _sys_sched_yield(void); +int _sys_aio_suspend(const struct aiocb * const[], int, + const struct timespec *); +int _sys_mq_send(mqd_t, const char *, size_t, unsigned); +ssize_t _sys_mq_receive(mqd_t, char *, size_t, unsigned *); +int _sys_mq_timedsend(mqd_t, const char *, size_t, unsigned, + const struct timespec *); +ssize_t _sys_mq_timedreceive(mqd_t, char *, size_t, unsigned *, + const struct timespec *); + +static void +__pthread_init(void) +{ + + __libc_atomic_init(); + __libc_thr_init(); +} + +int +_lwp_kill(lwpid_t a, int b) +{ + + return syscall(SYS__lwp_kill, a, b); +} + +int +_lwp_detach(lwpid_t a) +{ + + return syscall(SYS__lwp_detach, a); +} + +int +_lwp_park(clockid_t a, int b, const struct timespec *c, lwpid_t d, + const void *e, const void *f) +{ + + return syscall(SYS____lwp_park60, a, b, c, d, e, f); +} + +int +_lwp_unpark(lwpid_t a, const void *b) +{ + + return syscall(SYS__lwp_unpark, a, b); +} + +ssize_t +_lwp_unpark_all(const lwpid_t *a, size_t b, const void *c) +{ + + return (ssize_t)syscall(SYS__lwp_unpark_all, a, b, c); +} + +int +_lwp_setname(lwpid_t a, const char *b) +{ + + return syscall(SYS__lwp_setname, a, b); +} + +int +_lwp_getname(lwpid_t a, char *b, size_t c) +{ + + return syscall(SYS__lwp_getname, a, b, c); +} + +int +_lwp_ctl(int a, struct lwpctl **b) +{ + + return syscall(SYS__lwp_ctl, a, b); +} + +int +_sys_sched_yield(void) +{ + + return syscall(SYS_sched_yield); +} + +int +sched_yield(void) +{ + + return syscall(SYS_sched_yield); +} + +int +_sched_setaffinity(pid_t a, lwpid_t b, size_t c, const cpuset_t *d) +{ + + return syscall(SYS__sched_setaffinity, a, b, c, d); +} + +int +_sched_getaffinity(pid_t a, lwpid_t b, size_t c, cpuset_t *d) +{ + + return syscall(SYS__sched_getaffinity, a, b, c, d); +} + +int +_sched_setparam(pid_t a, lwpid_t b, int c, const struct sched_param *d) +{ + + return syscall(SYS__sched_setparam, a, b, c, d); +} + +int +_sched_getparam(pid_t a, lwpid_t b, int *c, struct sched_param *d) +{ + + return syscall(SYS__sched_getparam, a, b, c, d); +} + +int +_sys_aio_suspend(const struct aiocb * const a[], int b, + const struct timespec *c) +{ + + return syscall(SYS_aio_suspend, a, b, c); +} + +int +_sys_mq_send(mqd_t a, const char *b, size_t c, unsigned d) +{ + + return syscall(SYS_mq_send, a, b, c, d); +} + +ssize_t +_sys_mq_receive(mqd_t a, char *b, size_t c, unsigned *d) +{ + + return (ssize_t)syscall(SYS_mq_receive, a, b, c, d); +} + +int +_sys_mq_timedsend(mqd_t a, const char *b, size_t c, unsigned d, + const struct timespec *e) +{ + + return syscall(SYS_mq_timedsend, a, b,c ,d, e); +} + +ssize_t +_sys_mq_timedreceive(mqd_t a, char *b, size_t c, unsigned *d, + const struct timespec *e) +{ + + return (ssize_t)syscall(SYS_mq_timedreceive, a, b, c, d, e); +} diff --git a/lib/libpthread/pthread_cond.3 b/lib/libpthread/pthread_cond.3 new file mode 100644 index 000000000..c1321a66a --- /dev/null +++ b/lib/libpthread/pthread_cond.3 @@ -0,0 +1,275 @@ +.\" $NetBSD: pthread_cond.3,v 1.6 2012/11/12 23:11:05 uwe Exp $ +.\" +.\" Copyright (c) 2002, 2008 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" Copyright (c) 1997 Brian Cully +.\" 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 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. +.\" +.\" ---------------------------------------------------------------------------- +.Dd July 8, 2010 +.Dt PTHREAD_COND 3 +.Os +.Sh NAME +.Nm pthread_cond +.Nd condition variable interface +.Sh LIBRARY +.Lb libpthread +.\" ---------------------------------------------------------------------------- +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_cond_init "pthread_cond_t * restrict cond" \ +"const pthread_condattr_t * restrict attr" +.Vt pthread_cond_t cond No = Dv PTHREAD_COND_INITIALIZER; +.Ft int +.Fn pthread_cond_destroy "pthread_cond_t *cond" +.Ft int +.Fn pthread_cond_broadcast "pthread_cond_t *cond" +.Ft int +.Fn pthread_cond_signal "pthread_cond_t *cond" +.Ft int +.Fn pthread_cond_wait "pthread_cond_t * restrict cond" \ +"pthread_mutex_t * restrict mutex" +.Ft int +.Fn pthread_cond_timedwait "pthread_cond_t * restrict cond" \ +"pthread_mutex_t * restrict mutex" "const struct timespec * restrict abstime" +.\" ---------------------------------------------------------------------------- +.Sh DESCRIPTION +Condition variables are intended to be used to communicate changes in +the state of data shared between threads. +Condition variables are always associated with a mutex to provide +synchronized access to the shared data. +A single predicate should always be associated with a +condition variable. +The predicate should identify a state of the +shared data that must be true before the thread proceeds. +.Pp +The +.Fn pthread_cond_init +function creates a new condition variable, with attributes specified with +.Fa attr . +If +.Fa attr +is +.Dv NULL +the default attributes are used. +The +.Fn pthread_cond_destroy +function frees the resources allocated by the condition variable +.Fa cond . +.Pp +The macro +.Dv PTHREAD_COND_INITIALIZER +can be used to initialize a condition variable when it can be statically +allocated and the default attributes are appropriate. +The effect is similar to calling +.Fn pthread_cond_init +with +.Fa attr +specified as +.Dv NULL , +except that no error checking is done. +.Pp +.\" ----- +The difference between +.Fn pthread_cond_broadcast +and +.Fn pthread_cond_signal +is that the former unblocks all threads waiting for the condition variable, +whereas the latter blocks only one waiting thread. +If no threads are waiting on +.Fa cond , +neither function has any effect. +If more than one thread is blocked on a condition variable, +the used scheduling policy determines the order in which threads are unblocked. +The same mutex used for waiting must be held while calling either function. +Although neither function strictly enforces this requirement, +undefined behavior may follow if the mutex is not held. +.Pp +.\" ----- +The +.Fn pthread_cond_wait +function atomically blocks the current thread waiting on the condition +variable specified by +.Fa cond , +and unlocks the mutex specified by +.Fa mutex . +The +.Fn pthread_cond_timedwait +function behaves similarly, but unblocks also +if the system time reaches the time specified in +.Fa abstime , +represented as +.Em struct timespec +(see +.Xr timespec 3 ) . +With both functions the waiting thread unblocks after another thread calls +.Fn pthread_cond_signal +or +.Fn pthread_cond_broadcast +with the same condition variable and by holding the same +.Fa mutex +that was associated with +.Fa cond +by either one of the blocking functions. +The current thread holds the lock on +.Fa mutex +upon return from either function. +.\" ----- +.Pp +Note that a call to +.Fn pthread_cond_wait +or +.Fn pthread_cond_timedwait +may wake up spontaneously, without a call to +.Fn pthread_cond_signal +or +.Fn pthread_cond_broadcast . +The caller should prepare for this by invoking either function +within a predicate loop that tests whether the thread should proceed. +.Pp +.\" ----- +As noted, when calling either function that waits on a condition variable, +a temporary binding is established between the condition variable +.Fa cond +and the mutex +.Fa mutex . +During this time, the effect of an attempt by any thread to wait on +that condition variable using a different mutex is undefined. +The same mutex must be held while broadcasting or signaling on +.Fa cond . +Additionally, the same mutex must be used for concurrent calls to +.Fn pthread_cond_wait +and +.Fn pthread_cond_timedwait . +Only when a condition variable is known to be quiescent may an application +change the mutex associated with it. +In this implementation, none of the functions enforce this requirement, but +if the mutex is not held or independent mutexes are used the resulting +behaviour is undefined. +.\" ---------------------------------------------------------------------------- +.Sh RETURN VALUES +If successful, all functions return zero. +Otherwise, an error number will be returned to indicate the error. +.Sh ERRORS +The +.Fn pthread_cond_init +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_cond_destroy +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The variable +.Fa cond +is locked by another thread. +.It Bq Er EINVAL +The value specified by +.Fa cond +is invalid. +.El +.Pp +.\" ----- +Both +.Fn pthread_cond_broadcast +and +.Fn pthread_cond_signal +may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +is invalid. +.El +.Pp +.\" ----- +Both +.Fn pthread_cond_wait +and +.Fn pthread_cond_timedwait +may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa cond +or the value specified by +.Fa mutex +is invalid. +.It Bq Er EPERM +The value specified by +.Fa mutex +was not locked in the condition wait. +.El +.Pp +The +.Fn pthread_cond_timedwait +function may additionally fail if: +.Bl -tag -width Er +.It Bq Er ETIMEDOUT +The system time has reached or exceeded the time specified in +.Fa abstime . +.El +.Sh SEE ALSO +.Xr pthread 3 , +.Xr pthread_barrier 3 , +.Xr pthread_condattr 3 , +.Xr pthread_mutex 3 , +.Xr pthread_rwlock 3 , +.Xr pthread_spin 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_cond.c b/lib/libpthread/pthread_cond.c new file mode 100644 index 000000000..4be884a13 --- /dev/null +++ b/lib/libpthread/pthread_cond.c @@ -0,0 +1,418 @@ +/* $NetBSD: pthread_cond.c,v 1.63 2014/01/31 20:44:01 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * We assume that there will be no contention on pthread_cond_t::ptc_lock + * because functioning applications must call both the wait and wakeup + * functions while holding the same application provided mutex. The + * spinlock is present only to prevent libpthread causing the application + * to crash or malfunction as a result of corrupted data structures, in + * the event that the application is buggy. + * + * If there is contention on spinlock when real-time threads are in use, + * it could cause a deadlock due to priority inversion: the thread holding + * the spinlock may not get CPU time to make forward progress and release + * the spinlock to a higher priority thread that is waiting for it. + * Contention on the spinlock will only occur with buggy applications, + * so at the time of writing it's not considered a major bug in libpthread. + */ + +#include +__RCSID("$NetBSD: pthread_cond.c,v 1.63 2014/01/31 20:44:01 christos Exp $"); + +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +int _sys___nanosleep50(const struct timespec *, struct timespec *); + +extern int pthread__started; + +static int pthread_cond_wait_nothread(pthread_t, pthread_mutex_t *, + pthread_cond_t *, const struct timespec *); + +int _pthread_cond_has_waiters_np(pthread_cond_t *); + +__weak_alias(pthread_cond_has_waiters_np,_pthread_cond_has_waiters_np) + +__strong_alias(__libc_cond_init,pthread_cond_init) +__strong_alias(__libc_cond_signal,pthread_cond_signal) +__strong_alias(__libc_cond_broadcast,pthread_cond_broadcast) +__strong_alias(__libc_cond_wait,pthread_cond_wait) +__strong_alias(__libc_cond_timedwait,pthread_cond_timedwait) +__strong_alias(__libc_cond_destroy,pthread_cond_destroy) + +static clockid_t +pthread_cond_getclock(const pthread_cond_t *cond) +{ + return cond->ptc_private ? + *(clockid_t *)cond->ptc_private : CLOCK_REALTIME; +} + +int +pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) +{ + if (__predict_false(__uselibcstub)) + return __libc_cond_init_stub(cond, attr); + + pthread__error(EINVAL, "Invalid condition variable attribute", + (attr == NULL) || (attr->ptca_magic == _PT_CONDATTR_MAGIC)); + + cond->ptc_magic = _PT_COND_MAGIC; + pthread_lockinit(&cond->ptc_lock); + PTQ_INIT(&cond->ptc_waiters); + cond->ptc_mutex = NULL; + if (attr && attr->ptca_private) { + cond->ptc_private = malloc(sizeof(clockid_t)); + if (cond->ptc_private == NULL) + return errno; + *(clockid_t *)cond->ptc_private = + *(clockid_t *)attr->ptca_private; + } else + cond->ptc_private = NULL; + + return 0; +} + + +int +pthread_cond_destroy(pthread_cond_t *cond) +{ + if (__predict_false(__uselibcstub)) + return __libc_cond_destroy_stub(cond); + + pthread__error(EINVAL, "Invalid condition variable", + cond->ptc_magic == _PT_COND_MAGIC); + pthread__error(EBUSY, "Destroying condition variable in use", + cond->ptc_mutex == NULL); + + cond->ptc_magic = _PT_COND_DEAD; + free(cond->ptc_private); + + return 0; +} + +int +pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + pthread_t self; + int retval; + clockid_t clkid = pthread_cond_getclock(cond); + + if (__predict_false(__uselibcstub)) + return __libc_cond_timedwait_stub(cond, mutex, abstime); + + pthread__error(EINVAL, "Invalid condition variable", + cond->ptc_magic == _PT_COND_MAGIC); + pthread__error(EINVAL, "Invalid mutex", + mutex->ptm_magic == _PT_MUTEX_MAGIC); + pthread__error(EPERM, "Mutex not locked in condition wait", + mutex->ptm_owner != NULL); + + self = pthread__self(); + + /* Just hang out for a while if threads aren't running yet. */ + if (__predict_false(pthread__started == 0)) { + return pthread_cond_wait_nothread(self, mutex, cond, abstime); + } + if (__predict_false(self->pt_cancel)) { + pthread__cancelled(); + } + + /* Note this thread as waiting on the CV. */ + pthread__spinlock(self, &cond->ptc_lock); + cond->ptc_mutex = mutex; + PTQ_INSERT_HEAD(&cond->ptc_waiters, self, pt_sleep); + self->pt_sleepobj = cond; + pthread__spinunlock(self, &cond->ptc_lock); + + do { + self->pt_willpark = 1; + pthread_mutex_unlock(mutex); + self->pt_willpark = 0; + self->pt_blocking++; + do { + retval = _lwp_park(clkid, TIMER_ABSTIME, abstime, + self->pt_unpark, __UNVOLATILE(&mutex->ptm_waiters), + __UNVOLATILE(&mutex->ptm_waiters)); + self->pt_unpark = 0; + } while (retval == -1 && errno == ESRCH); + self->pt_blocking--; + membar_sync(); + pthread_mutex_lock(mutex); + + /* + * If we have cancelled then exit. POSIX dictates that + * the mutex must be held when we action the cancellation. + * + * If we absorbed a pthread_cond_signal() and cannot take + * the wakeup, we must ensure that another thread does. + * + * If awoke early, we may still be on the sleep queue and + * must remove ourself. + */ + if (__predict_false(retval != 0)) { + switch (errno) { + case EINTR: + case EALREADY: + retval = 0; + break; + default: + retval = errno; + break; + } + } + if (__predict_false(self->pt_cancel | retval)) { + pthread_cond_signal(cond); + if (self->pt_cancel) { + pthread__cancelled(); + } + break; + } + } while (self->pt_sleepobj != NULL); + + return retval; +} + +int +pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + if (__predict_false(__uselibcstub)) + return __libc_cond_wait_stub(cond, mutex); + + return pthread_cond_timedwait(cond, mutex, NULL); +} + +static int __noinline +pthread__cond_wake_one(pthread_cond_t *cond) +{ + pthread_t self, signaled; + pthread_mutex_t *mutex; + lwpid_t lid; + + pthread__error(EINVAL, "Invalid condition variable", + cond->ptc_magic == _PT_COND_MAGIC); + + /* + * Pull the first thread off the queue. If the current thread + * is associated with the condition variable, remove it without + * awakening (error case in pthread_cond_timedwait()). + */ + self = pthread__self(); + pthread__spinlock(self, &cond->ptc_lock); + if (self->pt_sleepobj == cond) { + PTQ_REMOVE(&cond->ptc_waiters, self, pt_sleep); + self->pt_sleepobj = NULL; + } + signaled = PTQ_FIRST(&cond->ptc_waiters); + if (__predict_false(signaled == NULL)) { + cond->ptc_mutex = NULL; + pthread__spinunlock(self, &cond->ptc_lock); + return 0; + } + mutex = cond->ptc_mutex; + if (PTQ_NEXT(signaled, pt_sleep) == NULL) { + cond->ptc_mutex = NULL; + PTQ_INIT(&cond->ptc_waiters); + } else { + PTQ_REMOVE(&cond->ptc_waiters, signaled, pt_sleep); + } + signaled->pt_sleepobj = NULL; + lid = signaled->pt_lid; + pthread__spinunlock(self, &cond->ptc_lock); + + /* + * For all valid uses of pthread_cond_signal(), the caller will + * hold the mutex that the target is using to synchronize with. + * To avoid the target awakening and immediately blocking on the + * mutex, transfer the thread to be awoken to the current thread's + * deferred wakeup list. The waiter will be set running when the + * caller (this thread) releases the mutex. + */ + if (__predict_false(self->pt_nwaiters == (size_t)pthread__unpark_max)) { + (void)_lwp_unpark_all(self->pt_waiters, self->pt_nwaiters, + __UNVOLATILE(&mutex->ptm_waiters)); + self->pt_nwaiters = 0; + } + self->pt_waiters[self->pt_nwaiters++] = lid; + pthread__mutex_deferwake(self, mutex); + return 0; +} + +int +pthread_cond_signal(pthread_cond_t *cond) +{ + + if (__predict_false(__uselibcstub)) + return __libc_cond_signal_stub(cond); + + if (__predict_true(PTQ_EMPTY(&cond->ptc_waiters))) + return 0; + return pthread__cond_wake_one(cond); +} + +static int __noinline +pthread__cond_wake_all(pthread_cond_t *cond) +{ + pthread_t self, signaled; + pthread_mutex_t *mutex; + u_int max; + size_t nwaiters; + + pthread__error(EINVAL, "Invalid condition variable", + cond->ptc_magic == _PT_COND_MAGIC); + + /* + * Try to defer waking threads (see pthread_cond_signal()). + * Only transfer waiters for which there is no pending wakeup. + */ + self = pthread__self(); + pthread__spinlock(self, &cond->ptc_lock); + max = pthread__unpark_max; + mutex = cond->ptc_mutex; + nwaiters = self->pt_nwaiters; + PTQ_FOREACH(signaled, &cond->ptc_waiters, pt_sleep) { + if (__predict_false(nwaiters == max)) { + /* Overflow. */ + (void)_lwp_unpark_all(self->pt_waiters, + nwaiters, __UNVOLATILE(&mutex->ptm_waiters)); + nwaiters = 0; + } + signaled->pt_sleepobj = NULL; + self->pt_waiters[nwaiters++] = signaled->pt_lid; + } + PTQ_INIT(&cond->ptc_waiters); + self->pt_nwaiters = nwaiters; + cond->ptc_mutex = NULL; + pthread__spinunlock(self, &cond->ptc_lock); + pthread__mutex_deferwake(self, mutex); + + return 0; +} + +int +pthread_cond_broadcast(pthread_cond_t *cond) +{ + if (__predict_false(__uselibcstub)) + return __libc_cond_broadcast_stub(cond); + + if (__predict_true(PTQ_EMPTY(&cond->ptc_waiters))) + return 0; + return pthread__cond_wake_all(cond); +} + +int +_pthread_cond_has_waiters_np(pthread_cond_t *cond) +{ + + return !PTQ_EMPTY(&cond->ptc_waiters); +} + +int +pthread_condattr_init(pthread_condattr_t *attr) +{ + + attr->ptca_magic = _PT_CONDATTR_MAGIC; + attr->ptca_private = NULL; + + return 0; +} + +int +pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clck) +{ + switch (clck) { + case CLOCK_MONOTONIC: + case CLOCK_REALTIME: + if (attr->ptca_private == NULL) + attr->ptca_private = malloc(sizeof(clockid_t)); + if (attr->ptca_private == NULL) + return errno; + *(clockid_t *)attr->ptca_private = clck; + return 0; + default: + return EINVAL; + } +} + +int +pthread_condattr_destroy(pthread_condattr_t *attr) +{ + + pthread__error(EINVAL, "Invalid condition variable attribute", + attr->ptca_magic == _PT_CONDATTR_MAGIC); + + attr->ptca_magic = _PT_CONDATTR_DEAD; + free(attr->ptca_private); + + return 0; +} + +/* Utility routine to hang out for a while if threads haven't started yet. */ +static int +pthread_cond_wait_nothread(pthread_t self, pthread_mutex_t *mutex, + pthread_cond_t *cond, const struct timespec *abstime) +{ + struct timespec now, diff; + int retval; + + if (abstime == NULL) { + diff.tv_sec = 99999999; + diff.tv_nsec = 0; + } else { + clockid_t clck = pthread_cond_getclock(cond); + clock_gettime(clck, &now); + if (timespeccmp(abstime, &now, <)) + timespecclear(&diff); + else + timespecsub(abstime, &now, &diff); + } + + do { + pthread__testcancel(self); + pthread_mutex_unlock(mutex); + retval = _sys___nanosleep50(&diff, NULL); + pthread_mutex_lock(mutex); + } while (abstime == NULL && retval == 0); + pthread__testcancel(self); + + if (retval == 0) + return ETIMEDOUT; + else + /* spurious wakeup */ + return 0; +} diff --git a/lib/libpthread/pthread_condattr.3 b/lib/libpthread/pthread_condattr.3 new file mode 100644 index 000000000..6816c4296 --- /dev/null +++ b/lib/libpthread/pthread_condattr.3 @@ -0,0 +1,117 @@ +.\" $NetBSD: pthread_condattr.3,v 1.9 2012/11/03 09:20:36 wiz Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_condattr.3,v 1.10 2002/09/16 19:29:28 mini Exp $ +.Dd November 2, 2012 +.Dt PTHREAD_CONDATTR 3 +.Os +.Sh NAME +.Nm pthread_condattr_init +.Nd condition attribute operations +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_condattr_init "pthread_condattr_t *attr" +.Ft int +.Fn pthread_condattr_setclock "pthread_condattr_t *attr" "clockid_t clock" +.Ft int +.Fn pthread_condattr_destroy "pthread_condattr_t *attr" +.Sh DESCRIPTION +Condition attribute objects are used to specify parameters to the +.Xr pthread_cond_init 3 +function. +The +.Fn pthread_condattr_init +function initializes a condition attribute object with the default attributes +and the +.Fn pthread_condattr_destroy +function destroys a condition attribute object. +The +.Fn pthread_condattr_setclock +function sets the system clock to be used for time comparisons to +the one specified in +.Fa clock . +Valid clock values are +.Dv CLOCK_MONOTONIC +and +.Dv CLOCK_REALTIME +(the default). +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +No errors are defined for +.Fn pthread_condattr_init . +.Pp +The +.Fn pthread_condattr_destroy +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.El +.Sh SEE ALSO +.Xr pthread_cond_init 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2001 . +.Sh CAVEATS +The usefulness of the functions is questionable as the +.Nx +implementation does not support any non-default attributes. +These functions do not conform to the +.St -p1003.1-2008 +revision of the standard, which mandates two additional attributes, +the clock attribute and the process-shared attribute. diff --git a/lib/libpthread/pthread_create.3 b/lib/libpthread/pthread_create.3 new file mode 100644 index 000000000..b72344fc6 --- /dev/null +++ b/lib/libpthread/pthread_create.3 @@ -0,0 +1,157 @@ +.\" $NetBSD: pthread_create.3,v 1.7 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_create.3,v 1.16 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_CREATE 3 +.Os +.Sh NAME +.Nm pthread_create +.Nd create a new thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_create "pthread_t * restrict thread" "const pthread_attr_t * restrict attr" "void *(*start_routine)(void *)" "void * restrict arg" +.Sh DESCRIPTION +The +.Fn pthread_create +function is used to create a new thread, with attributes specified by +.Fa attr , +within a process. +If +.Fa attr +is +.Dv NULL , +the default attributes are used. +.Pp +The attributes specified via +.Fa attr +are copied into the new thread. +Any subsequent modifications to the attributes object +.Fa attr +points to will have no effect upon already-created threads. +It is thus also safe to pass the same +.Fa attr +to multiple calls to +.Fn pthread_create . +.Pp +Upon +successful completion +.Fn pthread_create +will store the ID of the created thread in the location specified by +.Fa thread . +The thread is created executing +.Fa start_routine +with +.Fa arg +as its sole argument. +.Pp +If the +.Fa start_routine +returns, the effect is as if there was an implicit call to +.Fn pthread_exit +using the return value of +.Fa start_routine +as the exit status. +Note that the thread in which +.Fn main +was originally invoked differs from this. +When it returns from +.Fn main , +the effect is as if there was an implicit call to +.Fn exit +using the return value of +.Fn main +as the exit status. +.Pp +The signal state of the new thread is initialized as: +.Bl -bullet -offset indent +.It +The signal mask is inherited from the creating thread. +.It +The set of signals pending for the new thread is empty. +.El +.Sh RETURN VALUES +If successful, the +.Fn pthread_create +function will return zero. +Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_create +shall fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The system lacks the necessary resources to create another thread, or +the system-imposed limit on the total number of threads in a process +.Dv PTHREAD_THREADS_MAX +would be exceeded. +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.El +.Sh SEE ALSO +.Xr fork 2 , +.Xr pthread_attr 3 , +.Xr pthread_cleanup_pop 3 , +.Xr pthread_cleanup_push 3 , +.Xr pthread_exit 3 , +.Xr pthread_join 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_curcpu_np.3 b/lib/libpthread/pthread_curcpu_np.3 new file mode 100644 index 000000000..6bf0ba408 --- /dev/null +++ b/lib/libpthread/pthread_curcpu_np.3 @@ -0,0 +1,66 @@ +.\" $NetBSD: pthread_curcpu_np.3,v 1.2 2011/11/10 16:44:47 wiz Exp $ +.\" +.\" Copyright (c)2011 YAMAMOTO Takashi, +.\" 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. +.\" +.\" ------------------------------------------------------------ +.Dd November 10, 2011 +.Dt PTHREAD_CURCPU_NP 3 +.Os +.\" ------------------------------------------------------------ +.Sh NAME +.Nm pthread_curcpu_np +.Nd get current CPU identifier +.\" ------------------------------------------------------------ +.Sh SYNOPSIS +.In pthread.h +.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +.Ft unsigned int +.Fn pthread_curcpu_np \ +"void" +.\" ------------------------------------------------------------ +.Sh DESCRIPTION +The +.Fn pthread_curcpu_np +function provides a way for a thread to know which CPU it's currently running +on. +.Pp +Note that, unless the thread is bound to a specific CPU, the result might be +already stale when the function returns. +However, it still can be useful as a hint to achieve better CPU locality. +.\" ------------------------------------------------------------ +.Sh RETURN VALUES +The +.Fn pthread_curcpu_np +function returns the integer identifier of the CPU which is currently +running the calling thread. +.\" ------------------------------------------------------------ +.Sh COMPATIBILITY +The +.Fn pthread_curcpu_np +function is a non-standard extension. +.\" ------------------------------------------------------------ +.Sh SEE ALSO +.Xr affinity 3 , +.Xr pthread 3 diff --git a/lib/libpthread/pthread_detach.3 b/lib/libpthread/pthread_detach.3 new file mode 100644 index 000000000..ea6172e0f --- /dev/null +++ b/lib/libpthread/pthread_detach.3 @@ -0,0 +1,108 @@ +.\" $NetBSD: pthread_detach.3,v 1.4 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" Copyright (c) 1996-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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_detach.3,v 1.13 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_DETACH 3 +.Os +.Sh NAME +.Nm pthread_detach +.Nd detach a thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_detach "pthread_t thread" +.Sh DESCRIPTION +The +.Fn pthread_detach +function is used to indicate to the implementation that storage for the +thread +.Fa thread +can be reclaimed when the thread terminates. +If +.Fa thread +has not terminated, +.Fn pthread_detach +will not cause it to terminate. +The effect of multiple +.Fn pthread_detach +calls on the same target thread is unspecified. +.Sh RETURN VALUES +If successful, the +.Fn pthread_detach +function will return zero. +Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_detach +shall fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa thread +does not refer to a joinable thread. +.It Bq Er ESRCH +No thread could be found corresponding to that specified by the given +thread ID, +.Fa thread . +.El +.Sh SEE ALSO +.Xr pthread_join 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_equal.3 b/lib/libpthread/pthread_equal.3 new file mode 100644 index 000000000..33e176631 --- /dev/null +++ b/lib/libpthread/pthread_equal.3 @@ -0,0 +1,92 @@ +.\" $NetBSD: pthread_equal.3,v 1.4 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_equal.3,v 1.11 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_EQUAL 3 +.Os +.Sh NAME +.Nm pthread_equal +.Nd compare thread IDs +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_equal "pthread_t t1" "pthread_t t2" +.Sh DESCRIPTION +The +.Fn pthread_equal +function compares the thread IDs +.Fa t1 +and +.Fa t2 . +.Sh RETURN VALUES +The +.Fn pthread_equal +function will return non-zero if the thread IDs +.Fa t1 +and +.Fa t2 +correspond to the same thread, otherwise it will return zero. +.Sh ERRORS +None. +.Sh SEE ALSO +.Xr pthread_create 3 , +.Xr pthread_exit 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_exit.3 b/lib/libpthread/pthread_exit.3 new file mode 100644 index 000000000..d82d6b340 --- /dev/null +++ b/lib/libpthread/pthread_exit.3 @@ -0,0 +1,129 @@ +.\" $NetBSD: pthread_exit.3,v 1.5 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_exit.3,v 1.16 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_EXIT 3 +.Os +.Sh NAME +.Nm pthread_exit +.Nd terminate the calling thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft void +.Fn pthread_exit "void *value_ptr" +.Sh DESCRIPTION +The +.Fn pthread_exit +function terminates the calling thread and makes the value +.Fa value_ptr +available to any successful join with the terminating thread. +Any +cancellation cleanup handlers that have been pushed and are not yet popped +are popped in the reverse order that they were pushed and then executed. +After all cancellation handlers have been executed, if the thread has any +thread-specific data, appropriate destructor functions are called in an +unspecified order. +Thread termination does not release any application +visible process resources, including, but not limited to, mutexes and +file descriptors, nor does it perform any process level cleanup +actions, including, but not limited to, calling +.Fn atexit +routines that may exist. +.Pp +An implicit call to +.Fn pthread_exit +is made when a thread other than the thread in which +.Fn main +was first invoked returns from the start routine that was used to create +it. +The function's return value serves as the thread's exit status. +.Pp +The behavior of +.Fn pthread_exit +is undefined if called from a cancellation handler or destructor function +that was invoked as the result of an implicit or explicit call to +.Fn pthread_exit . +.Pp +After a thread has terminated, the result of access to local (auto) +variables of the thread is undefined. +Thus, references to local variables +of the exiting thread should not be used for the +.Fn pthread_exit +.Fa value_ptr +parameter value. +.Pp +The process will exit with an exit status of 0 after the last thread has +been terminated. +The behavior is as if the implementation called +.Fn exit +with a zero argument at thread termination time. +.Sh RETURN VALUES +The +.Fn pthread_exit +function cannot return to its caller. +.Sh ERRORS +None. +.Sh SEE ALSO +.Xr _exit 2 , +.Xr exit 3 , +.Xr pthread_create 3 , +.Xr pthread_join 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_getname_np.3 b/lib/libpthread/pthread_getname_np.3 new file mode 100644 index 000000000..db228d997 --- /dev/null +++ b/lib/libpthread/pthread_getname_np.3 @@ -0,0 +1,107 @@ +.\" $NetBSD: pthread_getname_np.3,v 1.4 2010/07/09 07:31:01 jruoho Exp $ +.\" +.\" Copyright (c)2007 YAMAMOTO Takashi, +.\" 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. +.\" +.\" ------------------------------------------------------------ +.Dd July 9, 2010 +.Dt PTHREAD_GETNAME_NP 3 +.Os +.Sh NAME +.Nm pthread_getname_np +.Nd get and set descriptive name of a thread +.\" ------------------------------------------------------------ +.Sh LIBRARY +.Lb libpthread +.\" ------------------------------------------------------------ +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_getname_np "pthread_t thread" "char *name" "size_t len" +.Ft int +.Fn pthread_setname_np "pthread_t thread" "const char *name" "void *arg" +.\" ------------------------------------------------------------ +.Sh DESCRIPTION +The +.Fn pthread_getname_np +function obtains the descriptive name of a thread. +It takes the following arguments: +.Bl -tag -width target -offset indent +.It Fa thread +The thread whose descriptive name will be obtained. +.It Fa name +The buffer to be filled with the descriptive name of the thread. +.It Fa len +The size of the buffer +.Fa name +in bytes. +.El +.Pp +The +.Fn pthread_setname_np +function sets the descriptive name of a thread. +It takes the following arguments: +.Bl -tag -width target -offset indent +.It Fa thread +The thread whose descriptive name will be set. +.It Fa name +The +.Xr printf 3 +format string to be used to construct the descriptive name of the thread. +The resulted descriptive name should be shorter than +.Dv PTHREAD_MAX_NAMELEN_NP . +.It Fa arg +The +.Xr printf 3 +argument used with +.Fa name . +.El +.\" ------------------------------------------------------------ +.Sh RETURN VALUES +Both functions return 0 on success. +Otherwise, an error number is returned to indicate the error. +.\" ------------------------------------------------------------ +.Sh COMPATIBILITY +Both functions are non-standard extensions. +.\" ------------------------------------------------------------ +.Sh ERRORS +Both functions may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +Invalid parameter. +.It Bq Er ESRCH +Non-existent +.Fa thread . +.El +.Pp +The +.Fn pthread_setname_np +function may also fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +There was insufficient memory for the operation. +.El +.Sh SEE ALSO +.Xr pthread_attr_get_np 3 , +.Xr pthread_attr_getname_np 3 diff --git a/lib/libpthread/pthread_getspecific.3 b/lib/libpthread/pthread_getspecific.3 new file mode 100644 index 000000000..09d5f80cc --- /dev/null +++ b/lib/libpthread/pthread_getspecific.3 @@ -0,0 +1,123 @@ +.\" $NetBSD: pthread_getspecific.3,v 1.5 2010/07/09 10:49:48 wiz Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_getspecific.3,v 1.11 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_GETSPECIFIC 3 +.Os +.Sh NAME +.Nm pthread_getspecific +.Nd thread-specific data value +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft void * +.Fn pthread_getspecific "pthread_key_t key" +.Ft int +.Fn pthread_setspecific "pthread_key_t key" "const void *value" +.Sh DESCRIPTION +The +.Fn pthread_getspecific +function returns the value currently bound to the specified +.Fa key +on behalf of the calling thread. +Conversely, the +.Fn pthread_setspecific +function associates a thread-specific value with a +.Fa key +obtained via a previous call to +.Xr pthread_key_create 3 . +Different threads have different values bound to each key. +These values are typically pointers to blocks of dynamically +allocated memory that have been reserved for use by the calling thread. +.Pp +Undefined behavior may follow if either function is called with a +.Fa key +value not obtained from +.Xr pthread_key_create 3 , +or if the call is made after +.Fa key +has been deleted with +.Xr pthread_key_delete 3 . +It is possible to call either function from +a thread-specific data destructor function. +Note however that this is not well defined for the +.Fn pthread_setspecific +function; +lost storage or infinite loops may occur. +.Sh RETURN VALUES +The +.Fn pthread_getspecific +function will return the thread-specific data value associated with the given +.Fa key . +If no thread-specific data value is associated with +.Fa key , +then the value +.Dv NULL +is returned. +If successful, the +.Fn pthread_setspecific +function will return zero. +Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +No errors are defined for either function. +.Sh SEE ALSO +.Xr pthread_key_create 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_int.h b/lib/libpthread/pthread_int.h new file mode 100644 index 000000000..b3463ee59 --- /dev/null +++ b/lib/libpthread/pthread_int.h @@ -0,0 +1,333 @@ +/* $NetBSD: pthread_int.h,v 1.92 2015/05/29 16:05:13 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * NOTE: when changing anything in this file, please ensure that + * libpthread_dbg still compiles. + */ + +#ifndef _LIB_PTHREAD_INT_H +#define _LIB_PTHREAD_INT_H + +#include + +/* #define PTHREAD__DEBUG */ +#define ERRORCHECK + +#include "pthread_types.h" +#include "pthread_queue.h" +#include "pthread_md.h" + +/* Need to use libc-private names for atomic operations. */ +#include "../../common/lib/libc/atomic/atomic_op_namespace.h" + +#include +#include + +#include +#include +#include +#include + +#ifdef __GNUC__ +#define PTHREAD_HIDE __attribute__ ((visibility("hidden"))) +#else +#define PTHREAD_HIDE /* nothing */ +#endif + +#define PTHREAD__UNPARK_MAX 32 + +/* + * The size of this structure needs to be no larger than struct + * __pthread_cleanup_store, defined in pthread.h. + */ +struct pt_clean_t { + PTQ_ENTRY(pt_clean_t) ptc_next; + void (*ptc_cleanup)(void *); + void *ptc_arg; +}; + +/* Private data for pthread_attr_t */ +struct pthread_attr_private { + char ptap_name[PTHREAD_MAX_NAMELEN_NP]; + void *ptap_namearg; + void *ptap_stackaddr; + size_t ptap_stacksize; + size_t ptap_guardsize; + struct sched_param ptap_sp; + int ptap_policy; +}; + +struct pthread_lock_ops { + void (*plo_init)(__cpu_simple_lock_t *); + int (*plo_try)(__cpu_simple_lock_t *); + void (*plo_unlock)(__cpu_simple_lock_t *); + void (*plo_lock)(__cpu_simple_lock_t *); +}; + +struct __pthread_st { + pthread_t pt_self; /* Must be first. */ +#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) + struct tls_tcb *pt_tls; /* Thread Local Storage area */ +#endif + unsigned int pt_magic; /* Magic number */ + int pt_state; /* running, blocked, etc. */ + pthread_mutex_t pt_lock; /* lock on state */ + int pt_flags; /* see PT_FLAG_* below */ + int pt_cancel; /* Deferred cancellation */ + int pt_errno; /* Thread-specific errno. */ + stack_t pt_stack; /* Our stack */ + bool pt_stack_allocated; + size_t pt_guardsize; + void *pt_exitval; /* Read by pthread_join() */ + char *pt_name; /* Thread's name, set by the app. */ + int pt_willpark; /* About to park */ + lwpid_t pt_unpark; /* Unpark this when parking */ + struct pthread_lock_ops pt_lockops;/* Cached to avoid PIC overhead */ + pthread_mutex_t *pt_droplock; /* Drop this lock if cancelled */ + pthread_cond_t pt_joiners; /* Threads waiting to join. */ + void *(*pt_func)(void *);/* Function to call at start. */ + void *pt_arg; /* Argument to pass at start. */ + + /* Threads to defer waking, usually until pthread_mutex_unlock(). */ + lwpid_t pt_waiters[PTHREAD__UNPARK_MAX]; + size_t pt_nwaiters; + + /* Stack of cancellation cleanup handlers and their arguments */ + PTQ_HEAD(, pt_clean_t) pt_cleanup_stack; + + /* LWP ID and entry on the list of all threads. */ + lwpid_t pt_lid; + rb_node_t pt_alltree; + PTQ_ENTRY(__pthread_st) pt_allq; + PTQ_ENTRY(__pthread_st) pt_deadq; + + /* + * General synchronization data. We try to align, as threads + * on other CPUs will access this data frequently. + */ + int pt_dummy1 __aligned(128); + struct lwpctl *pt_lwpctl; /* Kernel/user comms area */ + volatile int pt_blocking; /* Blocking in userspace */ + volatile int pt_rwlocked; /* Handed rwlock successfully */ + volatile int pt_signalled; /* Received pthread_cond_signal() */ + volatile int pt_mutexwait; /* Waiting to acquire mutex */ + void * volatile pt_mutexnext; /* Next thread in chain */ + void * volatile pt_sleepobj; /* Object slept on */ + PTQ_ENTRY(__pthread_st) pt_sleep; + void (*pt_early)(void *); + int pt_dummy2 __aligned(128); + + /* Thread-specific data. Large so it sits close to the end. */ + int pt_havespecific; + struct pt_specific { + void *pts_value; + PTQ_ENTRY(pt_specific) pts_next; + } pt_specific[]; +}; + +/* Thread states */ +#define PT_STATE_RUNNING 1 +#define PT_STATE_ZOMBIE 5 +#define PT_STATE_DEAD 6 + +/* Flag values */ + +#define PT_FLAG_DETACHED 0x0001 +#define PT_FLAG_CS_DISABLED 0x0004 /* Cancellation disabled */ +#define PT_FLAG_CS_ASYNC 0x0008 /* Cancellation is async */ +#define PT_FLAG_CS_PENDING 0x0010 +#define PT_FLAG_SCOPE_SYSTEM 0x0040 +#define PT_FLAG_EXPLICIT_SCHED 0x0080 +#define PT_FLAG_SUSPENDED 0x0100 /* In the suspended queue */ + +#define PT_MAGIC 0x11110001 +#define PT_DEAD 0xDEAD0001 + +#define PT_ATTR_MAGIC 0x22220002 +#define PT_ATTR_DEAD 0xDEAD0002 + +extern size_t pthread__stacksize; +extern size_t pthread__pagesize; +extern int pthread__nspins; +extern int pthread__concurrency; +extern int pthread__osrev; +extern int pthread__unpark_max; +extern int pthread_keys_max; + +extern int __uselibcstub; + +/* Flag to be used in a ucontext_t's uc_flags indicating that + * the saved register state is "user" state only, not full + * trap state. + */ +#define _UC_USER_BIT 30 +#define _UC_USER (1LU << _UC_USER_BIT) + +/* Utility functions */ +void pthread__unpark_all(pthread_queue_t *, pthread_t, pthread_mutex_t *) + PTHREAD_HIDE; +void pthread__unpark(pthread_queue_t *, pthread_t, pthread_mutex_t *) + PTHREAD_HIDE; +int pthread__park(pthread_t, pthread_mutex_t *, pthread_queue_t *, + const struct timespec *, int, const void *) + PTHREAD_HIDE; +pthread_mutex_t *pthread__hashlock(volatile const void *) PTHREAD_HIDE; + +/* Internal locking primitives */ +void pthread__lockprim_init(void) PTHREAD_HIDE; +void pthread_lockinit(pthread_spin_t *) PTHREAD_HIDE; + +static inline void pthread__spinlock(pthread_t, pthread_spin_t *) + __attribute__((__always_inline__)); +static inline void +pthread__spinlock(pthread_t self, pthread_spin_t *lock) +{ + if (__predict_true((*self->pt_lockops.plo_try)(lock))) + return; + (*self->pt_lockops.plo_lock)(lock); +} + +static inline int pthread__spintrylock(pthread_t, pthread_spin_t *) + __attribute__((__always_inline__)); +static inline int +pthread__spintrylock(pthread_t self, pthread_spin_t *lock) +{ + return (*self->pt_lockops.plo_try)(lock); +} + +static inline void pthread__spinunlock(pthread_t, pthread_spin_t *) + __attribute__((__always_inline__)); +static inline void +pthread__spinunlock(pthread_t self, pthread_spin_t *lock) +{ + (*self->pt_lockops.plo_unlock)(lock); +} + +extern const struct pthread_lock_ops *pthread__lock_ops; + +int pthread__simple_locked_p(__cpu_simple_lock_t *) PTHREAD_HIDE; +#define pthread__simple_lock_init(alp) (*pthread__lock_ops->plo_init)(alp) +#define pthread__simple_lock_try(alp) (*pthread__lock_ops->plo_try)(alp) +#define pthread__simple_unlock(alp) (*pthread__lock_ops->plo_unlock)(alp) + +void pthread__testcancel(pthread_t) PTHREAD_HIDE; +int pthread__find(pthread_t) PTHREAD_HIDE; + +#ifndef PTHREAD_MD_INIT +#define PTHREAD_MD_INIT +#endif + +#ifndef _INITCONTEXT_U_MD +#define _INITCONTEXT_U_MD(ucp) +#endif + +#define _INITCONTEXT_U(ucp) do { \ + (ucp)->uc_flags = _UC_CPU | _UC_STACK; \ + _INITCONTEXT_U_MD(ucp) \ + } while (/*CONSTCOND*/0) + + +#if !defined(__HAVE_TLS_VARIANT_I) && !defined(__HAVE_TLS_VARIANT_II) +#error Either __HAVE_TLS_VARIANT_I or __HAVE_TLS_VARIANT_II must be defined +#endif + +#ifdef _PTHREAD_GETTCB_EXT +struct tls_tcb *_PTHREAD_GETTCB_EXT(void); +#endif + +static inline pthread_t __constfunc +pthread__self(void) +{ +#if defined(_PTHREAD_GETTCB_EXT) + struct tls_tcb * const tcb = _PTHREAD_GETTCB_EXT(); +#elif defined(__HAVE___LWP_GETTCB_FAST) + struct tls_tcb * const tcb = __lwp_gettcb_fast(); +#else + struct tls_tcb * const tcb = __lwp_getprivate_fast(); +#endif + return (pthread_t)tcb->tcb_pthread; +} + +#define pthread__abort() \ + pthread__assertfunc(__FILE__, __LINE__, __func__, "unreachable") + +#define pthread__assert(e) do { \ + if (__predict_false(!(e))) \ + pthread__assertfunc(__FILE__, __LINE__, __func__, #e); \ + } while (/*CONSTCOND*/0) + +#define pthread__error(err, msg, e) do { \ + if (__predict_false(!(e))) { \ + pthread__errorfunc(__FILE__, __LINE__, __func__, msg); \ + return (err); \ + } \ + } while (/*CONSTCOND*/0) + +void *pthread_tsd_init(size_t *) PTHREAD_HIDE; +void pthread__destroy_tsd(pthread_t) PTHREAD_HIDE; +__dead void pthread__assertfunc(const char *, int, const char *, const char *) + PTHREAD_HIDE; +void pthread__errorfunc(const char *, int, const char *, const char *) + PTHREAD_HIDE; +char *pthread__getenv(const char *) PTHREAD_HIDE; +__dead void pthread__cancelled(void) PTHREAD_HIDE; +void pthread__mutex_deferwake(pthread_t, pthread_mutex_t *) PTHREAD_HIDE; +int pthread__checkpri(int) PTHREAD_HIDE; +int pthread__add_specific(pthread_t, pthread_key_t, const void *) PTHREAD_HIDE; + +#ifndef pthread__smt_pause +#define pthread__smt_pause() /* nothing */ +#endif +#ifndef pthread__smt_wake +#define pthread__smt_wake() /* nothing */ +#endif + +/* + * Bits in the owner field of the lock that indicate lock state. If the + * WRITE_LOCKED bit is clear, then the owner field is actually a count of + * the number of readers. + */ +#define RW_HAS_WAITERS 0x01 /* lock has waiters */ +#define RW_WRITE_WANTED 0x02 /* >= 1 waiter is a writer */ +#define RW_WRITE_LOCKED 0x04 /* lock is currently write locked */ +#define RW_UNUSED 0x08 /* currently unused */ + +#define RW_FLAGMASK 0x0f + +#define RW_READ_COUNT_SHIFT 4 +#define RW_READ_INCR (1 << RW_READ_COUNT_SHIFT) +#define RW_THREAD ((uintptr_t)-RW_READ_INCR) +#define RW_OWNER(rw) ((rw)->rw_owner & RW_THREAD) +#define RW_COUNT(rw) ((rw)->rw_owner & RW_THREAD) +#define RW_FLAGS(rw) ((rw)->rw_owner & ~RW_THREAD) + +#endif /* _LIB_PTHREAD_INT_H */ diff --git a/lib/libpthread/pthread_join.3 b/lib/libpthread/pthread_join.3 new file mode 100644 index 000000000..41609f65c --- /dev/null +++ b/lib/libpthread/pthread_join.3 @@ -0,0 +1,134 @@ +.\" $NetBSD: pthread_join.3,v 1.6 2010/07/09 10:55:11 wiz Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" Copyright (c) 1996-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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_join.3,v 1.13 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_JOIN 3 +.Os +.Sh NAME +.Nm pthread_join +.Nd wait for thread termination +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_join "pthread_t thread" "void **value_ptr" +.Sh DESCRIPTION +The +.Fn pthread_join +function suspends execution of the calling thread until the target +.Fa thread +terminates unless the target +.Fa thread +has already terminated. +.Pp +On return from a successful +.Fn pthread_join +call with a +.Pf non- Dv NULL +.Fa value_ptr +argument, the value passed to +.Fn pthread_exit +by the terminating thread is stored in the location referenced by +.Fa value_ptr . +When a +.Fn pthread_join +returns successfully, the target thread has been terminated. +The results +of multiple simultaneous calls to +.Fn pthread_join +specifying the same target thread are undefined. +If the thread calling +.Fn pthread_join +is cancelled, then the target thread is not detached. +.Pp +A thread that has exited but remains unjoined counts against +.Dv _POSIX_THREAD_THREADS_MAX . +.Sh RETURN VALUES +If successful, the +.Fn pthread_join +function will return zero. +Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +.Fn pthread_join +shall fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa thread +does not refer to a joinable thread. +.It Bq Er ESRCH +No thread could be found corresponding to that specified by the given +thread ID, +.Fa thread . +.El +.Pp +.Fn pthread_join +may fail if: +.Bl -tag -width Er +.It Bq Er EDEADLK +A deadlock was detected or the value of +.Fa thread +specifies the calling thread. +.El +.Sh SEE ALSO +.Xr wait 2 , +.Xr pthread_create 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_key_create.3 b/lib/libpthread/pthread_key_create.3 new file mode 100644 index 000000000..8a5a7decb --- /dev/null +++ b/lib/libpthread/pthread_key_create.3 @@ -0,0 +1,194 @@ +.\" $NetBSD: pthread_key_create.3,v 1.8 2015/05/29 18:00:51 wiz Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_key_create.3,v 1.12 2002/09/16 19:29:28 mini Exp $ +.\" +.Dd May 29, 2015 +.Dt PTHREAD_KEY_CREATE 3 +.Os +.Sh NAME +.Nm pthread_key_create +.Nd thread-specific data +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_key_create "pthread_key_t *key" "void (*destructor)(void *)" +.Ft int +.Fn pthread_key_delete "pthread_key_t key" +.Sh DESCRIPTION +The +.Fn pthread_key_create +function creates a thread-specific data key visible to all threads in the +process. +Key values are opaque objects used to locate thread-specific data. +The same key value may be used by different threads, +but the values bound to the key by +.Fn pthread_setspecific +are maintained on a per-thread basis and +persist for the life of the calling thread. +.Pp +Upon key creation, the value +.Dv NULL +is associated with the new key in all active threads. +Upon thread creation, the value +.Dv NULL +is associated with all +defined keys in the new thread. +.Pp +An optional destructor function may be associated with each key value. +At thread exit, if a key value has a +.Pf non- Dv NULL +destructor pointer, and the thread has a +.Pf non- Dv NULL +value associated with the key, the function pointed +to is called with the current associated value as its sole argument. +The order of destructor calls is unspecified if more +than one destructor exists for a thread when it exits. +.Pp +If, after all the destructors have been called for all +.Pf non- Dv NULL +values with associated destructors, there are still some +.Pf non- Dv NULL +values with associated destructors, then the process is repeated. +If, after at least +.Dv PTHREAD_DESTRUCTOR_ITERATIONS +iterations of destructor calls for outstanding +.Pf non- Dv NULL +values, there are still some +.Pf non- Dv NULL +values with +associated destructors, the implementation stops calling destructors. +.Pp +The +.Fn pthread_key_delete +function deletes a thread-specific data key previously returned by +.Fn pthread_key_create . +The thread-specific data values associated with +.Fa key +need not be +.Dv NULL +at the time of the call. +It is the responsibility of the application to free any +application storage or perform any cleanup actions for data structures +related to the deleted key or associated thread-specific data in any threads; +this cleanup can be done either before or after +.Fn pthread_key_delete +is called. +Any attempt to use +.Fa key +following the call to +.Fn pthread_key_delete +results in undefined behavior. +.Pp +The +.Fn pthread_key_delete +function itself is callable from within destructor functions, +but destructor functions are not invoked by the function. +Any destructor function that may have been associated with +.Fa key +will no longer be called upon thread exit. +.Sh RETURN VALUES +If successful, the +.Fn pthread_key_create +function will store the newly created key value at the location specified by +.Fa key +and returns zero. +Also +.Fn pthread_key_delete +will return zero upon success. +Upon failure both functions return an error number to indicate the cause. +.Sh ENVIRONMENT +.Bl -tag -width PTHREAD_KEYS_MAX +.It Ev PTHREAD_KEYS_MAX +Maximum per-process thread-specific data keys. +This cannot be set below +.Dv _POSIX_THREAD_KEYS_MAX . +.El +.Sh ERRORS +The +.Fn pthread_key_create +may fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The system lacked the necessary resources to create another thread-specific +data key, or the system-imposed limit on the total number of keys per-process +.Dv PTHREAD_KEYS_MAX +would be exceeded. +.It Bq Er ENOMEM +Insufficient memory exists to create the key. +.El +.Pp +The +.Fn pthread_key_delete +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa key +value is invalid. +.El +.Sh SEE ALSO +.Xr pthread_getspecific 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . +.Sh BUGS +The current specifications are flawed and +do not permit a clean implementation without potential problems. +The current implementation in +.Nx +addresses these problems by not supporting key reuse. diff --git a/lib/libpthread/pthread_kill.3 b/lib/libpthread/pthread_kill.3 new file mode 100644 index 000000000..90513e941 --- /dev/null +++ b/lib/libpthread/pthread_kill.3 @@ -0,0 +1,102 @@ +.\" $NetBSD: pthread_kill.3,v 1.9 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_kill.3,v 1.9 2002/09/16 19:29:28 mini Exp $ +.Dd July 9, 2010 +.Dt PTHREAD_KILL 3 +.Os +.Sh NAME +.Nm pthread_kill +.Nd send a signal to a specified thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.In signal.h +.Ft int +.Fn pthread_kill "pthread_t thread" "int sig" +.Sh DESCRIPTION +The +.Fn pthread_kill +function sends a signal, specified by +.Fa sig , +to a thread, specified by +.Fa thread . +The signal will be handled in the context of +.Fa thread , +but the signal action may alter the process as a whole. +If +.Fa sig +is 0, error checking is performed, but no signal is actually sent. +.Sh RETURN VALUES +If successful, +.Fn pthread_kill +returns 0. +Otherwise, an error number is returned. +.Sh ERRORS +.Fn pthread_kill +shall fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa sig +is an invalid or unsupported signal number. +.It Bq Er ESRCH +.Fa thread +is an invalid thread ID. +.El +.Sh SEE ALSO +.Xr kill 2 , +.Xr sigwait 2 , +.Xr pthread_self 3 , +.Xr raise 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_lock.c b/lib/libpthread/pthread_lock.c new file mode 100644 index 000000000..8365abd32 --- /dev/null +++ b/lib/libpthread/pthread_lock.c @@ -0,0 +1,198 @@ +/* $NetBSD: pthread_lock.c,v 1.34 2008/04/28 20:23:01 martin Exp $ */ + +/*- + * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * libpthread internal spinlock routines. + */ + +#include +__RCSID("$NetBSD: pthread_lock.c,v 1.34 2008/04/28 20:23:01 martin Exp $"); + +#include +#include + +#include + +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" + +/* How many times to try acquiring spin locks on MP systems. */ +#define PTHREAD__NSPINS 64 + +RAS_DECL(pthread__lock); + +static void pthread__spinlock_slow(pthread_spin_t *); + +#ifdef PTHREAD__ASM_RASOPS + +void pthread__ras_simple_lock_init(__cpu_simple_lock_t *); +int pthread__ras_simple_lock_try(__cpu_simple_lock_t *); +void pthread__ras_simple_unlock(__cpu_simple_lock_t *); + +#else + +static void +pthread__ras_simple_lock_init(__cpu_simple_lock_t *alp) +{ + + __cpu_simple_lock_clear(alp); +} + +static int +pthread__ras_simple_lock_try(__cpu_simple_lock_t *alp) +{ + int locked; + + RAS_START(pthread__lock); + locked = __SIMPLELOCK_LOCKED_P(alp); + __cpu_simple_lock_set(alp); + RAS_END(pthread__lock); + + return !locked; +} + +static void +pthread__ras_simple_unlock(__cpu_simple_lock_t *alp) +{ + + __cpu_simple_lock_clear(alp); +} + +#endif /* PTHREAD__ASM_RASOPS */ + +static const struct pthread_lock_ops pthread__lock_ops_ras = { + pthread__ras_simple_lock_init, + pthread__ras_simple_lock_try, + pthread__ras_simple_unlock, + pthread__spinlock_slow, +}; + +static void +pthread__atomic_simple_lock_init(__cpu_simple_lock_t *alp) +{ + + __cpu_simple_lock_init(alp); +} + +static int +pthread__atomic_simple_lock_try(__cpu_simple_lock_t *alp) +{ + + return (__cpu_simple_lock_try(alp)); +} + +static void +pthread__atomic_simple_unlock(__cpu_simple_lock_t *alp) +{ + + __cpu_simple_unlock(alp); +} + +static const struct pthread_lock_ops pthread__lock_ops_atomic = { + pthread__atomic_simple_lock_init, + pthread__atomic_simple_lock_try, + pthread__atomic_simple_unlock, + pthread__spinlock_slow, +}; + +/* + * We default to pointing to the RAS primitives; we might need to use + * locks early, but before main() starts. This is safe, since no other + * threads will be active for the process, so atomicity will not be + * required. + */ +const struct pthread_lock_ops *pthread__lock_ops = &pthread__lock_ops_ras; + +/* + * Prevent this routine from being inlined. The common case is no + * contention and it's better to not burden the instruction decoder. + */ +static void +pthread__spinlock_slow(pthread_spin_t *lock) +{ + pthread_t self; + int count; + + self = pthread__self(); + + do { + count = pthread__nspins; + while (__SIMPLELOCK_LOCKED_P(lock) && --count > 0) + pthread__smt_pause(); + if (count > 0) { + if ((*self->pt_lockops.plo_try)(lock)) + break; + continue; + } + sched_yield(); + } while (/*CONSTCOND*/ 1); +} + +/* + * Initialize the locking primitives. On uniprocessors, we always + * use Restartable Atomic Sequences if they are available. Otherwise, + * we fall back onto machine-dependent atomic lock primitives. + */ +void +pthread__lockprim_init(void) +{ + char *p; + + if ((p = pthread__getenv("PTHREAD_NSPINS")) != NULL) + pthread__nspins = atoi(p); + else if (pthread__concurrency != 1) + pthread__nspins = PTHREAD__NSPINS; + else + pthread__nspins = 1; + + if (pthread__concurrency != 1) { + pthread__lock_ops = &pthread__lock_ops_atomic; + return; + } + + if (rasctl(RAS_ADDR(pthread__lock), RAS_SIZE(pthread__lock), + RAS_INSTALL) != 0) { + pthread__lock_ops = &pthread__lock_ops_atomic; + return; + } +} + +void +pthread_lockinit(pthread_spin_t *lock) +{ + + pthread__simple_lock_init(lock); +} diff --git a/lib/libpthread/pthread_makelwp.h b/lib/libpthread/pthread_makelwp.h new file mode 100644 index 000000000..27b79ba07 --- /dev/null +++ b/lib/libpthread/pthread_makelwp.h @@ -0,0 +1,46 @@ +/* $NetBSD: pthread_makelwp.h,v 1.1 2014/12/16 20:05:54 pooka Exp $ */ + +/*- + * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_MAKELWP_H_ +#define _LIB_PTHREAD_MAKELWP_H_ + +#include + +#include + +/* for PTHREAD_HIDE */ +#include +#include "pthread_int.h" + +int pthread__makelwp(void (*)(void *), void *, void *, void *, size_t, + unsigned long, lwpid_t *) PTHREAD_HIDE; + +#endif /* _LIB_PTHREAD_MAKELWP_H_ */ diff --git a/lib/libpthread/pthread_makelwp_netbsd.c b/lib/libpthread/pthread_makelwp_netbsd.c new file mode 100644 index 000000000..ab7cbdc50 --- /dev/null +++ b/lib/libpthread/pthread_makelwp_netbsd.c @@ -0,0 +1,65 @@ +/* $NetBSD: pthread_makelwp_netbsd.c,v 1.2 2014/12/17 01:49:08 pooka Exp $ */ + +/*- + * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_makelwp_netbsd.c,v 1.2 2014/12/17 01:49:08 pooka Exp $"); + +#include + +#include +#include +#include + +#include "pthread_int.h" +#include "pthread_makelwp.h" + +int +pthread__makelwp(void (*start_routine)(void *), void *arg, void *priv, + void *stack_base, size_t stack_size, + unsigned long flag, lwpid_t *newlid) +{ + ucontext_t uc; + + /* + * XXX: most of the following chunk is these days + * performed also by _lwp_makecontext(), but there may + * be MD differences, so lug everything along for now. + */ + memset(&uc, 0, sizeof(uc)); + _INITCONTEXT_U(&uc); + uc.uc_stack.ss_sp = stack_base; + uc.uc_stack.ss_size = stack_size; + uc.uc_stack.ss_flags = 0; + uc.uc_link = NULL; + + _lwp_makecontext(&uc, start_routine, arg, priv, stack_base, stack_size); + return _lwp_create(&uc, flag, newlid); +} diff --git a/lib/libpthread/pthread_misc.c b/lib/libpthread/pthread_misc.c new file mode 100644 index 000000000..e94290b13 --- /dev/null +++ b/lib/libpthread/pthread_misc.c @@ -0,0 +1,170 @@ +/* $NetBSD: pthread_misc.c,v 1.15 2013/03/21 16:49:12 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_misc.c,v 1.15 2013/03/21 16:49:12 christos Exp $"); + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +int pthread__sched_yield(void); + +int _sys___sigprocmask14(int, const sigset_t *, sigset_t *); +int _sys_sched_yield(void); + +__strong_alias(__libc_thr_sigsetmask,pthread_sigmask) +__strong_alias(__sigprocmask14,pthread_sigmask) +__strong_alias(__libc_thr_yield,pthread__sched_yield) + +int +pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + + if (_sched_getparam(getpid(), thread->pt_lid, policy, param) < 0) + return errno; + + return 0; +} + +int +pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) +{ + struct sched_param sp; + + if (pthread__find(thread) != 0) + return ESRCH; + + memcpy(&sp, param, sizeof(struct sched_param)); + if (_sched_setparam(getpid(), thread->pt_lid, policy, &sp) < 0) + return errno; + + return 0; +} + +int +pthread_getaffinity_np(pthread_t thread, size_t size, cpuset_t *cpuset) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + + if (_sched_getaffinity(getpid(), thread->pt_lid, size, cpuset) < 0) + return errno; + + return 0; +} + +int +pthread_setaffinity_np(pthread_t thread, size_t size, cpuset_t *cpuset) +{ + + if (pthread__find(thread) != 0) + return ESRCH; + + if (_sched_setaffinity(getpid(), thread->pt_lid, size, cpuset) < 0) + return errno; + + return 0; +} + +int +pthread_setschedprio(pthread_t thread, int prio) +{ + struct sched_param sp; + + if (pthread__find(thread) != 0) + return ESRCH; + + sp.sched_priority = prio; + if (_sched_setparam(getpid(), thread->pt_lid, SCHED_NONE, &sp) < 0) + return errno; + + return 0; +} + +int +pthread_kill(pthread_t thread, int sig) +{ + + if ((sig < 0) || (sig >= _NSIG)) + return EINVAL; + if (pthread__find(thread) != 0) + return ESRCH; + if (_lwp_kill(thread->pt_lid, sig)) + return errno; + return 0; +} + +int +pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) +{ + if (_sys___sigprocmask14(how, set, oset)) + return errno; + return 0; +} + +int +pthread__sched_yield(void) +{ + pthread_t self; + int error; + + if (__predict_false(__uselibcstub)) + return __libc_thr_yield(); + + self = pthread__self(); + + /* Memory barrier for unlocked mutex release. */ + membar_producer(); + self->pt_blocking++; + error = _sys_sched_yield(); + self->pt_blocking--; + membar_sync(); + + return error; +} diff --git a/lib/libpthread/pthread_mutex.3 b/lib/libpthread/pthread_mutex.3 new file mode 100644 index 000000000..b6ddcab93 --- /dev/null +++ b/lib/libpthread/pthread_mutex.3 @@ -0,0 +1,217 @@ +.\" $NetBSD: pthread_mutex.3,v 1.6 2012/11/12 23:11:05 uwe Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" Copyright (c) 1997 Brian Cully +.\" 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 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. +.\" +.\" ---------------------------------------------------------------------------- +.Dd July 8, 2010 +.Dt PTHREAD_MUTEX 3 +.Os +.Sh NAME +.Nm pthread_mutex +.Nd mutual exclusion primitives +.Sh LIBRARY +.Lb libpthread +.\" ---------------------------------------------------------------------------- +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_mutex_init "pthread_mutex_t * restrict mutex" \ +"const pthread_mutexattr_t * restrict attr" +.Vt pthread_mutex_t mutex No = Dv PTHREAD_MUTEX_INITIALIZER; +.Ft int +.Fn pthread_mutex_destroy "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_mutex_lock "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_mutex_trylock "pthread_mutex_t *mutex" +.Ft int +.Fn pthread_mutex_unlock "pthread_mutex_t *mutex" +.\" ---------------------------------------------------------------------------- +.Sh DESCRIPTION +The +.Fn pthread_mutex_init +function creates a new mutex, with attributes specified with +.Fa attr . +If +.Fa attr +is +.Dv NULL , +the default attributes are used. +.Pp +The macro +.Dv PTHREAD_MUTEX_INITIALIZER +can be used to initialize a mutex when the default attributes are +appropriate and the mutex can be statically allocated. +The behavior is similar to +.Fn pthread_mutex_init +with +.Fa attr +specified as +.Dv NULL , +except that no error checking is done. +.Pp +.\" ----- +The +.Fn pthread_mutex_destroy +function frees the resources allocated for +.Fa mutex . +It is possible to reinitialize a destroyed mutex, but undefined +behavior may follow if the destroyed object is otherwise referenced. +.Pp +.\" ----- +The +.Fn pthread_mutex_lock +function locks +.Fa mutex . +If the mutex is already locked, the calling thread will block until the +mutex becomes available. +The error conditions may vary depending on the type of the mutex; see +.Xr pthread_mutexattr 3 +for additional details. +.Pp +The +.Fn pthread_mutex_trylock +function locks +.Fa mutex . +If the mutex is already locked, +.Fn pthread_mutex_trylock +will not block waiting for the mutex, but will return an error condition. +.Pp +.\" ----- +The +.Fn pthread_mutex_unlock +function unlocks an acquired +.Fa mutex . +When operating with the default mutex type, +undefined behavior follows if a thread tries to unlock a mutex +that has not been locked by it, or if a thread tries to release +a mutex that is already unlocked. +.\" ---------------------------------------------------------------------------- +.Sh RETURN VALUES +Upon success all described functions return zero. +Otherwise, an error number will be returned to indicate the error. +.Sh ERRORS +.Fn pthread_mutex_init +may fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The system lacks the resources to initialize another mutex. +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.It Bq Er ENOMEM +The process cannot allocate enough memory to initialize another mutex. +.El +.Pp +.\" ----- +.Fn pthread_mutex_destroy +may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +.Fa Mutex +is locked by another thread. +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.El +.Pp +.\" ----- +.Fn pthread_mutex_lock +may fail if: +.Bl -tag -width Er +.It Bq Er EDEADLK +A deadlock would occur if the thread blocked waiting for +.Fa mutex . +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.El +.Pp +.Fn pthread_mutex_trylock +may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +.Fa Mutex +is already locked. +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.El +.Pp +.\" ----- +.Fn pthread_mutex_unlock +may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa mutex +is invalid. +.It Bq Er EPERM +The current thread does not hold a lock on +.Fa mutex . +.El +.\" ---------------------------------------------------------------------------- +.Sh SEE ALSO +.Xr pthread 3 , +.Xr pthread_barrier 3 , +.Xr pthread_cond 3 , +.Xr pthread_mutexattr 3 , +.Xr pthread_rwlock 3 , +.Xr pthread_spin 3 +.\" ---------------------------------------------------------------------------- +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_mutex.c b/lib/libpthread/pthread_mutex.c new file mode 100644 index 000000000..2d8eed5f1 --- /dev/null +++ b/lib/libpthread/pthread_mutex.c @@ -0,0 +1,659 @@ +/* $NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $ */ + +/*- + * Copyright (c) 2001, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams, by Jason R. Thorpe, and by Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * To track threads waiting for mutexes to be released, we use lockless + * lists built on atomic operations and memory barriers. + * + * A simple spinlock would be faster and make the code easier to + * follow, but spinlocks are problematic in userspace. If a thread is + * preempted by the kernel while holding a spinlock, any other thread + * attempting to acquire that spinlock will needlessly busy wait. + * + * There is no good way to know that the holding thread is no longer + * running, nor to request a wake-up once it has begun running again. + * Of more concern, threads in the SCHED_FIFO class do not have a + * limited time quantum and so could spin forever, preventing the + * thread holding the spinlock from getting CPU time: it would never + * be released. + */ + +#include +__RCSID("$NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $"); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +#define MUTEX_WAITERS_BIT ((uintptr_t)0x01) +#define MUTEX_RECURSIVE_BIT ((uintptr_t)0x02) +#define MUTEX_DEFERRED_BIT ((uintptr_t)0x04) +#define MUTEX_THREAD ((uintptr_t)-16L) + +#define MUTEX_HAS_WAITERS(x) ((uintptr_t)(x) & MUTEX_WAITERS_BIT) +#define MUTEX_RECURSIVE(x) ((uintptr_t)(x) & MUTEX_RECURSIVE_BIT) +#define MUTEX_OWNER(x) ((uintptr_t)(x) & MUTEX_THREAD) + +#if __GNUC_PREREQ__(3, 0) +#define NOINLINE __attribute ((noinline)) +#else +#define NOINLINE /* nothing */ +#endif + +static void pthread__mutex_wakeup(pthread_t, pthread_mutex_t *); +static int pthread__mutex_lock_slow(pthread_mutex_t *); +static int pthread__mutex_unlock_slow(pthread_mutex_t *); +static void pthread__mutex_pause(void); + +int _pthread_mutex_held_np(pthread_mutex_t *); +pthread_t _pthread_mutex_owner_np(pthread_mutex_t *); + +__weak_alias(pthread_mutex_held_np,_pthread_mutex_held_np) +__weak_alias(pthread_mutex_owner_np,_pthread_mutex_owner_np) + +__strong_alias(__libc_mutex_init,pthread_mutex_init) +__strong_alias(__libc_mutex_lock,pthread_mutex_lock) +__strong_alias(__libc_mutex_trylock,pthread_mutex_trylock) +__strong_alias(__libc_mutex_unlock,pthread_mutex_unlock) +__strong_alias(__libc_mutex_destroy,pthread_mutex_destroy) + +__strong_alias(__libc_mutexattr_init,pthread_mutexattr_init) +__strong_alias(__libc_mutexattr_destroy,pthread_mutexattr_destroy) +__strong_alias(__libc_mutexattr_settype,pthread_mutexattr_settype) + +int +pthread_mutex_init(pthread_mutex_t *ptm, const pthread_mutexattr_t *attr) +{ + intptr_t type; + + if (__predict_false(__uselibcstub)) + return __libc_mutex_init_stub(ptm, attr); + + if (attr == NULL) + type = PTHREAD_MUTEX_NORMAL; + else + type = (intptr_t)attr->ptma_private; + + switch (type) { + case PTHREAD_MUTEX_ERRORCHECK: + __cpu_simple_lock_set(&ptm->ptm_errorcheck); + ptm->ptm_owner = NULL; + break; + case PTHREAD_MUTEX_RECURSIVE: + __cpu_simple_lock_clear(&ptm->ptm_errorcheck); + ptm->ptm_owner = (void *)MUTEX_RECURSIVE_BIT; + break; + default: + __cpu_simple_lock_clear(&ptm->ptm_errorcheck); + ptm->ptm_owner = NULL; + break; + } + + ptm->ptm_magic = _PT_MUTEX_MAGIC; + ptm->ptm_waiters = NULL; + ptm->ptm_recursed = 0; + + return 0; +} + +int +pthread_mutex_destroy(pthread_mutex_t *ptm) +{ + + if (__predict_false(__uselibcstub)) + return __libc_mutex_destroy_stub(ptm); + + pthread__error(EINVAL, "Invalid mutex", + ptm->ptm_magic == _PT_MUTEX_MAGIC); + pthread__error(EBUSY, "Destroying locked mutex", + MUTEX_OWNER(ptm->ptm_owner) == 0); + + ptm->ptm_magic = _PT_MUTEX_DEAD; + return 0; +} + +int +pthread_mutex_lock(pthread_mutex_t *ptm) +{ + pthread_t self; + void *val; + + if (__predict_false(__uselibcstub)) + return __libc_mutex_lock_stub(ptm); + + self = pthread__self(); + val = atomic_cas_ptr(&ptm->ptm_owner, NULL, self); + if (__predict_true(val == NULL)) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + return pthread__mutex_lock_slow(ptm); +} + +/* We want function call overhead. */ +NOINLINE static void +pthread__mutex_pause(void) +{ + + pthread__smt_pause(); +} + +/* + * Spin while the holder is running. 'lwpctl' gives us the true + * status of the thread. pt_blocking is set by libpthread in order + * to cut out system call and kernel spinlock overhead on remote CPUs + * (could represent many thousands of clock cycles). pt_blocking also + * makes this thread yield if the target is calling sched_yield(). + */ +NOINLINE static void * +pthread__mutex_spin(pthread_mutex_t *ptm, pthread_t owner) +{ + pthread_t thread; + unsigned int count, i; + + for (count = 2;; owner = ptm->ptm_owner) { + thread = (pthread_t)MUTEX_OWNER(owner); + if (thread == NULL) + break; + if (thread->pt_lwpctl->lc_curcpu == LWPCTL_CPU_NONE || + thread->pt_blocking) + break; + if (count < 128) + count += count; + for (i = count; i != 0; i--) + pthread__mutex_pause(); + } + + return owner; +} + +NOINLINE static void +pthread__mutex_setwaiters(pthread_t self, pthread_mutex_t *ptm) +{ + void *new, *owner; + + /* + * Note that the mutex can become unlocked before we set + * the waiters bit. If that happens it's not safe to sleep + * as we may never be awoken: we must remove the current + * thread from the waiters list and try again. + * + * Because we are doing this atomically, we can't remove + * one waiter: we must remove all waiters and awken them, + * then sleep in _lwp_park() until we have been awoken. + * + * Issue a memory barrier to ensure that we are reading + * the value of ptm_owner/pt_mutexwait after we have entered + * the waiters list (the CAS itself must be atomic). + */ +again: + membar_consumer(); + owner = ptm->ptm_owner; + + if (MUTEX_OWNER(owner) == 0) { + pthread__mutex_wakeup(self, ptm); + return; + } + if (!MUTEX_HAS_WAITERS(owner)) { + new = (void *)((uintptr_t)owner | MUTEX_WAITERS_BIT); + if (atomic_cas_ptr(&ptm->ptm_owner, owner, new) != owner) { + goto again; + } + } + + /* + * Note that pthread_mutex_unlock() can do a non-interlocked CAS. + * We cannot know if the presence of the waiters bit is stable + * while the holding thread is running. There are many assumptions; + * see sys/kern/kern_mutex.c for details. In short, we must spin if + * we see that the holder is running again. + */ + membar_sync(); + pthread__mutex_spin(ptm, owner); + + if (membar_consumer(), !MUTEX_HAS_WAITERS(ptm->ptm_owner)) { + goto again; + } +} + +NOINLINE static int +pthread__mutex_lock_slow(pthread_mutex_t *ptm) +{ + void *waiters, *new, *owner, *next; + pthread_t self; + int serrno; + + pthread__error(EINVAL, "Invalid mutex", + ptm->ptm_magic == _PT_MUTEX_MAGIC); + + owner = ptm->ptm_owner; + self = pthread__self(); + + /* Recursive or errorcheck? */ + if (MUTEX_OWNER(owner) == (uintptr_t)self) { + if (MUTEX_RECURSIVE(owner)) { + if (ptm->ptm_recursed == INT_MAX) + return EAGAIN; + ptm->ptm_recursed++; + return 0; + } + if (__SIMPLELOCK_LOCKED_P(&ptm->ptm_errorcheck)) + return EDEADLK; + } + + serrno = errno; + for (;; owner = ptm->ptm_owner) { + /* Spin while the owner is running. */ + owner = pthread__mutex_spin(ptm, owner); + + /* If it has become free, try to acquire it again. */ + if (MUTEX_OWNER(owner) == 0) { + do { + new = (void *) + ((uintptr_t)self | (uintptr_t)owner); + next = atomic_cas_ptr(&ptm->ptm_owner, owner, + new); + if (next == owner) { + errno = serrno; +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + owner = next; + } while (MUTEX_OWNER(owner) == 0); + /* + * We have lost the race to acquire the mutex. + * The new owner could be running on another + * CPU, in which case we should spin and avoid + * the overhead of blocking. + */ + continue; + } + + /* + * Nope, still held. Add thread to the list of waiters. + * Issue a memory barrier to ensure mutexwait/mutexnext + * are visible before we enter the waiters list. + */ + self->pt_mutexwait = 1; + for (waiters = ptm->ptm_waiters;; waiters = next) { + self->pt_mutexnext = waiters; + membar_producer(); + next = atomic_cas_ptr(&ptm->ptm_waiters, waiters, self); + if (next == waiters) + break; + } + + /* Set the waiters bit and block. */ + pthread__mutex_setwaiters(self, ptm); + + /* + * We may have been awoken by the current thread above, + * or will be awoken by the current holder of the mutex. + * The key requirement is that we must not proceed until + * told that we are no longer waiting (via pt_mutexwait + * being set to zero). Otherwise it is unsafe to re-enter + * the thread onto the waiters list. + */ + while (self->pt_mutexwait) { + self->pt_blocking++; + (void)_lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, NULL, + self->pt_unpark, __UNVOLATILE(&ptm->ptm_waiters), + __UNVOLATILE(&ptm->ptm_waiters)); + self->pt_unpark = 0; + self->pt_blocking--; + membar_sync(); + } + } +} + +int +pthread_mutex_trylock(pthread_mutex_t *ptm) +{ + pthread_t self; + void *val, *new, *next; + + if (__predict_false(__uselibcstub)) + return __libc_mutex_trylock_stub(ptm); + + self = pthread__self(); + val = atomic_cas_ptr(&ptm->ptm_owner, NULL, self); + if (__predict_true(val == NULL)) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + + if (MUTEX_RECURSIVE(val)) { + if (MUTEX_OWNER(val) == 0) { + new = (void *)((uintptr_t)self | (uintptr_t)val); + next = atomic_cas_ptr(&ptm->ptm_owner, val, new); + if (__predict_true(next == val)) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + } + if (MUTEX_OWNER(val) == (uintptr_t)self) { + if (ptm->ptm_recursed == INT_MAX) + return EAGAIN; + ptm->ptm_recursed++; + return 0; + } + } + + return EBUSY; +} + +int +pthread_mutex_unlock(pthread_mutex_t *ptm) +{ + pthread_t self; + void *value; + + if (__predict_false(__uselibcstub)) + return __libc_mutex_unlock_stub(ptm); + + /* + * Note this may be a non-interlocked CAS. See lock_slow() + * above and sys/kern/kern_mutex.c for details. + */ +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_exit(); +#endif + self = pthread__self(); + value = atomic_cas_ptr_ni(&ptm->ptm_owner, self, NULL); + if (__predict_true(value == self)) { + pthread__smt_wake(); + return 0; + } + return pthread__mutex_unlock_slow(ptm); +} + +NOINLINE static int +pthread__mutex_unlock_slow(pthread_mutex_t *ptm) +{ + pthread_t self, owner, new; + int weown, error, deferred; + + pthread__error(EINVAL, "Invalid mutex", + ptm->ptm_magic == _PT_MUTEX_MAGIC); + + self = pthread__self(); + owner = ptm->ptm_owner; + weown = (MUTEX_OWNER(owner) == (uintptr_t)self); + deferred = (int)((uintptr_t)owner & MUTEX_DEFERRED_BIT); + error = 0; + + if (__SIMPLELOCK_LOCKED_P(&ptm->ptm_errorcheck)) { + if (!weown) { + error = EPERM; + new = owner; + } else { + new = NULL; + } + } else if (MUTEX_RECURSIVE(owner)) { + if (!weown) { + error = EPERM; + new = owner; + } else if (ptm->ptm_recursed) { + ptm->ptm_recursed--; + new = owner; + } else { + new = (pthread_t)MUTEX_RECURSIVE_BIT; + } + } else { + pthread__error(EPERM, + "Unlocking unlocked mutex", (owner != NULL)); + pthread__error(EPERM, + "Unlocking mutex owned by another thread", weown); + new = NULL; + } + + /* + * Release the mutex. If there appear to be waiters, then + * wake them up. + */ + if (new != owner) { + owner = atomic_swap_ptr(&ptm->ptm_owner, new); + if (MUTEX_HAS_WAITERS(owner) != 0) { + pthread__mutex_wakeup(self, ptm); + return 0; + } + } + + /* + * There were no waiters, but we may have deferred waking + * other threads until mutex unlock - we must wake them now. + */ + if (!deferred) + return error; + + if (self->pt_nwaiters == 1) { + /* + * If the calling thread is about to block, defer + * unparking the target until _lwp_park() is called. + */ + if (self->pt_willpark && self->pt_unpark == 0) { + self->pt_unpark = self->pt_waiters[0]; + } else { + (void)_lwp_unpark(self->pt_waiters[0], + __UNVOLATILE(&ptm->ptm_waiters)); + } + } else { + (void)_lwp_unpark_all(self->pt_waiters, self->pt_nwaiters, + __UNVOLATILE(&ptm->ptm_waiters)); + } + self->pt_nwaiters = 0; + + return error; +} + +/* + * pthread__mutex_wakeup: unpark threads waiting for us + * + * unpark threads on the ptm->ptm_waiters list and self->pt_waiters. + */ + +static void +pthread__mutex_wakeup(pthread_t self, pthread_mutex_t *ptm) +{ + pthread_t thread, next; + ssize_t n, rv; + + /* + * Take ownership of the current set of waiters. No + * need for a memory barrier following this, all loads + * are dependent upon 'thread'. + */ + thread = atomic_swap_ptr(&ptm->ptm_waiters, NULL); + pthread__smt_wake(); + + for (;;) { + /* + * Pull waiters from the queue and add to our list. + * Use a memory barrier to ensure that we safely + * read the value of pt_mutexnext before 'thread' + * sees pt_mutexwait being cleared. + */ + for (n = self->pt_nwaiters, self->pt_nwaiters = 0; + n < pthread__unpark_max && thread != NULL; + thread = next) { + next = thread->pt_mutexnext; + if (thread != self) { + self->pt_waiters[n++] = thread->pt_lid; + membar_sync(); + } + thread->pt_mutexwait = 0; + /* No longer safe to touch 'thread' */ + } + + switch (n) { + case 0: + return; + case 1: + /* + * If the calling thread is about to block, + * defer unparking the target until _lwp_park() + * is called. + */ + if (self->pt_willpark && self->pt_unpark == 0) { + self->pt_unpark = self->pt_waiters[0]; + return; + } + rv = (ssize_t)_lwp_unpark(self->pt_waiters[0], + __UNVOLATILE(&ptm->ptm_waiters)); + if (rv != 0 && errno != EALREADY && errno != EINTR && + errno != ESRCH) { + pthread__errorfunc(__FILE__, __LINE__, + __func__, "_lwp_unpark failed"); + } + return; + default: + rv = _lwp_unpark_all(self->pt_waiters, (size_t)n, + __UNVOLATILE(&ptm->ptm_waiters)); + if (rv != 0 && errno != EINTR) { + pthread__errorfunc(__FILE__, __LINE__, + __func__, "_lwp_unpark_all failed"); + } + break; + } + } +} + +int +pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + if (__predict_false(__uselibcstub)) + return __libc_mutexattr_init_stub(attr); + + attr->ptma_magic = _PT_MUTEXATTR_MAGIC; + attr->ptma_private = (void *)PTHREAD_MUTEX_DEFAULT; + return 0; +} + +int +pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + if (__predict_false(__uselibcstub)) + return __libc_mutexattr_destroy_stub(attr); + + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); + + return 0; +} + +int +pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) +{ + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); + + *typep = (int)(intptr_t)attr->ptma_private; + return 0; +} + +int +pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + if (__predict_false(__uselibcstub)) + return __libc_mutexattr_settype_stub(attr, type); + + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); + + switch (type) { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_RECURSIVE: + attr->ptma_private = (void *)(intptr_t)type; + return 0; + default: + return EINVAL; + } +} + +/* + * pthread__mutex_deferwake: try to defer unparking threads in self->pt_waiters + * + * In order to avoid unnecessary contention on the interlocking mutex, + * we defer waking up threads until we unlock the mutex. The threads will + * be woken up when the calling thread (self) releases the first mutex with + * MUTEX_DEFERRED_BIT set. It likely be the mutex 'ptm', but no problem + * even if it isn't. + */ + +void +pthread__mutex_deferwake(pthread_t self, pthread_mutex_t *ptm) +{ + + if (__predict_false(ptm == NULL || + MUTEX_OWNER(ptm->ptm_owner) != (uintptr_t)self)) { + (void)_lwp_unpark_all(self->pt_waiters, self->pt_nwaiters, + __UNVOLATILE(&ptm->ptm_waiters)); + self->pt_nwaiters = 0; + } else { + atomic_or_ulong((volatile unsigned long *) + (uintptr_t)&ptm->ptm_owner, + (unsigned long)MUTEX_DEFERRED_BIT); + } +} + +int +_pthread_mutex_held_np(pthread_mutex_t *ptm) +{ + + return MUTEX_OWNER(ptm->ptm_owner) == (uintptr_t)pthread__self(); +} + +pthread_t +_pthread_mutex_owner_np(pthread_mutex_t *ptm) +{ + + return (pthread_t)MUTEX_OWNER(ptm->ptm_owner); +} diff --git a/lib/libpthread/pthread_mutexattr.3 b/lib/libpthread/pthread_mutexattr.3 new file mode 100644 index 000000000..5a20787b7 --- /dev/null +++ b/lib/libpthread/pthread_mutexattr.3 @@ -0,0 +1,246 @@ +.\" $NetBSD: pthread_mutexattr.3,v 1.11 2010/07/08 22:46:34 jruoho Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_mutexattr.3,v 1.8 2002/09/16 19:29:29 mini Exp $ +.Dd July 9, 2010 +.Dt PTHREAD_MUTEXATTR 3 +.Os +.Sh NAME +.Nm pthread_mutexattr_init , +.Nm pthread_mutexattr_destroy , +.\" .Nm pthread_mutexattr_setprioceiling , +.\" .Nm pthread_mutexattr_getprioceiling , +.\" .Nm pthread_mutexattr_setprotocol , +.\" .Nm pthread_mutexattr_getprotocol , +.Nm pthread_mutexattr_settype , +.Nm pthread_mutexattr_gettype +.Nd mutex attribute operations +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_mutexattr_init "pthread_mutexattr_t *attr" +.Ft int +.Fn pthread_mutexattr_destroy "pthread_mutexattr_t *attr" +.\" .Ft int +.\" .Fn pthread_mutexattr_setprioceiling \ +.\" "pthread_mutexattr_t *attr" "int prioceiling" +.\" .Ft int +.\" .Fn pthread_mutexattr_getprioceiling \ +.\" "pthread_mutexattr_t *attr" "int *prioceiling" +.\" .Ft int +.\" .Fn pthread_mutexattr_setprotocol \ +.\" "pthread_mutexattr_t *attr" "int protocol" +.\" .Ft int +.\" .Fn pthread_mutexattr_getprotocol \ +.\" "pthread_mutexattr_t *attr" "int *protocol" +.Ft int +.Fn pthread_mutexattr_settype "pthread_mutexattr_t *attr" "int type" +.Ft int +.Fn pthread_mutexattr_gettype \ +"pthread_mutexattr_t * restrict attr" "int * restrict type" +.Sh DESCRIPTION +Mutex attributes are used to specify parameters to +.Fn pthread_mutex_init . +Like with thread attributes, +one attribute object can be used in multiple calls to +.Xr pthread_mutex_init 3 , +with or without modifications between calls. +.Pp +The +.Fn pthread_mutexattr_init +function initializes +.Fa attr +with all the default mutex attributes. +.Pp +The +.Fn pthread_mutexattr_destroy +function destroys +.Fa attr . +.Pp +The +.Fn pthread_mutexattr_settype +functions set the mutex +.Fa type +value of the attribute. +Valid mutex types are: +.Bl -tag -width "XXX" -offset 2n +.It Dv PTHREAD_MUTEX_NORMAL +This type of mutex does not check for usage errors. +It will deadlock if reentered, and result in undefined behavior if a +locked mutex is unlocked by another thread. +Attempts to unlock an already unlocked +.Dv PTHREAD_MUTEX_NORMAL +mutex will result in undefined behavior. +.It Dv PTHREAD_MUTEX_ERRORCHECK +These mutexes do check for usage errors. +If an attempt is made to relock a +.Dv PTHREAD_MUTEX_ERRORCHECK +mutex without first dropping the lock, an error will be returned. +If a thread attempts to unlock a +.Dv PTHREAD_MUTEX_ERRORCHECK +mutex that is locked by another thread, an error will be returned. +If a thread attempts to unlock a +.Dv PTHREAD_MUTEX_ERRORCHECK +thread that is unlocked, an error will be returned. +.It Dv PTHREAD_MUTEX_RECURSIVE +These mutexes allow recursive locking. +An attempt to relock a +.Dv PTHREAD_MUTEX_RECURSIVE +mutex that is already locked by the same thread succeeds. +An equivalent number of +.Xr pthread_mutex_unlock 3 +calls are needed before the mutex will wake another thread waiting +on this lock. +If a thread attempts to unlock a +.Dv PTHREAD_MUTEX_RECURSIVE +mutex that is locked by another thread, an error will be returned. +If a thread attempts to unlock a +.Dv PTHREAD_MUTEX_RECURSIVE +thread that is unlocked, an error will be returned. +.Pp +It is advised that +.Dv PTHREAD_MUTEX_RECURSIVE +mutexes are not used with condition variables. +This is because of the implicit unlocking done by +.Xr pthread_cond_wait 3 +and +.Xr pthread_cond_timedwait 3 . +.It Dv PTHREAD_MUTEX_DEFAULT +Also this type of mutex will cause undefined behavior if reentered. +Unlocking a +.Dv PTHREAD_MUTEX_DEFAULT +mutex locked by another thread will result in undefined behavior. +Attempts to unlock an already unlocked +.Dv PTHREAD_MUTEX_DEFAULT +mutex will result in undefined behavior. +.Pp +This is the default mutex type for +.Fn pthread_mutexaddr_init . +.El +.Pp +The +.Fn pthread_mutexattr_gettype +functions copy the type value of the attribute to the location +pointed to by the second parameter. +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +The +.Fn pthread_mutexattr_init +function shall fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +Insufficient memory exists to initialize the mutex attributes object. +.El +.Pp +The +.Fn pthread_mutexattr_settype +function shall fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified either by +.Fa type +or +.Fa attr +is invalid. +.El +.Pp +No error numbers are defined for the +.Fn pthread_mutexattr_destroy +and +.Fn pthread_mutexattr_gettype +functions. +.\" +.\" .Pp +.\" .Fn pthread_mutexattr_setprioceiling +.\" may fail if: +.\" .Bl -tag -width Er +.\" .It Bq Er EINVAL +.\" Invalid value for +.\" .Fa attr , +.\" or invalid value for +.\" .Fa prioceiling . +.\" .El +.\" .Pp +.\" .Fn pthread_mutexattr_getprioceiling +.\" may fail if: +.\" .Bl -tag -width Er +.\" .It Bq Er EINVAL +.\" Invalid value for +.\" .Fa attr . +.\" .El +.\" .Pp +.\" .Fn pthread_mutexattr_setprotocol +.\" may fail if: +.\" .Bl -tag -width Er +.\" .It Bq Er EINVAL +.\" Invalid value for +.\" .Fa attr , +.\" or invalid value for +.\" .Fa protocol . +.\" .El +.\" .Pp +.\" .Fn pthread_mutexattr_getprotocol +.\" may fail if: +.\" .Bl -tag -width Er +.\" .It Bq Er EINVAL +.\" Invalid value for +.\" .Fa attr . +.\" .El +.\" .Pp +.Sh SEE ALSO +.Xr pthread_mutex_init 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_once.3 b/lib/libpthread/pthread_once.3 new file mode 100644 index 000000000..e0aa9da2c --- /dev/null +++ b/lib/libpthread/pthread_once.3 @@ -0,0 +1,128 @@ +.\" $NetBSD: pthread_once.3,v 1.9 2012/11/12 23:28:11 uwe Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_once.3,v 1.14 2002/09/16 19:29:29 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_ONCE 3 +.Os +.Sh NAME +.Nm pthread_once +.Nd dynamic package initialization +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_once "pthread_once_t *once_control" "void (*init_routine)(void)" +.Vt pthread_once_t once_control No = Dv PTHREAD_ONCE_INIT; +.Sh DESCRIPTION +The first call to +.Fn pthread_once +by any thread in a process, with a given +.Fa once_control , +will call the +.Fa init_routine Ns () +with no arguments. +Subsequent calls to +.Fn pthread_once +with the same +.Fa once_control +will not call the +.Fa init_routine Ns (). +On return from +.Fn pthread_once , +it is guaranteed that +.Fa init_routine Ns () +has completed. +The +.Fa once_control +parameter is used to determine whether the associated initialization +routine has been called. +.Pp +The function +.Fn pthread_once +is not a cancellation point. +However, if +.Fa init_routine Ns () +is a cancellation point and is cancelled, the effect on +.Fa once_control +is as if +.Fn pthread_once +was never called. +.Pp +The constant +.Dv PTHREAD_ONCE_INIT +initializes the static once synchronization control structure +.Fa once_control +to be used with +.Fn pthread_once . +The behavior of +.Fn pthread_once +is undefined if +.Fa once_control +has automatic storage duration or is not initialized by +.Dv PTHREAD_ONCE_INIT . +.Sh RETURN VALUES +If successful, the +.Fn pthread_once +function will return zero. +Otherwise an error number will be returned to +indicate the error. +.Sh ERRORS +None. +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_once.c b/lib/libpthread/pthread_once.c new file mode 100644 index 000000000..a4033c4e3 --- /dev/null +++ b/lib/libpthread/pthread_once.c @@ -0,0 +1,72 @@ +/* $NetBSD: pthread_once.c,v 1.3 2013/03/21 16:49:12 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams, and by Jason R. Thorpe. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_once.c,v 1.3 2013/03/21 16:49:12 christos Exp $"); + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +static void +once_cleanup(void *closure) +{ + + pthread_mutex_unlock((pthread_mutex_t *)closure); +} + +int +pthread_once(pthread_once_t *once_control, void (*routine)(void)) +{ + if (__predict_false(__uselibcstub)) + return __libc_thr_once_stub(once_control, routine); + + if (once_control->pto_done == 0) { + pthread_mutex_lock(&once_control->pto_mutex); + pthread_cleanup_push(&once_cleanup, &once_control->pto_mutex); + if (once_control->pto_done == 0) { + routine(); + once_control->pto_done = 1; + } + pthread_cleanup_pop(1); + } + + return 0; +} + +__strong_alias(__libc_thr_once,pthread_once) diff --git a/lib/libpthread/pthread_queue.h b/lib/libpthread/pthread_queue.h new file mode 100644 index 000000000..d3f6cf2a0 --- /dev/null +++ b/lib/libpthread/pthread_queue.h @@ -0,0 +1,137 @@ +/* $NetBSD: pthread_queue.h,v 1.5 2009/10/05 23:33:48 rmind Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_QUEUE_H +#define _LIB_PTHREAD_QUEUE_H + +/* + * Definition of a queue interface for the pthread library. + * Style modeled on the sys/queue.h macros; implementation taken from + * the tail queue, with the added property of static initializability + * (and a corresponding extra cost in the _INSERT_TAIL() function. +*/ + +/* + * Queue definitions. + */ + +#define PTQ_HEAD(name, type) \ +struct name { \ + struct type *ptqh_first;/* first element */ \ + struct type **ptqh_last;/* addr of last next element */ \ +} + +#define PTQ_HEAD_INITIALIZER { NULL, NULL } + +#define PTQ_ENTRY(type) \ +struct { \ + struct type *ptqe_next; /* next element */ \ + struct type **ptqe_prev;/* address of previous next element */ \ +} + +/* + * Queue functions. + */ + +#define PTQ_INIT(head) do { \ + (head)->ptqh_first = NULL; \ + (head)->ptqh_last = &(head)->ptqh_first; \ +} while (/*CONSTCOND*/0) + +#define PTQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.ptqe_next = (head)->ptqh_first) != NULL) \ + (head)->ptqh_first->field.ptqe_prev = \ + &(elm)->field.ptqe_next; \ + else \ + (head)->ptqh_last = &(elm)->field.ptqe_next; \ + (head)->ptqh_first = (elm); \ + (elm)->field.ptqe_prev = &(head)->ptqh_first; \ +} while (/*CONSTCOND*/0) + +#define PTQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.ptqe_next = NULL; \ + if ((head)->ptqh_last == NULL) \ + (head)->ptqh_last = &(head)->ptqh_first; \ + (elm)->field.ptqe_prev = (head)->ptqh_last; \ + *(head)->ptqh_last = (elm); \ + (head)->ptqh_last = &(elm)->field.ptqe_next; \ +} while (/*CONSTCOND*/0) + +#define PTQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.ptqe_next = (listelm)->field.ptqe_next) != NULL)\ + (elm)->field.ptqe_next->field.ptqe_prev = \ + &(elm)->field.ptqe_next; \ + else \ + (head)->ptqh_last = &(elm)->field.ptqe_next; \ + (listelm)->field.ptqe_next = (elm); \ + (elm)->field.ptqe_prev = &(listelm)->field.ptqe_next; \ +} while (/*CONSTCOND*/0) + +#define PTQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.ptqe_prev = (listelm)->field.ptqe_prev; \ + (elm)->field.ptqe_next = (listelm); \ + *(listelm)->field.ptqe_prev = (elm); \ + (listelm)->field.ptqe_prev = &(elm)->field.ptqe_next; \ +} while (/*CONSTCOND*/0) + +#define PTQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.ptqe_next) != NULL) \ + (elm)->field.ptqe_next->field.ptqe_prev = \ + (elm)->field.ptqe_prev; \ + else \ + (head)->ptqh_last = (elm)->field.ptqe_prev; \ + *(elm)->field.ptqe_prev = (elm)->field.ptqe_next; \ +} while (/*CONSTCOND*/0) + +/* + * Queue access methods. + */ + +#define PTQ_EMPTY(head) ((head)->ptqh_first == NULL) +#define PTQ_FIRST(head) ((head)->ptqh_first) +#define PTQ_NEXT(elm, field) ((elm)->field.ptqe_next) + +#define PTQ_LAST(head, headname) \ + (*(((struct headname *)(void *)((head)->ptqh_last))->ptqh_last)) +#define PTQ_PREV(elm, headname, field) \ + (*(((struct headname *)(void *)((elm)->field.ptqe_prev))->ptqh_last)) + +#define PTQ_FOREACH(var, head, field) \ + for ((var) = ((head)->ptqh_first); \ + (var); \ + (var) = ((var)->field.ptqe_next)) + +#define PTQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)(void *)((head)->ptqh_last))->ptqh_last)); \ + (var); \ + (var) = (*(((struct headname *)(void *)((var)->field.ptqe_prev))->ptqh_last))) + +#endif /* _LIB_PTHREAD_QUEUE_H */ diff --git a/lib/libpthread/pthread_rwlock.3 b/lib/libpthread/pthread_rwlock.3 new file mode 100644 index 000000000..75b5fb665 --- /dev/null +++ b/lib/libpthread/pthread_rwlock.3 @@ -0,0 +1,346 @@ +.\" $NetBSD: pthread_rwlock.3,v 1.5 2012/11/12 23:34:50 uwe Exp $ +.\" +.\" Copyright (c) 2002, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. +.\" +.\" ---------------------------------------------------------------------------- +.Dd July 8, 2010 +.Dt PTHREAD_RWLOCK 3 +.Os +.Sh NAME +.Nm pthread_rwlock +.Nd read/write lock interface +.Sh LIBRARY +.Lb libpthread +.\" ---------------------------------------------------------------------------- +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_rwlock_init "pthread_rwlock_t * restrict lock" \ +"const pthread_rwlockattr_t * restrict attr" +.Vt pthread_rwlock_t lock No = Dv PTHREAD_RWLOCK_INITIALIZER; +.Ft int +.Fn pthread_rwlock_destroy "pthread_rwlock_t *lock" +.Ft int +.Fn pthread_rwlock_rdlock "pthread_rwlock_t *lock" +.Ft int +.Fn pthread_rwlock_timedrdlock "pthread_rwlock_t * restrict lock" \ +"const struct timespec * restrict abstime" +.Ft int +.Fn pthread_rwlock_tryrdlock "pthread_rwlock_t *lock" +.Ft int +.Fn pthread_rwlock_wrlock "pthread_rwlock_t *lock" +.Ft int +.Fn pthread_rwlock_timedwrlock "pthread_rwlock_t * restrict lock" \ +"const struct timespec * restrict abstime" +.Ft int +.Fn pthread_rwlock_trywrlock "pthread_rwlock_t *lock" +.Ft int +.Fn pthread_rwlock_unlock "pthread_rwlock_t *lock" +.\" ---------------------------------------------------------------------------- +.Sh DESCRIPTION +The +.Fn pthread_rwlock_init +function is used to initialize a read/write lock, with attributes +specified by +.Fa attr . +If +.Fa attr +is +.Dv NULL , +the default read/write lock attributes are used. +.Pp +The results of calling +.Fn pthread_rwlock_init +with an already initialized lock are undefined. +.Pp +The macro +.Dv PTHREAD_RWLOCK_INITIALIZER +can be used to initialize a read/write lock when the allocation can be done +statically, no error checking is required, and the default attributes are +appropriate. +The behavior is similar to calling +.Fn pthread_rwlock_init +with +.Fa attr +specified as +.Dv NULL . +.Pp +.\" ----- +The +.Fn pthread_rwlock_destroy +function is used to destroy a read/write lock previously created with +.Fn pthread_rwlock_init . +.Pp +.\" ----- +The +.Fn pthread_rwlock_rdlock +function acquires a read lock on +.Fa lock +provided that +.Fa lock +is not presently held for writing and no writer threads are +presently blocked on the lock. +If the read lock cannot be immediately acquired, the calling thread +blocks until it can acquire the lock. +.Pp +The +.Fn pthread_rwlock_timedrdlock +performs the same action, but will not wait beyond +.Fa abstime +to obtain the lock before returning. +.Pp +The +.Fn pthread_rwlock_tryrdlock +function performs the same action as +.Fn pthread_rwlock_rdlock , +but does not block if the lock cannot be immediately obtained (i.e., +the lock is held for writing or there are waiting writers). +.Pp +A thread may hold multiple concurrent read locks. +If so, +.Fn pthread_rwlock_unlock +must be called once for each lock obtained. +.Pp +The results of acquiring a read lock while the calling thread holds +a write lock are undefined. +.Pp +.\" ----- +The +.Fn pthread_rwlock_wrlock +function blocks until a write lock can be acquired against +.Fa lock . +.Pp +The +.Fn pthread_rwlock_timedwrlock +performs the same action, but will not wait beyond +.Fa abstime +to obtain the lock before returning. +.Pp +The +.Fn pthread_rwlock_trywrlock +function performs the same action as +.Fn pthread_rwlock_wrlock , +but does not block if the lock cannot be immediately obtained. +.Pp +The results are undefined if the calling thread already holds the +lock at the time the call is made. +.Pp +.\" ----- +The +.Fn pthread_rwlock_unlock +function is used to release the read/write lock previously obtained by +.Fn pthread_rwlock_rdlock , +.Fn pthread_rwlock_wrlock , +.Fn pthread_rwlock_tryrdlock , +or +.Fn pthread_rwlock_trywrlock . +.\" ---------------------------------------------------------------------------- +.Sh RETURN VALUES +If successful, the +.Fn pthread_rwlock_init +function will return zero. +Otherwise an error number will be returned to indicate the error. +.Pp +If successful, the +.Fn pthread_rwlock_destroy , +.Fn pthread_rwlock_rdlock , +.Fn pthread_rwlock_timedrdlock , +.Fn pthread_rwlock_tryrdlock , +.Fn pthread_rwlock_wrlock , +.Fn pthread_rwlock_timedwrlock , +.Fn pthread_rwlock_trywrlock , +and +.Fn pthread_rwlock_unlock +will return zero. +Otherwise an error number will be returned to indicate the error. +.Pp +The results are undefined if +.Fa lock +is not held by the calling thread. +.\" ---------------------------------------------------------------------------- +.Sh ERRORS +The +.Fn pthread_rwlock_init +function may fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The system lacks the resources to initialize another read-write lock. +.It Bq Er EBUSY +The system has detected an attempt to re-initialize the object +referenced by +.Fa lock , +a previously initialized but not yet destroyed read/write lock. +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.It Bq Er ENOMEM +Insufficient memory exists to initialize the read-write lock. +.El +.Pp +.\" ----- +The +.Fn pthread_rwlock_destroy +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The system has detected an attempt to destroy the object referenced by +.Fa lock +while it is locked. +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_rwlock_tryrdlock +function shall fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The lock could not be acquired because a writer holds the lock or +was blocked on it. +.El +.Pp +The +.Fn pthread_rwlock_timedrdlock +function shall fail if: +.Bl -tag -width Er +.It Bq Er ETIMEDOUT +The time specified by +.Fa abstime +was reached before the lock could be obtained. +.El +.Pp +The +.Fn pthread_rwlock_rdlock , +.Fn pthread_rwlock_timedrdlock , +and +.Fn pthread_rwlock_tryrdlock +functions may fail if: +.Bl -tag -width Er +.It Bq Er EAGAIN +The lock could not be acquired because the maximum number of read locks +against +.Fa lock +has been exceeded. +.It Bq Er EDEADLK +The current thread already owns +.Fa lock +for writing. +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_rwlock_trywrlock +function shall fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The calling thread is not able to acquire the lock without blocking. +.El +.Pp +The +.Fn pthread_rwlock_timedrdlock +function shall fail if: +.Bl -tag -width Er +.It Bq Er ETIMEDOUT +The time specified by +.Fa abstime +was reached before the lock could be obtained. +.El +.Pp +The +.Fn pthread_rwlock_wrlock , +.Fn pthread_rwlock_timedwrlock , +and +.Fn pthread_rwlock_trywrlock +functions may fail if: +.Bl -tag -width Er +.It Bq Er EDEADLK +The calling thread already owns the read/write lock (for reading +or writing). +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_rwlock_unlock +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.It Bq Er EPERM +The current thread does not own the read/write lock. +.El +.\" ---------------------------------------------------------------------------- +.Sh SEE ALSO +.Xr pthread 3 , +.Xr pthread_barrier 3 , +.Xr pthread_cond 3 , +.Xr pthread_mutex 3 , +.Xr pthread_rwlockattr 3 , +.Xr pthread_spin 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . +.\" ---------------------------------------------------------------------------- +.Sh BUGS +The +.Dv PTHREAD_PROCESS_SHARED +attribute is not supported. diff --git a/lib/libpthread/pthread_rwlock.c b/lib/libpthread/pthread_rwlock.c new file mode 100644 index 000000000..e5712abaa --- /dev/null +++ b/lib/libpthread/pthread_rwlock.c @@ -0,0 +1,664 @@ +/* $NetBSD: pthread_rwlock.c,v 1.33 2013/03/21 16:49:12 christos Exp $ */ + +/*- + * Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams, by Jason R. Thorpe, and by Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_rwlock.c,v 1.33 2013/03/21 16:49:12 christos Exp $"); + +#include +#include + +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +#define _RW_LOCKED 0 +#define _RW_WANT_WRITE 1 +#define _RW_WANT_READ 2 + +#if __GNUC_PREREQ__(3, 0) +#define NOINLINE __attribute ((noinline)) +#else +#define NOINLINE /* nothing */ +#endif + +static int pthread__rwlock_wrlock(pthread_rwlock_t *, const struct timespec *); +static int pthread__rwlock_rdlock(pthread_rwlock_t *, const struct timespec *); +static void pthread__rwlock_early(void *); + +int _pthread_rwlock_held_np(pthread_rwlock_t *); +int _pthread_rwlock_rdheld_np(pthread_rwlock_t *); +int _pthread_rwlock_wrheld_np(pthread_rwlock_t *); + +#ifndef lint +__weak_alias(pthread_rwlock_held_np,_pthread_rwlock_held_np) +__weak_alias(pthread_rwlock_rdheld_np,_pthread_rwlock_rdheld_np) +__weak_alias(pthread_rwlock_wrheld_np,_pthread_rwlock_wrheld_np) +#endif + +__strong_alias(__libc_rwlock_init,pthread_rwlock_init) +__strong_alias(__libc_rwlock_rdlock,pthread_rwlock_rdlock) +__strong_alias(__libc_rwlock_wrlock,pthread_rwlock_wrlock) +__strong_alias(__libc_rwlock_tryrdlock,pthread_rwlock_tryrdlock) +__strong_alias(__libc_rwlock_trywrlock,pthread_rwlock_trywrlock) +__strong_alias(__libc_rwlock_unlock,pthread_rwlock_unlock) +__strong_alias(__libc_rwlock_destroy,pthread_rwlock_destroy) + +static inline uintptr_t +rw_cas(pthread_rwlock_t *ptr, uintptr_t o, uintptr_t n) +{ + + return (uintptr_t)atomic_cas_ptr(&ptr->ptr_owner, (void *)o, + (void *)n); +} + +int +pthread_rwlock_init(pthread_rwlock_t *ptr, + const pthread_rwlockattr_t *attr) +{ + if (__predict_false(__uselibcstub)) + return __libc_rwlock_init_stub(ptr, attr); + + if (attr && (attr->ptra_magic != _PT_RWLOCKATTR_MAGIC)) + return EINVAL; + ptr->ptr_magic = _PT_RWLOCK_MAGIC; + PTQ_INIT(&ptr->ptr_rblocked); + PTQ_INIT(&ptr->ptr_wblocked); + ptr->ptr_nreaders = 0; + ptr->ptr_owner = NULL; + + return 0; +} + + +int +pthread_rwlock_destroy(pthread_rwlock_t *ptr) +{ + if (__predict_false(__uselibcstub)) + return __libc_rwlock_destroy_stub(ptr); + + if ((ptr->ptr_magic != _PT_RWLOCK_MAGIC) || + (!PTQ_EMPTY(&ptr->ptr_rblocked)) || + (!PTQ_EMPTY(&ptr->ptr_wblocked)) || + (ptr->ptr_nreaders != 0) || + (ptr->ptr_owner != NULL)) + return EINVAL; + ptr->ptr_magic = _PT_RWLOCK_DEAD; + + return 0; +} + +/* We want function call overhead. */ +NOINLINE static void +pthread__rwlock_pause(void) +{ + + pthread__smt_pause(); +} + +NOINLINE static int +pthread__rwlock_spin(uintptr_t owner) +{ + pthread_t thread; + unsigned int i; + + thread = (pthread_t)(owner & RW_THREAD); + if (thread == NULL || (owner & ~RW_THREAD) != RW_WRITE_LOCKED) + return 0; + if (thread->pt_lwpctl->lc_curcpu == LWPCTL_CPU_NONE || + thread->pt_blocking) + return 0; + for (i = 128; i != 0; i--) + pthread__rwlock_pause(); + return 1; +} + +static int +pthread__rwlock_rdlock(pthread_rwlock_t *ptr, const struct timespec *ts) +{ + uintptr_t owner, next; + pthread_mutex_t *interlock; + pthread_t self; + int error; + +#ifdef ERRORCHECK + if (ptr->ptr_magic != _PT_RWLOCK_MAGIC) + return EINVAL; +#endif + + for (owner = (uintptr_t)ptr->ptr_owner;; owner = next) { + /* + * Read the lock owner field. If the need-to-wait + * indicator is clear, then try to acquire the lock. + */ + if ((owner & (RW_WRITE_LOCKED | RW_WRITE_WANTED)) == 0) { + next = rw_cas(ptr, owner, owner + RW_READ_INCR); + if (owner == next) { + /* Got it! */ +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + + /* + * Didn't get it -- spin around again (we'll + * probably sleep on the next iteration). + */ + continue; + } + + self = pthread__self(); + if ((owner & RW_THREAD) == (uintptr_t)self) + return EDEADLK; + + /* If held write locked and no waiters, spin. */ + if (pthread__rwlock_spin(owner)) { + while (pthread__rwlock_spin(owner)) { + owner = (uintptr_t)ptr->ptr_owner; + } + next = owner; + continue; + } + + /* + * Grab the interlock. Once we have that, we + * can adjust the waiter bits and sleep queue. + */ + interlock = pthread__hashlock(ptr); + pthread_mutex_lock(interlock); + + /* + * Mark the rwlock as having waiters. If the set fails, + * then we may not need to sleep and should spin again. + */ + next = rw_cas(ptr, owner, owner | RW_HAS_WAITERS); + if (owner != next) { + pthread_mutex_unlock(interlock); + continue; + } + + /* The waiters bit is set - it's safe to sleep. */ + PTQ_INSERT_HEAD(&ptr->ptr_rblocked, self, pt_sleep); + ptr->ptr_nreaders++; + self->pt_rwlocked = _RW_WANT_READ; + self->pt_sleepobj = &ptr->ptr_rblocked; + self->pt_early = pthread__rwlock_early; + error = pthread__park(self, interlock, &ptr->ptr_rblocked, + ts, 0, &ptr->ptr_rblocked); + + /* Did we get the lock? */ + if (self->pt_rwlocked == _RW_LOCKED) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + if (error != 0) + return error; + + pthread__errorfunc(__FILE__, __LINE__, __func__, + "direct handoff failure"); + } +} + + +int +pthread_rwlock_tryrdlock(pthread_rwlock_t *ptr) +{ + uintptr_t owner, next; + + if (__predict_false(__uselibcstub)) + return __libc_rwlock_tryrdlock_stub(ptr); + +#ifdef ERRORCHECK + if (ptr->ptr_magic != _PT_RWLOCK_MAGIC) + return EINVAL; +#endif + + /* + * Don't get a readlock if there is a writer or if there are waiting + * writers; i.e. prefer writers to readers. This strategy is dictated + * by SUSv3. + */ + for (owner = (uintptr_t)ptr->ptr_owner;; owner = next) { + if ((owner & (RW_WRITE_LOCKED | RW_WRITE_WANTED)) != 0) + return EBUSY; + next = rw_cas(ptr, owner, owner + RW_READ_INCR); + if (owner == next) { + /* Got it! */ +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + } +} + +static int +pthread__rwlock_wrlock(pthread_rwlock_t *ptr, const struct timespec *ts) +{ + uintptr_t owner, next; + pthread_mutex_t *interlock; + pthread_t self; + int error; + + self = pthread__self(); + +#ifdef ERRORCHECK + if (ptr->ptr_magic != _PT_RWLOCK_MAGIC) + return EINVAL; +#endif + + for (owner = (uintptr_t)ptr->ptr_owner;; owner = next) { + /* + * Read the lock owner field. If the need-to-wait + * indicator is clear, then try to acquire the lock. + */ + if ((owner & RW_THREAD) == 0) { + next = rw_cas(ptr, owner, + (uintptr_t)self | RW_WRITE_LOCKED); + if (owner == next) { + /* Got it! */ +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + + /* + * Didn't get it -- spin around again (we'll + * probably sleep on the next iteration). + */ + continue; + } + + if ((owner & RW_THREAD) == (uintptr_t)self) + return EDEADLK; + + /* If held write locked and no waiters, spin. */ + if (pthread__rwlock_spin(owner)) { + while (pthread__rwlock_spin(owner)) { + owner = (uintptr_t)ptr->ptr_owner; + } + next = owner; + continue; + } + + /* + * Grab the interlock. Once we have that, we + * can adjust the waiter bits and sleep queue. + */ + interlock = pthread__hashlock(ptr); + pthread_mutex_lock(interlock); + + /* + * Mark the rwlock as having waiters. If the set fails, + * then we may not need to sleep and should spin again. + */ + next = rw_cas(ptr, owner, + owner | RW_HAS_WAITERS | RW_WRITE_WANTED); + if (owner != next) { + pthread_mutex_unlock(interlock); + continue; + } + + /* The waiters bit is set - it's safe to sleep. */ + PTQ_INSERT_TAIL(&ptr->ptr_wblocked, self, pt_sleep); + self->pt_rwlocked = _RW_WANT_WRITE; + self->pt_sleepobj = &ptr->ptr_wblocked; + self->pt_early = pthread__rwlock_early; + error = pthread__park(self, interlock, &ptr->ptr_wblocked, + ts, 0, &ptr->ptr_wblocked); + + /* Did we get the lock? */ + if (self->pt_rwlocked == _RW_LOCKED) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + if (error != 0) + return error; + + pthread__errorfunc(__FILE__, __LINE__, __func__, + "direct handoff failure"); + } +} + + +int +pthread_rwlock_trywrlock(pthread_rwlock_t *ptr) +{ + uintptr_t owner, next; + pthread_t self; + + if (__predict_false(__uselibcstub)) + return __libc_rwlock_trywrlock_stub(ptr); + +#ifdef ERRORCHECK + if (ptr->ptr_magic != _PT_RWLOCK_MAGIC) + return EINVAL; +#endif + + self = pthread__self(); + + for (owner = (uintptr_t)ptr->ptr_owner;; owner = next) { + if (owner != 0) + return EBUSY; + next = rw_cas(ptr, owner, (uintptr_t)self | RW_WRITE_LOCKED); + if (owner == next) { + /* Got it! */ +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + } +} + +int +pthread_rwlock_rdlock(pthread_rwlock_t *ptr) +{ + if (__predict_false(__uselibcstub)) + return __libc_rwlock_rdlock_stub(ptr); + + return pthread__rwlock_rdlock(ptr, NULL); +} + +int +pthread_rwlock_timedrdlock(pthread_rwlock_t *ptr, + const struct timespec *abs_timeout) +{ + if (abs_timeout == NULL) + return EINVAL; + if ((abs_timeout->tv_nsec >= 1000000000) || + (abs_timeout->tv_nsec < 0) || + (abs_timeout->tv_sec < 0)) + return EINVAL; + + return pthread__rwlock_rdlock(ptr, abs_timeout); +} + +int +pthread_rwlock_wrlock(pthread_rwlock_t *ptr) +{ + if (__predict_false(__uselibcstub)) + return __libc_rwlock_wrlock_stub(ptr); + + return pthread__rwlock_wrlock(ptr, NULL); +} + +int +pthread_rwlock_timedwrlock(pthread_rwlock_t *ptr, + const struct timespec *abs_timeout) +{ + if (abs_timeout == NULL) + return EINVAL; + if ((abs_timeout->tv_nsec >= 1000000000) || + (abs_timeout->tv_nsec < 0) || + (abs_timeout->tv_sec < 0)) + return EINVAL; + + return pthread__rwlock_wrlock(ptr, abs_timeout); +} + + +int +pthread_rwlock_unlock(pthread_rwlock_t *ptr) +{ + uintptr_t owner, decr, new, next; + pthread_mutex_t *interlock; + pthread_t self, thread; + + if (__predict_false(__uselibcstub)) + return __libc_rwlock_unlock_stub(ptr); + +#ifdef ERRORCHECK + if ((ptr == NULL) || (ptr->ptr_magic != _PT_RWLOCK_MAGIC)) + return EINVAL; +#endif + +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_exit(); +#endif + + /* + * Since we used an add operation to set the required lock + * bits, we can use a subtract to clear them, which makes + * the read-release and write-release path similar. + */ + owner = (uintptr_t)ptr->ptr_owner; + if ((owner & RW_WRITE_LOCKED) != 0) { + self = pthread__self(); + decr = (uintptr_t)self | RW_WRITE_LOCKED; + if ((owner & RW_THREAD) != (uintptr_t)self) { + return EPERM; + } + } else { + decr = RW_READ_INCR; + if (owner == 0) { + return EPERM; + } + } + + for (;; owner = next) { + /* + * Compute what we expect the new value of the lock to be. + * Only proceed to do direct handoff if there are waiters, + * and if the lock would become unowned. + */ + new = (owner - decr); + if ((new & (RW_THREAD | RW_HAS_WAITERS)) != RW_HAS_WAITERS) { + next = rw_cas(ptr, owner, new); + if (owner == next) { + /* Released! */ + return 0; + } + continue; + } + + /* + * Grab the interlock. Once we have that, we can adjust + * the waiter bits. We must check to see if there are + * still waiters before proceeding. + */ + interlock = pthread__hashlock(ptr); + pthread_mutex_lock(interlock); + owner = (uintptr_t)ptr->ptr_owner; + if ((owner & RW_HAS_WAITERS) == 0) { + pthread_mutex_unlock(interlock); + next = owner; + continue; + } + + /* + * Give the lock away. SUSv3 dictates that we must give + * preference to writers. + */ + self = pthread__self(); + if ((thread = PTQ_FIRST(&ptr->ptr_wblocked)) != NULL) { + new = (uintptr_t)thread | RW_WRITE_LOCKED; + + if (PTQ_NEXT(thread, pt_sleep) != NULL) + new |= RW_HAS_WAITERS | RW_WRITE_WANTED; + else if (ptr->ptr_nreaders != 0) + new |= RW_HAS_WAITERS; + + /* + * Set in the new value. The lock becomes owned + * by the writer that we are about to wake. + */ + (void)atomic_swap_ptr(&ptr->ptr_owner, (void *)new); + + /* Wake the writer. */ + thread->pt_rwlocked = _RW_LOCKED; + pthread__unpark(&ptr->ptr_wblocked, self, + interlock); + } else { + new = 0; + PTQ_FOREACH(thread, &ptr->ptr_rblocked, pt_sleep) { + /* + * May have already been handed the lock, + * since pthread__unpark_all() can release + * our interlock before awakening all + * threads. + */ + if (thread->pt_sleepobj == NULL) + continue; + new += RW_READ_INCR; + thread->pt_rwlocked = _RW_LOCKED; + } + + /* + * Set in the new value. The lock becomes owned + * by the readers that we are about to wake. + */ + (void)atomic_swap_ptr(&ptr->ptr_owner, (void *)new); + + /* Wake up all sleeping readers. */ + ptr->ptr_nreaders = 0; + pthread__unpark_all(&ptr->ptr_rblocked, self, + interlock); + } + pthread_mutex_unlock(interlock); + + return 0; + } +} + +/* + * Called when a timedlock awakens early to adjust the waiter bits. + * The rwlock's interlock is held on entry, and the caller has been + * removed from the waiters lists. + */ +static void +pthread__rwlock_early(void *obj) +{ + uintptr_t owner, set, new, next; + pthread_rwlock_t *ptr; + pthread_t self; + u_int off; + + self = pthread__self(); + + switch (self->pt_rwlocked) { + case _RW_WANT_READ: + off = offsetof(pthread_rwlock_t, ptr_rblocked); + break; + case _RW_WANT_WRITE: + off = offsetof(pthread_rwlock_t, ptr_wblocked); + break; + default: + pthread__errorfunc(__FILE__, __LINE__, __func__, + "bad value of pt_rwlocked"); + off = 0; + /* NOTREACHED */ + break; + } + + /* LINTED mind your own business */ + ptr = (pthread_rwlock_t *)((uint8_t *)obj - off); + owner = (uintptr_t)ptr->ptr_owner; + + if ((owner & RW_THREAD) == 0) { + pthread__errorfunc(__FILE__, __LINE__, __func__, + "lock not held"); + } + + if (!PTQ_EMPTY(&ptr->ptr_wblocked)) + set = RW_HAS_WAITERS | RW_WRITE_WANTED; + else if (ptr->ptr_nreaders != 0) + set = RW_HAS_WAITERS; + else + set = 0; + + for (;; owner = next) { + new = (owner & ~(RW_HAS_WAITERS | RW_WRITE_WANTED)) | set; + next = rw_cas(ptr, owner, new); + if (owner == next) + break; + } +} + +int +_pthread_rwlock_held_np(pthread_rwlock_t *ptr) +{ + uintptr_t owner = (uintptr_t)ptr->ptr_owner; + + if ((owner & RW_WRITE_LOCKED) != 0) + return (owner & RW_THREAD) == (uintptr_t)pthread__self(); + return (owner & RW_THREAD) != 0; +} + +int +_pthread_rwlock_rdheld_np(pthread_rwlock_t *ptr) +{ + uintptr_t owner = (uintptr_t)ptr->ptr_owner; + + return (owner & RW_THREAD) != 0 && (owner & RW_WRITE_LOCKED) == 0; +} + +int +_pthread_rwlock_wrheld_np(pthread_rwlock_t *ptr) +{ + uintptr_t owner = (uintptr_t)ptr->ptr_owner; + + return (owner & (RW_THREAD | RW_WRITE_LOCKED)) == + ((uintptr_t)pthread__self() | RW_WRITE_LOCKED); +} + +int +pthread_rwlockattr_init(pthread_rwlockattr_t *attr) +{ + + if (attr == NULL) + return EINVAL; + attr->ptra_magic = _PT_RWLOCKATTR_MAGIC; + + return 0; +} + + +int +pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) +{ + + if ((attr == NULL) || + (attr->ptra_magic != _PT_RWLOCKATTR_MAGIC)) + return EINVAL; + attr->ptra_magic = _PT_RWLOCKATTR_DEAD; + + return 0; +} diff --git a/lib/libpthread/pthread_rwlockattr.3 b/lib/libpthread/pthread_rwlockattr.3 new file mode 100644 index 000000000..78ab06e86 --- /dev/null +++ b/lib/libpthread/pthread_rwlockattr.3 @@ -0,0 +1,105 @@ +.\" $NetBSD: pthread_rwlockattr.3,v 1.8 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_rwlockattr_init.3,v 1.7 2002/09/16 19:29:29 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_RWLOCKATTR 3 +.Os +.Sh NAME +.Nm pthread_rwlockattr_init , +.Nm pthread_rwlockattr_destroy +.Nd initialize or destroy read/write lock attributes +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_rwlockattr_init "pthread_rwlockattr_t *attr" +.Ft int +.Fn pthread_rwlockattr_destroy "pthread_rwlockattr_t *attr" +.Sh DESCRIPTION +The +.Fn pthread_rwlockattr_init +function is used to initialize a read/write lock attributes object. +.Pp +The +.Fn pthread_rwlockattr_destroy +function is used to destroy a read/write lock attribute object +previously created with +.Fn pthread_rwlockattr_init . +.Sh RETURN VALUES +If successful, the +.Fn pthread_rwlockattr_init +and +.Fn pthread_rwlockattr_destroy +functions return zero. +Otherwise an error number will be returned to indicate the error. +.Sh ERRORS +.Fn pthread_rwlockattr_init +shall fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +Insufficient memory exists to initialize the read/write lock attributes object. +.El +.Pp +.Fn pthread_rwlockattr_init +and +.Fn pthread_rwlockattr_destroy +may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa attr +is invalid. +.El +.Sh SEE ALSO +.Xr pthread_rwlock_init 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_schedparam.3 b/lib/libpthread/pthread_schedparam.3 new file mode 100644 index 000000000..2c76453cb --- /dev/null +++ b/lib/libpthread/pthread_schedparam.3 @@ -0,0 +1,120 @@ +.\" $NetBSD: pthread_schedparam.3,v 1.7 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_schedparam.3,v 1.7 2002/09/16 19:29:29 mini Exp $ +.Dd July 9, 2010 +.Dt PTHREAD_SCHEDPARAM 3 +.Os +.Sh NAME +.Nm pthread_setschedparam , +.Nm pthread_getschedparam +.Nd thread scheduling parameter manipulation +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_setschedparam "pthread_t thread" "int policy" "const struct sched_param *param" +.Ft int +.Fn pthread_getschedparam "pthread_t thread" "int * restrict policy" "struct sched_param * restrict param" +.Sh DESCRIPTION +The +.Fn pthread_setschedparam +and +.Fn pthread_getschedparam +functions set and get the scheduling parameters of individual threads. +The scheduling policy for a thread can be: +.Bl -tag -width SCHED_OTHER -offset indent +.It Dv SCHED_FIFO +First in, first out. +.It Dv SCHED_RR +Round-robin. +.It Dv SCHED_OTHER +The system default. +.El +.Pp +The thread priority (accessed via +.Va param-\*[Gt]sched_priority ) +must be at least +.Dv PTHREAD_MIN_PRIORITY +and no more than +.Dv PTHREAD_MAX_PRIORITY . +.Sh RETURN VALUES +If successful, these functions return 0. +Otherwise, an error number is returned to indicate the error. +.Sh ERRORS +.Fn pthread_setschedparam +may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Va policy +is invalid. +.It Bq Er ENOTSUP +Invalid value for scheduling parameters. +.It Bq Er ESRCH +Non-existent thread +.Va thread . +.El +.Pp +.Fn pthread_getschedparam +may fail if: +.Bl -tag -width Er +.It Bq Er ESRCH +Non-existent thread +.Va thread . +.El +.Sh SEE ALSO +.Xr pthread_attr_getschedparam 3 , +.Xr sched 3 +.Sh STANDARDS +Both functions conform to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_self.3 b/lib/libpthread/pthread_self.3 new file mode 100644 index 000000000..98fc831ff --- /dev/null +++ b/lib/libpthread/pthread_self.3 @@ -0,0 +1,86 @@ +.\" $NetBSD: pthread_self.3,v 1.4 2010/07/09 08:51:28 jruoho Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by John Birrell. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libpthread/man/pthread_self.3,v 1.10 2002/09/16 19:29:29 mini Exp $ +.\" +.Dd July 9, 2010 +.Dt PTHREAD_SELF 3 +.Os +.Sh NAME +.Nm pthread_self +.Nd get the calling thread's ID +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft pthread_t +.Fn pthread_self "void" +.Sh DESCRIPTION +The +.Fn pthread_self +function returns the thread +.Tn ID +of the calling thread. +.Sh RETURN VALUES +The return value is the thread +.Tn ID . +.Sh ERRORS +None. +.Sh SEE ALSO +.Xr pthread_create 3 , +.Xr pthread_equal 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_sigmask.3 b/lib/libpthread/pthread_sigmask.3 new file mode 100644 index 000000000..3286e11ca --- /dev/null +++ b/lib/libpthread/pthread_sigmask.3 @@ -0,0 +1,122 @@ +.\" $NetBSD: pthread_sigmask.3,v 1.9 2010/07/09 10:55:11 wiz Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" 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: src/lib/libpthread/man/pthread_sigmask.3,v 1.10 2002/09/16 19:29:29 mini Exp $ +.Dd July 9, 2010 +.Dt PTHREAD_SIGMASK 3 +.Os +.Sh NAME +.Nm pthread_sigmask +.Nd examine and/or change a thread's signal mask +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.\" .In pthread.h +.In signal.h +.Ft int +.Fn pthread_sigmask "int how" "const sigset_t * restrict set" "sigset_t * restrict oset" +.Sh DESCRIPTION +The +.Fn pthread_sigmask +function examines and/or changes the calling thread's signal mask. +.Pp +If +.Fa set +is not +.Dv NULL , +it specifies a set of signals to be modified, and +.Fa how +specifies what to set the signal mask to: +.Bl -tag -width SIG_UNBLOCK +.It Dv SIG_BLOCK +Union of the current mask and +.Fa set . +.It Dv SIG_UNBLOCK +Intersection of the current mask and the complement of +.Fa set . +.It Dv SIG_SETMASK +.Fa set . +.El +.Pp +If +.Fa oset +is not +.Dv NULL , +the previous signal mask is stored in the location pointed to by +.Fa oset . +.Pp +.Dv SIGKILL +and +.Dv SIGSTOP +cannot be blocked, and will be silently ignored if included in the signal mask. +.Sh RETURN VALUES +If successful, +.Fn pthread_sigmask +returns 0. +Otherwise, an error is returned. +.Sh ERRORS +.Fn pthread_sigmask +shall fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa how +is not one of the defined values. +.El +.Sh SEE ALSO +.Xr sigaction 2 , +.Xr sigpending 2 , +.Xr sigprocmask 2 , +.Xr sigsuspend 2 , +.Xr sigwait 2 , +.Xr sigsetops 3 +.Sh STANDARDS +The function conforms to +.St -p1003.1-2001 . diff --git a/lib/libpthread/pthread_specific.c b/lib/libpthread/pthread_specific.c new file mode 100644 index 000000000..5e0a2c304 --- /dev/null +++ b/lib/libpthread/pthread_specific.c @@ -0,0 +1,115 @@ +/* $NetBSD: pthread_specific.c,v 1.26 2013/03/21 16:49:12 christos Exp $ */ + +/*- + * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_specific.c,v 1.26 2013/03/21 16:49:12 christos Exp $"); + +/* Functions and structures dealing with thread-specific data */ + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +#include +#include + +#include "../libc/include/extern.h" /* for _sys_setcontext() */ + +int pthread_setcontext(const ucontext_t *); + +__strong_alias(__libc_thr_setspecific,pthread_setspecific) +__strong_alias(__libc_thr_getspecific,pthread_getspecific) +__strong_alias(__libc_thr_curcpu,pthread_curcpu_np) + +__strong_alias(setcontext,pthread_setcontext) + +int +pthread_setspecific(pthread_key_t key, const void *value) +{ + pthread_t self; + + if (__predict_false(__uselibcstub)) + return __libc_thr_setspecific_stub(key, value); + + self = pthread__self(); + /* + * We can't win here on constness. Having been given a + * "const void *", we can only assign it to other const void *, + * and return it from functions that are const void *, without + * generating a warning. + */ + return pthread__add_specific(self, key, value); +} + +void * +pthread_getspecific(pthread_key_t key) +{ + if (__predict_false(__uselibcstub)) + return __libc_thr_getspecific_stub(key); + + return pthread__self()->pt_specific[key].pts_value; +} + +unsigned int +pthread_curcpu_np(void) +{ + if (__predict_false(__uselibcstub)) + return __libc_thr_curcpu_stub(); + + { + const int curcpu = pthread__self()->pt_lwpctl->lc_curcpu; + + pthread__assert(curcpu != LWPCTL_CPU_NONE); + pthread__assert(curcpu != LWPCTL_CPU_EXITED); + pthread__assert(curcpu >= 0); + return curcpu; + } +} + +/* + * Override setcontext so that pthread private pointer is preserved + */ +int +pthread_setcontext(const ucontext_t *ucp) +{ +#ifdef _UC_TLSBASE + ucontext_t uc; + /* + * Only copy and clear _UC_TLSBASE if it is set. + */ + if (ucp->uc_flags & _UC_TLSBASE) { + uc = *ucp; + uc.uc_flags &= ~_UC_TLSBASE; + ucp = &uc; + } +#endif /* _UC_TLSBASE */ + return _sys_setcontext(ucp); +} diff --git a/lib/libpthread/pthread_spin.3 b/lib/libpthread/pthread_spin.3 new file mode 100644 index 000000000..a687ea2ac --- /dev/null +++ b/lib/libpthread/pthread_spin.3 @@ -0,0 +1,208 @@ +.\" $NetBSD: pthread_spin.3,v 1.5 2010/07/09 10:55:11 wiz Exp $ +.\" +.\" Copyright (c) 2002, 2008, 2010 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.\" ---------------------------------------------------------------------------- +.Dd July 8, 2010 +.Dt PTHREAD_SPIN 3 +.Os +.Sh NAME +.Nm pthread_spin +.Nd spin lock interface +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_spin_init "pthread_spinlock_t *lock" "int pshared" +.Ft int +.Fn pthread_spin_destroy "pthread_spinlock_t *lock" +.Ft int +.Fn pthread_spin_lock "pthread_spinlock_t *lock" +.Ft int +.Fn pthread_spin_trylock "pthread_spinlock_t *lock" +.Ft int +.Fn pthread_spin_unlock "pthread_spinlock_t *lock" +.\" ---------------------------------------------------------------------------- +.Sh DESCRIPTION +The +.Fn pthread_spin_init +function is used to initialize a spin lock. +In the +.Nx +implementation the +.Fa pshared +parameter is currently unused and all spin locks exhibit the +.Dv PTHREAD_PROCESS_SHARED +property, implying that all spin locks may be +accessed by threads of multiple processes. +The results of calling +.Fn pthread_spin_init +with an already initialized lock are undefined. +.Pp +.\" ----- +The +.Fn pthread_spin_destroy +function is used to destroy a spin lock previously created with +.Fn pthread_spin_init . +It is undefined what happens if the function is called +when a thread holds the lock, or if the function is called +with an uninitialized spin lock. +.Pp +.\" ----- +The +.Fn pthread_spin_lock +function acquires a spin lock on +.Fa lock , +provided that +.Fa lock +is not presently held. +If the lock cannot be +immediately acquired, the calling thread repeatedly retries until it can +acquire the lock. +Undefined behavior may follow if the calling thread holds +the lock at the time the call is made. +.Pp +The +.Fn pthread_spin_trylock +function performs the same locking action, but does not block if the lock +cannot be immediately obtained; if the lock is held, the call fails. +.Pp +.\" ----- +The +.Fn pthread_spin_unlock +function is used to release the read/write lock previously obtained by +.Fn pthread_spin_lock +or +.Fn pthread_spin_trylock . +The results are undefined if the lock is not held by the calling thread. +.\" ---------------------------------------------------------------------------- +.Sh RETURN VALUES +If successful, all described functions return zero. +Otherwise an error number will be returned to indicate the error. +.Sh ERRORS +The +.Fn pthread_spin_init +function shall fail if: +.Bl -tag -width Er +.It Bq Er ENOMEM +Insufficient memory exists to initialize the lock. +.El +.Pp +The +.Fn pthread_spin_init +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa lock +parameter was +.Dv NULL +or the +.Fa pshared +parameter was neither +.Dv PTHREAD_PROCESS_SHARED +nor +.Dv PTHREAD_PROCESS_PRIVATE . +.El +.Pp +.\" ----- +The +.Fn pthread_spin_destroy +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The system has detected an attempt to destroy the object referenced by +.Fa lock +while it is locked. +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_spin_trylock +function shall fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The lock could not be acquired because a writer holds the lock or +was blocked on it. +.El +.Pp +The +.Fn pthread_spin_lock +function may fail if: +.Bl -tag -width Er +.It Bq Er EDEADLK +The current thread already owns +.Fa lock +for writing. +.El +.Pp +The +.Fn pthread_spin_lock +and +.Fn pthread_spin_trylock +functions may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.El +.Pp +.\" ----- +The +.Fn pthread_spin_unlock +function may fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The value specified by +.Fa lock +is invalid. +.El +.\" ---------------------------------------------------------------------------- +.Sh SEE ALSO +.Xr pthread 3 , +.Xr pthread_barrier 3 , +.Xr pthread_cond 3 , +.Xr pthread_mutex 3 , +.Xr pthread_rwlock 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . +.\" ---------------------------------------------------------------------------- +.Sh CAVEATS +Applications using spin locks are vulnerable to the effects of priority +inversion. +Applications using real-time threads +.Pq Dv SCHED_FIFO , +.Pq Dv SCHED_RR +should not use these interfaces. +Outside carefully controlled environments, priority inversion with spin locks +can lead to system deadlock. +Mutexes are preferable in nearly every possible use case. diff --git a/lib/libpthread/pthread_spin.c b/lib/libpthread/pthread_spin.c new file mode 100644 index 000000000..01738d73c --- /dev/null +++ b/lib/libpthread/pthread_spin.c @@ -0,0 +1,139 @@ +/* $NetBSD: pthread_spin.c,v 1.6 2012/08/16 04:49:47 matt Exp $ */ + +/*- + * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * Public (POSIX-specified) spinlocks. + */ + +#include +__RCSID("$NetBSD: pthread_spin.c,v 1.6 2012/08/16 04:49:47 matt Exp $"); + +#include +#include + +#include + +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" + +int +pthread_spin_init(pthread_spinlock_t *lock, int pshared) +{ + +#ifdef ERRORCHECK + if (lock == NULL || (pshared != PTHREAD_PROCESS_PRIVATE && + pshared != PTHREAD_PROCESS_SHARED)) + return EINVAL; +#endif + lock->pts_magic = _PT_SPINLOCK_MAGIC; + + /* + * We don't actually use the pshared flag for anything; + * CPU simple locks have all the process-shared properties + * that we want anyway. + */ + lock->pts_flags = pshared; + pthread_lockinit(&lock->pts_spin); + + return 0; +} + +int +pthread_spin_destroy(pthread_spinlock_t *lock) +{ + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; + if (!__SIMPLELOCK_UNLOCKED_P(&lock->pts_spin)) + return EBUSY; +#endif + + lock->pts_magic = _PT_SPINLOCK_DEAD; + + return 0; +} + +int +pthread_spin_lock(pthread_spinlock_t *lock) +{ + pthread_t self; + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; +#endif + + self = pthread__self(); + while (pthread__spintrylock(self, &lock->pts_spin) == 0) { + pthread__smt_pause(); + } + + return 0; +} + +int +pthread_spin_trylock(pthread_spinlock_t *lock) +{ + pthread_t self; + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; +#endif + + self = pthread__self(); + if (pthread__spintrylock(self, &lock->pts_spin) == 0) + return EBUSY; + return 0; +} + +int +pthread_spin_unlock(pthread_spinlock_t *lock) +{ + pthread_t self; + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; +#endif + + self = pthread__self(); + pthread__spinunlock(self, &lock->pts_spin); + pthread__smt_wake(); + + return 0; +} diff --git a/lib/libpthread/pthread_suspend_np.3 b/lib/libpthread/pthread_suspend_np.3 new file mode 100644 index 000000000..453ea06a9 --- /dev/null +++ b/lib/libpthread/pthread_suspend_np.3 @@ -0,0 +1,120 @@ +.\" $NetBSD: pthread_suspend_np.3,v 1.5 2010/07/09 09:18:45 jruoho Exp $ +.\" +.\" Copyright (c) 2003, 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christos Zoulas. +.\" +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. +.\" +.Dd July 9, 2010 +.Dt PTHREAD_SUSPEND_NP 3 +.Os +.Sh NAME +.Nm pthread_suspend_np , +.Nm pthread_resume_np +.Nd suspend/resume the given thread +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_suspend_np "pthread_t thread" +.Ft int +.Fn pthread_resume_np "pthread_t thread" +.Sh DESCRIPTION +The +.Fn pthread_suspend_np +function suspends the +.Fa thread +given as argument. +If +.Fa thread +is the currently running thread as returned by +.Xr pthread_self 3 , +the function fails and returns +.Er EDEADLK . +Otherwise, it removes the named thread from the running queue, and +adds it to the suspended queue. +The +.Fa thread +will remain blocked until +.Fn pthread_resume_np +is called on it. +In other words, +.Fn pthread_resume_np +resumes the +.Fa thread +given as argument, if it was suspended. +.Sh RETURN VALUES +Both functions return 0 on success and an error number indicating the +reason for the failure. +.Sh COMPATIBILITY +These functions are non-standard extensions. +.Sh ERRORS +The +.Fn pthread_suspend_np +function may fail if: +.Bl -tag -width Er +.It Bq Er EDEADLK +The thread requested to suspend was the currently running thread. +.It Bq Er ESRCH +The supplied +.Fa thread +was invalid. +.El +.Pp +The +.Fn pthread_resume_np +function may fail if: +.Bl -tag -width Er +.It Bq Er ESRCH +The supplied +.Fa thread +was invalid. +.El +.Sh NOTES +Some +.Fn pthread_suspend_np +implementations may allow suspending the current thread. +This is dangerous, because the semantics of the function would then +require the scheduler to schedule another thread, causing a thread +context switch. +Since that context switch can happen in a signal handler by someone +calling +.Fn pthread_suspend_np +in a signal handler, this is currently not allowed. +.Pp +In +.Fn pthread_resume_np +the +.Nx +implementation does not check if the +.Fa thread +argument is not already suspended. +Some implementations might return an error condition if +.Fn pthread_resume_np +is called on a non-suspended thread. +.Sh SEE ALSO +.Xr pthread_attr_setcreatesuspend_np 3 , +.Xr pthread_self 3 diff --git a/lib/libpthread/pthread_testcancel.3 b/lib/libpthread/pthread_testcancel.3 new file mode 100644 index 000000000..4c3858a31 --- /dev/null +++ b/lib/libpthread/pthread_testcancel.3 @@ -0,0 +1,271 @@ +.\" $NetBSD: pthread_testcancel.3,v 1.9 2014/03/18 18:20:38 riastradh Exp $ +.\" +.\" Copyright (c) 2002 The NetBSD Foundation, Inc. +.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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: src/lib/libpthread/man/pthread_testcancel.3,v 1.9 2002/09/16 19:29:29 mini Exp $ +.Dd August 6, 2010 +.Dt PTHREAD_TESTCANCEL 3 +.Os +.Sh NAME +.Nm pthread_setcancelstate , +.Nm pthread_setcanceltype , +.Nm pthread_testcancel +.Nd set cancelability state +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.Ft int +.Fn pthread_setcancelstate "int state" "int *oldstate" +.Ft int +.Fn pthread_setcanceltype "int type" "int *oldtype" +.Ft void +.Fn pthread_testcancel "void" +.Sh DESCRIPTION +The +.Fn pthread_setcancelstate +function atomically both sets the calling thread's cancelability state +to the indicated +.Fa state +and, if +.Fa oldstate +is not +.Dv NULL , +returns the previous cancelability state at the location referenced by +.Fa oldstate . +Legal values for +.Fa state +are +.Dv PTHREAD_CANCEL_ENABLE +and +.Dv PTHREAD_CANCEL_DISABLE . +.Pp +The +.Fn pthread_setcanceltype +function atomically both sets the calling thread's cancelability type +to the indicated +.Fa type +and, if +.Fa oldtype +is not +.Dv NULL , +returns the previous cancelability type at the location referenced by +.Fa oldtype . +Legal values for +.Fa type +are +.Dv PTHREAD_CANCEL_DEFERRED +and +.Dv PTHREAD_CANCEL_ASYNCHRONOUS . +.Pp +The cancelability state and type of any newly created threads, including the +thread in which +.Fn main +was first invoked, are +.Dv PTHREAD_CANCEL_ENABLE +and +.Dv PTHREAD_CANCEL_DEFERRED +respectively. +.Pp +The +.Fn pthread_testcancel +function creates a cancellation point in the calling thread. +The +.Fn pthread_testcancel +function has no effect if cancelability is disabled. +.Ss Cancelability States +The cancelability state of a thread determines the action taken upon +receipt of a cancellation request. +The thread may control cancellation in +a number of ways. +.Pp +Each thread maintains its own +.Dq cancelability state +which may be encoded in two bits: +.Bl -hang +.It Em Cancelability Enable +When cancelability is +.Dv PTHREAD_CANCEL_DISABLE , +cancellation requests against the target thread are held pending. +.It Em Cancelability Type +When cancelability is enabled and the cancelability type is +.Dv PTHREAD_CANCEL_ASYNCHRONOUS , +new or pending cancellation requests may be acted upon at any time. +When cancelability is enabled and the cancelability type is +.Dv PTHREAD_CANCEL_DEFERRED , +cancellation requests are held pending until a cancellation point (see +below) is reached. +If cancelability is disabled, the setting of the +cancelability type has no immediate effect as all cancellation requests +are held pending; however, once cancelability is enabled again the new +type will be in effect. +.El +.Ss Cancellation Points +Cancellation points will occur when a thread is executing the following +functions: +.Fn accept , +.Fn aio_suspend , +.Fn clock_nanosleep , +.Fn close , +.Fn connect , +.Fn creat , +.Fn fcntl , +.Fn fdatasync , +.Fn fsync , +.Fn fsync_range , +.\".Fn getmsg , +.\".Fn getpmsg , +.Fn kevent , +.\".Fn lockf , +.Fn mq_receive , +.Fn mq_send , +.Fn mq_timedreceive , +.Fn mq_timedsend , +.Fn msgrcv , +.Fn msgsnd , +.Fn msync , +.Fn nanosleep , +.Fn open , +.Fn pause , +.Fn poll , +.Fn pollts , +.Fn pread , +.Fn pselect , +.Fn pthread_cond_timedwait , +.Fn pthread_cond_wait , +.Fn pthread_join , +.Fn pthread_testcancel , +.\".Fn putmsg , +.\".Fn putpmsg , +.Fn pwrite , +.Fn read , +.Fn readv , +.Fn recv , +.Fn recvfrom , +.Fn recvmsg , +.Fn select , +.Fn sem_timedwait , +.Fn sem_wait , +.Fn send , +.Fn sendmsg , +.Fn sendto , +.Fn sigpause , +.Fn sigsuspend , +.Fn sigtimedwait , +.Fn sigwait , +.Fn sigwaitinfo , +.Fn sleep , +.Fn system , +.Fn tcdrain , +.Fn usleep , +.Fn wait , +.Fn wait4 , +.Fn waitid , +.Fn waitpid , +.Fn write , +and +.Fn writev . +.Sh RETURN VALUES +If successful, the +.Fn pthread_setcancelstate +and +.Fn pthread_setcanceltype +functions will return zero. +Otherwise, an error number shall be returned to +indicate the error. +.Pp +The +.Fn pthread_setcancelstate +and +.Fn pthread_setcanceltype +functions are used to control the points at which a thread may be +asynchronously canceled. +For cancellation control to be usable in modular +fashion, some rules must be followed. +.Pp +For purposes of this discussion, consider an object to be a generalization +of a procedure. +It is a set of procedures and global variables written as +a unit and called by clients not known by the object. +Objects may depend +on other objects. +.Pp +First, cancelability should only be disabled on entry to an object, never +explicitly enabled. +On exit from an object, the cancelability state should +always be restored to its value on entry to the object. +.Pp +This follows from a modularity argument: if the client of an object (or the +client of an object that uses that object) has disabled cancelability, it is +because the client doesn't want to have to worry about how to clean up if the +thread is canceled while executing some sequence of actions. +If an object +is called in such a state and it enables cancelability and a cancellation +request is pending for that thread, then the thread will be canceled, +contrary to the wish of the client that disabled. +.Pp +Second, the cancelability type may be explicitly set to either +.Em deferred +or +.Em asynchronous +upon entry to an object. +But as with the cancelability state, on exit from +an object that cancelability type should always be restored to its value on +entry to the object. +.Pp +Finally, only functions that are cancel-safe may be called from a thread that +is asynchronously cancelable. +.Sh ERRORS +The function +.Fn pthread_setcancelstate +may fail with: +.Bl -tag -width Er +.It Bq Er EINVAL +The specified state is not +.Dv PTHREAD_CANCEL_ENABLE +or +.Dv PTHREAD_CANCEL_DISABLE . +.El +.Pp +The function +.Fn pthread_setcanceltype +may fail with: +.Bl -tag -width Er +.It Bq Er EINVAL +The specified state is not +.Dv PTHREAD_CANCEL_DEFERRED +or +.Dv PTHREAD_CANCEL_ASYNCHRONOUS . +.El +.Sh SEE ALSO +.Xr pthread_cancel 3 +.Sh STANDARDS +These functions conform to +.St -p1003.1-2001 . +.Sh AUTHORS +This man page was written by +.An David Leonard Aq Mt d@openbsd.org +for the +.Ox +implementation of +.Xr pthread_cancel 3 . diff --git a/lib/libpthread/pthread_tsd.c b/lib/libpthread/pthread_tsd.c new file mode 100644 index 000000000..baceae9c9 --- /dev/null +++ b/lib/libpthread/pthread_tsd.c @@ -0,0 +1,363 @@ +/* $NetBSD: pthread_tsd.c,v 1.15 2015/08/25 13:46:23 pooka Exp $ */ + +/*- + * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams, by Andrew Doran, and by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +__RCSID("$NetBSD: pthread_tsd.c,v 1.15 2015/08/25 13:46:23 pooka Exp $"); + +/* Functions and structures dealing with thread-specific data */ +#include +#include + +#include "pthread.h" +#include "pthread_int.h" +#include "reentrant.h" + +int pthread_keys_max; +static pthread_mutex_t tsd_mutex = PTHREAD_MUTEX_INITIALIZER; +static int nextkey; + +PTQ_HEAD(pthread__tsd_list, pt_specific) *pthread__tsd_list = NULL; +void (**pthread__tsd_destructors)(void *) = NULL; + +__strong_alias(__libc_thr_keycreate,pthread_key_create) +__strong_alias(__libc_thr_keydelete,pthread_key_delete) + +static void +/*ARGSUSED*/ +null_destructor(void *p) +{ +} + +#include +#include +#include + +void * +pthread_tsd_init(size_t *tlen) +{ + char *pkm; + size_t alen; + char *arena; + + if ((pkm = pthread__getenv("PTHREAD_KEYS_MAX")) != NULL) { + pthread_keys_max = (int)strtol(pkm, NULL, 0); + if (pthread_keys_max < _POSIX_THREAD_KEYS_MAX) + pthread_keys_max = _POSIX_THREAD_KEYS_MAX; + } else { + pthread_keys_max = PTHREAD_KEYS_MAX; + } + + /* + * Can't use malloc here yet, because malloc will use the fake + * libc thread functions to initialize itself, so mmap the space. + */ + *tlen = sizeof(struct __pthread_st) + + pthread_keys_max * sizeof(struct pt_specific); + alen = *tlen + + sizeof(*pthread__tsd_list) * pthread_keys_max + + sizeof(*pthread__tsd_destructors) * pthread_keys_max; + + arena = mmap(NULL, alen, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); + if (arena == MAP_FAILED) { + pthread_keys_max = 0; + return NULL; + } + + pthread__tsd_list = (void *)arena; + arena += sizeof(*pthread__tsd_list) * pthread_keys_max; + pthread__tsd_destructors = (void *)arena; + arena += sizeof(*pthread__tsd_destructors) * pthread_keys_max; + return arena; +} + +int +pthread_key_create(pthread_key_t *key, void (*destructor)(void *)) +{ + int i; + + if (__predict_false(__uselibcstub)) + return __libc_thr_keycreate_stub(key, destructor); + + /* Get a lock on the allocation list */ + pthread_mutex_lock(&tsd_mutex); + + /* Find an available slot: + * The condition for an available slot is one with the destructor + * not being NULL. If the desired destructor is NULL we set it to + * our own internal destructor to satisfy the non NULL condition. + */ + /* 1. Search from "nextkey" to the end of the list. */ + for (i = nextkey; i < pthread_keys_max; i++) + if (pthread__tsd_destructors[i] == NULL) + break; + + if (i == pthread_keys_max) { + /* 2. If that didn't work, search from the start + * of the list back to "nextkey". + */ + for (i = 0; i < nextkey; i++) + if (pthread__tsd_destructors[i] == NULL) + break; + + if (i == nextkey) { + /* If we didn't find one here, there isn't one + * to be found. + */ + pthread_mutex_unlock(&tsd_mutex); + return EAGAIN; + } + } + + /* Got one. */ + pthread__assert(PTQ_EMPTY(&pthread__tsd_list[i])); + pthread__tsd_destructors[i] = destructor ? destructor : null_destructor; + + nextkey = (i + 1) % pthread_keys_max; + pthread_mutex_unlock(&tsd_mutex); + *key = i; + + return 0; +} + +/* + * Each thread holds an array of pthread_keys_max pt_specific list + * elements. When an element is used it is inserted into the appropriate + * key bucket of pthread__tsd_list. This means that ptqe_prev == NULL, + * means that the element is not threaded, ptqe_prev != NULL it is + * already part of the list. When we set to a NULL value we delete from the + * list if it was in the list, and when we set to non-NULL value, we insert + * in the list if it was not already there. + * + * We keep this global array of lists of threads that have called + * pthread_set_specific with non-null values, for each key so that + * we don't have to check all threads for non-NULL values in + * pthread_key_destroy + * + * We could keep an accounting of the number of specific used + * entries per thread, so that we can update pt_havespecific when we delete + * the last one, but we don't bother for now + */ +int +pthread__add_specific(pthread_t self, pthread_key_t key, const void *value) +{ + struct pt_specific *pt; + + pthread__assert(key >= 0 && key < pthread_keys_max); + + pthread_mutex_lock(&tsd_mutex); + pthread__assert(pthread__tsd_destructors[key] != NULL); + pt = &self->pt_specific[key]; + self->pt_havespecific = 1; + if (value) { + if (pt->pts_next.ptqe_prev == NULL) + PTQ_INSERT_HEAD(&pthread__tsd_list[key], pt, pts_next); + } else { + if (pt->pts_next.ptqe_prev != NULL) { + PTQ_REMOVE(&pthread__tsd_list[key], pt, pts_next); + pt->pts_next.ptqe_prev = NULL; + } + } + pt->pts_value = __UNCONST(value); + pthread_mutex_unlock(&tsd_mutex); + + return 0; +} + +int +pthread_key_delete(pthread_key_t key) +{ + /* + * This is tricky. The standard says of pthread_key_create() + * that new keys have the value NULL associated with them in + * all threads. According to people who were present at the + * standardization meeting, that requirement was written + * before pthread_key_delete() was introduced, and not + * reconsidered when it was. + * + * See David Butenhof's article in comp.programming.threads: + * Subject: Re: TSD key reusing issue + * Message-ID: + * Date: Thu, 21 Feb 2002 09:06:17 -0500 + * http://groups.google.com/groups?\ + * hl=en&selm=u97d8.29%24fL6.200%40news.cpqcorp.net + * + * Given: + * + * 1: Applications are not required to clear keys in all + * threads before calling pthread_key_delete(). + * 2: Clearing pointers without running destructors is a + * memory leak. + * 3: The pthread_key_delete() function is expressly forbidden + * to run any destructors. + * + * Option 1: Make this function effectively a no-op and + * prohibit key reuse. This is a possible resource-exhaustion + * problem given that we have a static storage area for keys, + * but having a non-static storage area would make + * pthread_setspecific() expensive (might need to realloc the + * TSD array). + * + * Option 2: Ignore the specified behavior of + * pthread_key_create() and leave the old values. If an + * application deletes a key that still has non-NULL values in + * some threads... it's probably a memory leak and hence + * incorrect anyway, and we're within our rights to let the + * application lose. However, it's possible (if unlikely) that + * the application is storing pointers to non-heap data, or + * non-pointers that have been wedged into a void pointer, so + * we can't entirely write off such applications as incorrect. + * This could also lead to running (new) destructors on old + * data that was never supposed to be associated with that + * destructor. + * + * Option 3: Follow the specified behavior of + * pthread_key_create(). Either pthread_key_create() or + * pthread_key_delete() would then have to clear the values in + * every thread's slot for that key. In order to guarantee the + * visibility of the NULL value in other threads, there would + * have to be synchronization operations in both the clearer + * and pthread_getspecific(). Putting synchronization in + * pthread_getspecific() is a big performance lose. But in + * reality, only (buggy) reuse of an old key would require + * this synchronization; for a new key, there has to be a + * memory-visibility propagating event between the call to + * pthread_key_create() and pthread_getspecific() with that + * key, so setting the entries to NULL without synchronization + * will work, subject to problem (2) above. However, it's kind + * of slow. + * + * Note that the argument in option 3 only applies because we + * keep TSD in ordinary memory which follows the pthreads + * visibility rules. The visibility rules are not required by + * the standard to apply to TSD, so the argument doesn't + * apply in general, just to this implementation. + */ + + /* + * We do option 3; we find the list of all pt_specific structures + * threaded on the key we are deleting, unthread them, and set the + * pointer to NULL. Finally we unthread the entry, freeing it for + * further use. + * + * We don't call the destructor here, it is the responsibility + * of the application to cleanup the storage: + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/\ + * pthread_key_delete.html + */ + struct pt_specific *pt; + + if (__predict_false(__uselibcstub)) + return __libc_thr_keydelete_stub(key); + + pthread__assert(key >= 0 && key < pthread_keys_max); + + pthread_mutex_lock(&tsd_mutex); + + pthread__assert(pthread__tsd_destructors[key] != NULL); + + while ((pt = PTQ_FIRST(&pthread__tsd_list[key])) != NULL) { + PTQ_REMOVE(&pthread__tsd_list[key], pt, pts_next); + pt->pts_value = NULL; + pt->pts_next.ptqe_prev = NULL; + } + + pthread__tsd_destructors[key] = NULL; + pthread_mutex_unlock(&tsd_mutex); + + return 0; +} + +/* Perform thread-exit-time destruction of thread-specific data. */ +void +pthread__destroy_tsd(pthread_t self) +{ + int i, done, iterations; + void *val; + void (*destructor)(void *); + + if (!self->pt_havespecific) + return; + pthread_mutex_unlock(&self->pt_lock); + + /* Butenhof, section 5.4.2 (page 167): + * + * ``Also, Pthreads sets the thread-specific data value for a + * key to NULL before calling that key's destructor (passing + * the previous value of the key) when a thread terminates [*]. + * ... + * [*] That is, unfortunately, not what the standard + * says. This is one of the problems with formal standards - + * they say what they say, not what they were intended to + * say. Somehow, an error crept in, and the sentence + * specifying that "the implementation clears the + * thread-specific data value before calling the destructor" + * was deleted. Nobody noticed, and the standard was approved + * with the error. So the standard says (by omission) that if + * you want to write a portable application using + * thread-specific data, that will not hang on thread + * termination, you must call pthread_setspecific within your + * destructor function to change the value to NULL. This would + * be silly, and any serious implementation of Pthreads will + * violate the standard in this respect. Of course, the + * standard will be fixed, probably by the 1003.1n amendment + * (assorted corrections to 1003.1c-1995), but that will take + * a while.'' + */ + + iterations = 4; /* We're not required to try very hard */ + do { + done = 1; + for (i = 0; i < pthread_keys_max; i++) { + struct pt_specific *pt = &self->pt_specific[i]; + if (pt->pts_next.ptqe_prev == NULL) + continue; + pthread_mutex_lock(&tsd_mutex); + + if (pt->pts_next.ptqe_prev != NULL) { + PTQ_REMOVE(&pthread__tsd_list[i], pt, pts_next); + val = pt->pts_value; + pt->pts_value = NULL; + pt->pts_next.ptqe_prev = NULL; + destructor = pthread__tsd_destructors[i]; + } else + destructor = NULL; + + pthread_mutex_unlock(&tsd_mutex); + if (destructor != NULL) { + done = 0; + (*destructor)(val); + } + } + } while (!done && iterations--); + + self->pt_havespecific = 0; + pthread_mutex_lock(&self->pt_lock); +} diff --git a/lib/libpthread/pthread_types.h b/lib/libpthread/pthread_types.h new file mode 100644 index 000000000..a25be8eff --- /dev/null +++ b/lib/libpthread/pthread_types.h @@ -0,0 +1,265 @@ +/* $NetBSD: pthread_types.h,v 1.17 2015/08/27 12:30:50 pooka Exp $ */ + +/*- + * Copyright (c) 2001, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +#ifndef _LIB_PTHREAD_TYPES_H +#define _LIB_PTHREAD_TYPES_H + +/* + * We use the "pthread_spin_t" name internally; "pthread_spinlock_t" is the + * POSIX spinlock object. + * + * C++ expects to be using PTHREAD_FOO_INITIALIZER as a member initializer. + * This does not work for volatile types. Since C++ does not touch the guts + * of those types, we do not include volatile in the C++ definitions. + */ +typedef __cpu_simple_lock_t pthread_spin_t; +#ifdef __cplusplus +typedef __cpu_simple_lock_nv_t __pthread_spin_t; +#define __pthread_volatile +#else +typedef pthread_spin_t __pthread_spin_t; +#define __pthread_volatile volatile +#endif + +/* + * Copied from PTQ_HEAD in pthread_queue.h + */ +#define _PTQ_HEAD(name, type) \ +struct name { \ + struct type *ptqh_first;/* first element */ \ + struct type **ptqh_last;/* addr of last next element */ \ +} + +_PTQ_HEAD(pthread_queue_struct_t, __pthread_st); +typedef struct pthread_queue_struct_t pthread_queue_t; + +struct __pthread_st; +struct __pthread_attr_st; +struct __pthread_mutex_st; +struct __pthread_mutexattr_st; +struct __pthread_cond_st; +struct __pthread_condattr_st; +struct __pthread_spin_st; +struct __pthread_rwlock_st; +struct __pthread_rwlockattr_st; +struct __pthread_barrier_st; +struct __pthread_barrierattr_st; + +typedef struct __pthread_st *pthread_t; +typedef struct __pthread_attr_st pthread_attr_t; +typedef struct __pthread_mutex_st pthread_mutex_t; +typedef struct __pthread_mutexattr_st pthread_mutexattr_t; +typedef struct __pthread_cond_st pthread_cond_t; +typedef struct __pthread_condattr_st pthread_condattr_t; +typedef struct __pthread_once_st pthread_once_t; +typedef struct __pthread_spinlock_st pthread_spinlock_t; +typedef struct __pthread_rwlock_st pthread_rwlock_t; +typedef struct __pthread_rwlockattr_st pthread_rwlockattr_t; +typedef struct __pthread_barrier_st pthread_barrier_t; +typedef struct __pthread_barrierattr_st pthread_barrierattr_t; +typedef int pthread_key_t; + +struct __pthread_attr_st { + unsigned int pta_magic; + + int pta_flags; + void *pta_private; +}; + +/* + * ptm_owner is the actual lock field which is locked via CAS operation. + * This structure's layout is designed to compatible with the previous + * version used in SA pthreads. + */ +#ifdef __CPU_SIMPLE_LOCK_PAD +/* + * If __SIMPLE_UNLOCKED != 0 and we have to pad, we have to worry about + * endianness. Currently that isn't an issue but put in a check in case + * something changes in the future. + */ +#if __SIMPLELOCK_UNLOCKED != 0 +#error __CPU_SIMPLE_LOCK_PAD incompatible with __SIMPLELOCK_UNLOCKED == 0 +#endif +#endif +struct __pthread_mutex_st { + unsigned int ptm_magic; + __pthread_spin_t ptm_errorcheck; +#ifdef __CPU_SIMPLE_LOCK_PAD + uint8_t ptm_pad1[3]; +#endif + __pthread_spin_t ptm_interlock; /* unused - backwards compat */ +#ifdef __CPU_SIMPLE_LOCK_PAD + uint8_t ptm_pad2[3]; +#endif + __pthread_volatile pthread_t ptm_owner; + pthread_t * __pthread_volatile ptm_waiters; + unsigned int ptm_recursed; + void *ptm_spare2; /* unused - backwards compat */ +}; + +#define _PT_MUTEX_MAGIC 0x33330003 +#define _PT_MUTEX_DEAD 0xDEAD0003 + +#ifdef __CPU_SIMPLE_LOCK_PAD +#define _PTHREAD_MUTEX_INITIALIZER { _PT_MUTEX_MAGIC, \ + __SIMPLELOCK_UNLOCKED, { 0, 0, 0 }, \ + __SIMPLELOCK_UNLOCKED, { 0, 0, 0 }, \ + NULL, NULL, 0, NULL \ + } +#else +#define _PTHREAD_MUTEX_INITIALIZER { _PT_MUTEX_MAGIC, \ + __SIMPLELOCK_UNLOCKED, \ + __SIMPLELOCK_UNLOCKED, \ + NULL, NULL, 0, NULL \ + } +#endif /* __CPU_SIMPLE_LOCK_PAD */ + + +struct __pthread_mutexattr_st { + unsigned int ptma_magic; + void *ptma_private; +}; + +#define _PT_MUTEXATTR_MAGIC 0x44440004 +#define _PT_MUTEXATTR_DEAD 0xDEAD0004 + + +struct __pthread_cond_st { + unsigned int ptc_magic; + + /* Protects the queue of waiters */ + __pthread_spin_t ptc_lock; + pthread_queue_t ptc_waiters; + + pthread_mutex_t *ptc_mutex; /* Current mutex */ + void *ptc_private; +}; + +#define _PT_COND_MAGIC 0x55550005 +#define _PT_COND_DEAD 0xDEAD0005 + +#define _PTHREAD_COND_INITIALIZER { _PT_COND_MAGIC, \ + __SIMPLELOCK_UNLOCKED, \ + {NULL, NULL}, \ + NULL, \ + NULL \ + } + +struct __pthread_condattr_st { + unsigned int ptca_magic; + void *ptca_private; +}; + +#define _PT_CONDATTR_MAGIC 0x66660006 +#define _PT_CONDATTR_DEAD 0xDEAD0006 + +struct __pthread_once_st { + pthread_mutex_t pto_mutex; + int pto_done; +}; + +#define _PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 } + +struct __pthread_spinlock_st { + unsigned int pts_magic; + __pthread_spin_t pts_spin; + int pts_flags; +}; + +#define _PT_SPINLOCK_MAGIC 0x77770007 +#define _PT_SPINLOCK_DEAD 0xDEAD0007 +#define _PT_SPINLOCK_PSHARED 0x00000001 + +/* PTHREAD_SPINLOCK_INITIALIZER is an extension not specified by POSIX. */ +#define _PTHREAD_SPINLOCK_INITIALIZER { _PT_SPINLOCK_MAGIC, \ + __SIMPLELOCK_UNLOCKED, \ + 0 \ + } + +struct __pthread_rwlock_st { + unsigned int ptr_magic; + + /* Protects data below */ + __pthread_spin_t ptr_interlock; + + pthread_queue_t ptr_rblocked; + pthread_queue_t ptr_wblocked; + unsigned int ptr_nreaders; + __pthread_volatile pthread_t ptr_owner; + void *ptr_private; +}; + +#define _PT_RWLOCK_MAGIC 0x99990009 +#define _PT_RWLOCK_DEAD 0xDEAD0009 + +#define _PTHREAD_RWLOCK_INITIALIZER { _PT_RWLOCK_MAGIC, \ + __SIMPLELOCK_UNLOCKED, \ + {NULL, NULL}, \ + {NULL, NULL}, \ + 0, \ + NULL, \ + NULL, \ + } + +struct __pthread_rwlockattr_st { + unsigned int ptra_magic; + void *ptra_private; +}; + +#define _PT_RWLOCKATTR_MAGIC 0x99990909 +#define _PT_RWLOCKATTR_DEAD 0xDEAD0909 + +struct __pthread_barrier_st { + unsigned int ptb_magic; + + /* Protects data below */ + pthread_spin_t ptb_lock; + + pthread_queue_t ptb_waiters; + unsigned int ptb_initcount; + unsigned int ptb_curcount; + unsigned int ptb_generation; + + void *ptb_private; +}; + +#define _PT_BARRIER_MAGIC 0x88880008 +#define _PT_BARRIER_DEAD 0xDEAD0008 + +struct __pthread_barrierattr_st { + unsigned int ptba_magic; + void *ptba_private; +}; + +#define _PT_BARRIERATTR_MAGIC 0x88880808 +#define _PT_BARRIERATTR_DEAD 0xDEAD0808 + +#endif /* _LIB_PTHREAD_TYPES_H */ diff --git a/lib/libpthread/res_state.c b/lib/libpthread/res_state.c new file mode 100644 index 000000000..5578b83a3 --- /dev/null +++ b/lib/libpthread/res_state.c @@ -0,0 +1,136 @@ +/* $NetBSD: res_state.c,v 1.6 2008/04/28 20:23:02 martin Exp $ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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 +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: res_state.c,v 1.6 2008/04/28 20:23:02 martin Exp $"); +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pthread.h" +#include "pthread_int.h" + +static SLIST_HEAD(, _res_st) res_list = LIST_HEAD_INITIALIZER(&res_list); + +struct _res_st { + /* __res_put_state() assumes st_res is the first member. */ + struct __res_state st_res; + + SLIST_ENTRY(_res_st) st_list; +}; + +static pthread_mutex_t res_mtx = PTHREAD_MUTEX_INITIALIZER; + +res_state __res_state(void); +res_state __res_get_state(void); +void __res_put_state(res_state); + +#ifdef RES_STATE_DEBUG +static void +res_state_debug(const char *msg, void *p) +{ + char buf[512]; + pthread_t self = pthread__self(); + int len = snprintf(buf, sizeof(buf), "%p: %s %p\n", self, msg, p); + + (void)write(STDOUT_FILENO, buf, (size_t)len); +} +#else +#define res_state_debug(a, b) +#endif + + +res_state +__res_get_state(void) +{ + res_state res; + struct _res_st *st; + pthread_mutex_lock(&res_mtx); + st = SLIST_FIRST(&res_list); + if (st != NULL) { + SLIST_REMOVE_HEAD(&res_list, st_list); + pthread_mutex_unlock(&res_mtx); + res = &st->st_res; + res_state_debug("checkout from list", st); + } else { + pthread_mutex_unlock(&res_mtx); + st = malloc(sizeof(*st)); + if (st == NULL) { + h_errno = NETDB_INTERNAL; + return NULL; + } + res = &st->st_res; + res->options = 0; + res_state_debug("alloc new", res); + } + if ((res->options & RES_INIT) == 0) { + if (res_ninit(res) == -1) { + h_errno = NETDB_INTERNAL; + free(st); + return NULL; + } + } + return res; +} + +void +/*ARGSUSED*/ +__res_put_state(res_state res) +{ + struct _res_st *st = (struct _res_st *)(void *)res; + + res_state_debug("free", res); + pthread_mutex_lock(&res_mtx); + SLIST_INSERT_HEAD(&res_list, st, st_list); + pthread_mutex_unlock(&res_mtx); +} + +/* + * This is aliased via a macro to _res; don't allow multi-threaded programs + * to use it. + */ +res_state +__res_state(void) +{ + static const char res[] = "_res is not supported for multi-threaded" + " programs.\n"; + (void)write(STDERR_FILENO, res, sizeof(res) - 1); + abort(); + return NULL; +} diff --git a/lib/libpthread/sem.c b/lib/libpthread/sem.c new file mode 100644 index 000000000..5c3e7fbb6 --- /dev/null +++ b/lib/libpthread/sem.c @@ -0,0 +1,316 @@ +/* $NetBSD: sem.c,v 1.24 2012/03/10 18:01:10 joerg Exp $ */ + +/*- + * Copyright (c) 2003, 2006, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 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. + */ + +/* + * 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. + */ + +#include +__RCSID("$NetBSD: sem.c,v 1.24 2012/03/10 18:01:10 joerg Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pthread.h" + +struct _sem_st { + unsigned int ksem_magic; +#define KSEM_MAGIC 0x90af0421U + + LIST_ENTRY(_sem_st) ksem_list; + intptr_t ksem_semid; /* 0 -> user (non-shared) */ + sem_t *ksem_identity; +}; + +static int sem_alloc(unsigned int value, intptr_t semid, sem_t *semp); +static void sem_free(sem_t sem); + +static LIST_HEAD(, _sem_st) named_sems = LIST_HEAD_INITIALIZER(&named_sems); +static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER; + +static void +sem_free(sem_t sem) +{ + + sem->ksem_magic = 0; + free(sem); +} + +static int +sem_alloc(unsigned int value, intptr_t semid, sem_t *semp) +{ + sem_t sem; + + if (value > SEM_VALUE_MAX) + return (EINVAL); + + if ((sem = malloc(sizeof(struct _sem_st))) == NULL) + return (ENOSPC); + + sem->ksem_magic = KSEM_MAGIC; + sem->ksem_semid = semid; + + *semp = sem; + return (0); +} + +/* ARGSUSED */ +int +sem_init(sem_t *sem, int pshared, unsigned int value) +{ + intptr_t semid; + int error; + + if (_ksem_init(value, &semid) == -1) + return (-1); + + if ((error = sem_alloc(value, semid, sem)) != 0) { + _ksem_destroy(semid); + errno = error; + return (-1); + } + + return (0); +} + +int +sem_destroy(sem_t *sem) +{ + int error, save_errno; + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + + error = _ksem_destroy((*sem)->ksem_semid); + save_errno = errno; + sem_free(*sem); + errno = save_errno; + + return error; +} + +sem_t * +sem_open(const char *name, int oflag, ...) +{ + sem_t *sem, s; + intptr_t semid; + mode_t mode; + unsigned int value; + int error; + va_list ap; + + mode = 0; + value = 0; + + if (oflag & O_CREAT) { + va_start(ap, oflag); + mode = va_arg(ap, int); + value = va_arg(ap, unsigned int); + va_end(ap); + } + + /* + * We can be lazy and let the kernel handle the oflag, + * we'll just merge duplicate IDs into our list. + */ + if (_ksem_open(name, oflag, mode, value, &semid) == -1) + return (SEM_FAILED); + + /* + * Search for a duplicate ID, we must return the same sem_t * + * if we locate one. + */ + pthread_mutex_lock(&named_sems_mtx); + LIST_FOREACH(s, &named_sems, ksem_list) { + if (s->ksem_semid == semid) { + pthread_mutex_unlock(&named_sems_mtx); + return (s->ksem_identity); + } + } + + if ((sem = malloc(sizeof(*sem))) == NULL) { + error = ENOSPC; + goto bad; + } + if ((error = sem_alloc(value, semid, sem)) != 0) + goto bad; + + LIST_INSERT_HEAD(&named_sems, *sem, ksem_list); + pthread_mutex_unlock(&named_sems_mtx); + (*sem)->ksem_identity = sem; + + return (sem); + + bad: + pthread_mutex_unlock(&named_sems_mtx); + _ksem_close(semid); + if (sem != NULL) { + if (*sem != NULL) + sem_free(*sem); + free(sem); + } + errno = error; + return (SEM_FAILED); +} + +int +sem_close(sem_t *sem) +{ + int error, save_errno; + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + + pthread_mutex_lock(&named_sems_mtx); + error = _ksem_close((*sem)->ksem_semid); + LIST_REMOVE((*sem), ksem_list); + save_errno = errno; + pthread_mutex_unlock(&named_sems_mtx); + sem_free(*sem); + free(sem); + errno = save_errno; + return error; +} + +int +sem_unlink(const char *name) +{ + + return (_ksem_unlink(name)); +} + +int +sem_wait(sem_t *sem) +{ + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + + return (_ksem_wait((*sem)->ksem_semid)); +} + +int +sem_timedwait(sem_t *sem, const struct timespec * __restrict abstime) +{ + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + + return (_ksem_timedwait((*sem)->ksem_semid, abstime)); +} + +int +sem_trywait(sem_t *sem) +{ + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + + return (_ksem_trywait((*sem)->ksem_semid)); +} + +int +sem_post(sem_t *sem) +{ + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + + return (_ksem_post((*sem)->ksem_semid)); +} + +int +sem_getvalue(sem_t * __restrict sem, int * __restrict sval) +{ + +#ifdef ERRORCHECK + if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) { + errno = EINVAL; + return (-1); + } +#endif + return (_ksem_getvalue((*sem)->ksem_semid, sval)); +} diff --git a/lib/libpthread/shlib_version b/lib/libpthread/shlib_version new file mode 100644 index 000000000..e674879f6 --- /dev/null +++ b/lib/libpthread/shlib_version @@ -0,0 +1,19 @@ +# $NetBSD: shlib_version,v 1.16 2013/04/03 15:45:21 christos Exp $ +# Remember to update distrib/sets/lists/base/shl.* when changing +# +# Things to do when bumping major version: +# +# - pthread_foo_t: +# +# clean out unused and abused members. +# +# add spare members. +# +# add members to deal with inter-process synch and priority inheritance. +# +# make objects same size and layout on 32/64 bit, so kernel can +# inspect them for priority inheritance / inter-process synch, +# without compat_netbsd32 shims?? +# +major=1 +minor=2