Index: head/include/pthread.h =================================================================== --- head/include/pthread.h (revision 337991) +++ head/include/pthread.h (revision 337992) @@ -1,334 +1,351 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu * Copyright (c) 1995-1998 by 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 Chris Provenzano. * 4. The name of Chris Provenzano may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _PTHREAD_H_ #define _PTHREAD_H_ /* * Header files. */ #include #include #include #include #include #include #include /* * Run-time invariant values: */ #define PTHREAD_DESTRUCTOR_ITERATIONS 4 #define PTHREAD_KEYS_MAX 256 #define PTHREAD_STACK_MIN __MINSIGSTKSZ #define PTHREAD_THREADS_MAX __ULONG_MAX #define PTHREAD_BARRIER_SERIAL_THREAD -1 /* * Flags for threads and thread attributes. */ #define PTHREAD_DETACHED 0x1 #define PTHREAD_SCOPE_SYSTEM 0x2 #define PTHREAD_INHERIT_SCHED 0x4 #define PTHREAD_NOFLOAT 0x8 #define PTHREAD_CREATE_DETACHED PTHREAD_DETACHED #define PTHREAD_CREATE_JOINABLE 0 #define PTHREAD_SCOPE_PROCESS 0 #define PTHREAD_EXPLICIT_SCHED 0 /* * Values for process shared/private attributes. */ #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 /* * Flags for cancelling threads */ #define PTHREAD_CANCEL_ENABLE 0 #define PTHREAD_CANCEL_DISABLE 1 #define PTHREAD_CANCEL_DEFERRED 0 #define PTHREAD_CANCEL_ASYNCHRONOUS 2 #define PTHREAD_CANCELED ((void *) 1) /* * Flags for once initialization. */ #define PTHREAD_NEEDS_INIT 0 #define PTHREAD_DONE_INIT 1 /* * Static once initialization values. */ #define PTHREAD_ONCE_INIT { PTHREAD_NEEDS_INIT, NULL } /* * Static initialization values. */ #define PTHREAD_MUTEX_INITIALIZER NULL #define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP ((pthread_mutex_t)1) #define PTHREAD_COND_INITIALIZER NULL #define PTHREAD_RWLOCK_INITIALIZER NULL /* * Default attribute arguments (draft 4, deprecated). */ #ifndef PTHREAD_KERNEL #define pthread_condattr_default NULL #define pthread_mutexattr_default NULL #define pthread_attr_default NULL #endif #define PTHREAD_PRIO_NONE 0 #define PTHREAD_PRIO_INHERIT 1 #define PTHREAD_PRIO_PROTECT 2 /* * Mutex types (Single UNIX Specification, Version 2, 1997). * * Note that a mutex attribute with one of the following types: * * PTHREAD_MUTEX_NORMAL * PTHREAD_MUTEX_RECURSIVE * * will deviate from POSIX specified semantics. */ enum pthread_mutextype { PTHREAD_MUTEX_ERRORCHECK = 1, /* Default POSIX mutex */ PTHREAD_MUTEX_RECURSIVE = 2, /* Recursive mutex */ PTHREAD_MUTEX_NORMAL = 3, /* No error checking */ PTHREAD_MUTEX_ADAPTIVE_NP = 4, /* Adaptive mutex, spins briefly before blocking on lock */ PTHREAD_MUTEX_TYPE_MAX }; #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_ERRORCHECK #define PTHREAD_MUTEX_STALLED 0 #define PTHREAD_MUTEX_ROBUST 1 struct _pthread_cleanup_info { __uintptr_t pthread_cleanup_pad[8]; }; /* * Thread function prototype definitions: */ __BEGIN_DECLS int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); int pthread_attr_destroy(pthread_attr_t *); int pthread_attr_getstack( const pthread_attr_t * __restrict, void ** __restrict, size_t * __restrict); -int pthread_attr_getstacksize(const pthread_attr_t *, - size_t *); -int pthread_attr_getguardsize(const pthread_attr_t *, - size_t *); +int pthread_attr_getstacksize(const pthread_attr_t * __restrict, + size_t * __restrict); +int pthread_attr_getguardsize(const pthread_attr_t * __restrict, + size_t * __restrict); int pthread_attr_getstackaddr(const pthread_attr_t *, void **); int pthread_attr_getdetachstate(const pthread_attr_t *, int *); int pthread_attr_init(pthread_attr_t *); int pthread_attr_setstacksize(pthread_attr_t *, size_t); int pthread_attr_setguardsize(pthread_attr_t *, size_t); int pthread_attr_setstack(pthread_attr_t *, void *, size_t); int pthread_attr_setstackaddr(pthread_attr_t *, void *); int pthread_attr_setdetachstate(pthread_attr_t *, int); int pthread_barrier_destroy(pthread_barrier_t *); -int pthread_barrier_init(pthread_barrier_t *, - const pthread_barrierattr_t *, unsigned); +int pthread_barrier_init(pthread_barrier_t * __restrict, + const pthread_barrierattr_t * __restrict, unsigned); int pthread_barrier_wait(pthread_barrier_t *); int pthread_barrierattr_destroy(pthread_barrierattr_t *); int pthread_barrierattr_getpshared( - const pthread_barrierattr_t *, int *); + const pthread_barrierattr_t * __restrict, int * __restrict); int pthread_barrierattr_init(pthread_barrierattr_t *); int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); #define pthread_cleanup_push(cleanup_routine, cleanup_arg) \ { \ struct _pthread_cleanup_info __cleanup_info__; \ __pthread_cleanup_push_imp(cleanup_routine, cleanup_arg,\ &__cleanup_info__); \ { #define pthread_cleanup_pop(execute) \ (void)0; \ } \ __pthread_cleanup_pop_imp(execute); \ } int pthread_condattr_destroy(pthread_condattr_t *); -int pthread_condattr_getclock(const pthread_condattr_t *, - clockid_t *); +int pthread_condattr_getclock(const pthread_condattr_t * __restrict, + clockid_t * __restrict); int pthread_condattr_getpshared(const pthread_condattr_t *, int *); int pthread_condattr_init(pthread_condattr_t *); int pthread_condattr_setclock(pthread_condattr_t *, clockid_t); int pthread_condattr_setpshared(pthread_condattr_t *, int); int pthread_cond_broadcast(pthread_cond_t *); int pthread_cond_destroy(pthread_cond_t *); -int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *); +int pthread_cond_init(pthread_cond_t * __restrict, + const pthread_condattr_t * __restrict); int pthread_cond_signal(pthread_cond_t *); int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t * __mutex, const struct timespec *) __requires_exclusive(*__mutex); -int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t * __mutex) +int pthread_cond_wait(pthread_cond_t * __restrict, + pthread_mutex_t * __restrict __mutex) __requires_exclusive(*__mutex); -int pthread_create(pthread_t *, const pthread_attr_t *, - void *(*) (void *), void *); +int pthread_create(pthread_t * __restrict, + const pthread_attr_t * __restrict, void *(*) (void *), + void * __restrict); int pthread_detach(pthread_t); int pthread_equal(pthread_t, pthread_t); void pthread_exit(void *) __dead2; void *pthread_getspecific(pthread_key_t); int pthread_getcpuclockid(pthread_t, clockid_t *); int pthread_join(pthread_t, void **); int pthread_key_create(pthread_key_t *, void (*) (void *)); int pthread_key_delete(pthread_key_t); int pthread_mutexattr_init(pthread_mutexattr_t *); int pthread_mutexattr_destroy(pthread_mutexattr_t *); -int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, - int *); -int pthread_mutexattr_gettype(pthread_mutexattr_t *, int *); +int pthread_mutexattr_getpshared( + const pthread_mutexattr_t * __restrict, + int * __restrict); +int pthread_mutexattr_gettype( + const pthread_mutexattr_t * __restrict, int * __restrict); int pthread_mutexattr_settype(pthread_mutexattr_t *, int); int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int); int pthread_mutex_consistent(pthread_mutex_t * __mutex) __requires_exclusive(*__mutex); int pthread_mutex_destroy(pthread_mutex_t * __mutex) __requires_unlocked(*__mutex); -int pthread_mutex_init(pthread_mutex_t * __mutex, - const pthread_mutexattr_t *) +int pthread_mutex_init(pthread_mutex_t * __restrict __mutex, + const pthread_mutexattr_t * __restrict) __requires_unlocked(*__mutex); int pthread_mutex_lock(pthread_mutex_t * __mutex) __locks_exclusive(*__mutex); int pthread_mutex_trylock(pthread_mutex_t * __mutex) __trylocks_exclusive(0, *__mutex); -int pthread_mutex_timedlock(pthread_mutex_t * __mutex, - const struct timespec *) +int pthread_mutex_timedlock(pthread_mutex_t * __restrict __mutex, + const struct timespec * __restrict) __trylocks_exclusive(0, *__mutex); int pthread_mutex_unlock(pthread_mutex_t * __mutex) __unlocks(*__mutex); int pthread_once(pthread_once_t *, void (*) (void)); int pthread_rwlock_destroy(pthread_rwlock_t * __rwlock) __requires_unlocked(*__rwlock); -int pthread_rwlock_init(pthread_rwlock_t * __rwlock, - const pthread_rwlockattr_t *) +int pthread_rwlock_init(pthread_rwlock_t * __restrict __rwlock, + const pthread_rwlockattr_t * __restrict) __requires_unlocked(*__rwlock); int pthread_rwlock_rdlock(pthread_rwlock_t * __rwlock) __locks_shared(*__rwlock); -int pthread_rwlock_timedrdlock(pthread_rwlock_t * __rwlock, - const struct timespec *) +int pthread_rwlock_timedrdlock( + pthread_rwlock_t * __restrict __rwlock, + const struct timespec * __restrict) __trylocks_shared(0, *__rwlock); -int pthread_rwlock_timedwrlock(pthread_rwlock_t * __rwlock, - const struct timespec *) +int pthread_rwlock_timedwrlock( + pthread_rwlock_t * __restrict __rwlock, + const struct timespec * __restrict) __trylocks_exclusive(0, *__rwlock); int pthread_rwlock_tryrdlock(pthread_rwlock_t * __rwlock) __trylocks_shared(0, *__rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t * __rwlock) __trylocks_exclusive(0, *__rwlock); int pthread_rwlock_unlock(pthread_rwlock_t * __rwlock) __unlocks(*__rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t * __rwlock) __locks_exclusive(*__rwlock); int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *, int *); -int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, - int *); +int pthread_rwlockattr_getpshared( + const pthread_rwlockattr_t * __restrict, + int * __restrict); int pthread_rwlockattr_init(pthread_rwlockattr_t *); int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int); int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); pthread_t pthread_self(void); int pthread_setspecific(pthread_key_t, const void *); int pthread_spin_init(pthread_spinlock_t * __spin, int) __requires_unlocked(*__spin); int pthread_spin_destroy(pthread_spinlock_t * __spin) __requires_unlocked(*__spin); int pthread_spin_lock(pthread_spinlock_t * __spin) __locks_exclusive(*__spin); int pthread_spin_trylock(pthread_spinlock_t * __spin) __trylocks_exclusive(0, *__spin); int pthread_spin_unlock(pthread_spinlock_t * __spin) __unlocks(*__spin); int pthread_cancel(pthread_t); int pthread_setcancelstate(int, int *); int pthread_setcanceltype(int, int *); void pthread_testcancel(void); #if __BSD_VISIBLE int pthread_getprio(pthread_t); int pthread_setprio(pthread_t, int); void pthread_yield(void); #endif -int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *, int *); +int pthread_mutexattr_getprioceiling( + const pthread_mutexattr_t * __restrict, + int * __restrict); int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int); -int pthread_mutex_getprioceiling(pthread_mutex_t *, int *); -int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *); +int pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict, + int * __restrict); +int pthread_mutex_setprioceiling(pthread_mutex_t * __restrict, int, + int * __restrict); -int pthread_mutexattr_getprotocol(pthread_mutexattr_t *, int *); +int pthread_mutexattr_getprotocol( + const pthread_mutexattr_t * __restrict, + int * __restrict); int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int); int pthread_mutexattr_getrobust( pthread_mutexattr_t * __restrict, int * __restrict); int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int); -int pthread_attr_getinheritsched(const pthread_attr_t *, int *); +int pthread_attr_getinheritsched(const pthread_attr_t * __restrict, + int * __restrict); int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *); -int pthread_attr_getschedpolicy(const pthread_attr_t *, int *); -int pthread_attr_getscope(const pthread_attr_t *, int *); +int pthread_attr_getschedpolicy(const pthread_attr_t * __restrict, + int * __restrict); +int pthread_attr_getscope(const pthread_attr_t * __restrict, + int * __restrict); int pthread_attr_setinheritsched(pthread_attr_t *, int); int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *); int pthread_attr_setschedpolicy(pthread_attr_t *, int); int pthread_attr_setscope(pthread_attr_t *, int); -int pthread_getschedparam(pthread_t pthread, int *, - struct sched_param *); +int pthread_getschedparam(pthread_t pthread, int * __restrict, + struct sched_param * __restrict); int pthread_setschedparam(pthread_t, int, const struct sched_param *); #if __XSI_VISIBLE int pthread_getconcurrency(void); int pthread_setconcurrency(int); #endif void __pthread_cleanup_push_imp(void (*)(void *), void *, struct _pthread_cleanup_info *); void __pthread_cleanup_pop_imp(int); __END_DECLS #endif /* !_PTHREAD_H_ */ Index: head/lib/libthr/thread/thr_attr.c =================================================================== --- head/lib/libthr/thread/thr_attr.c (revision 337991) +++ head/lib/libthr/thread/thr_attr.c (revision 337992) @@ -1,653 +1,660 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 2003 Craig Rodrigues . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Craig Rodrigues. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * Copyright (c) 1998 Daniel Eischen . * Copyright (C) 2001 Jason Evans . * Copyright (c) 2002,2003 Alexey Zelkin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice(s), this list of conditions and the following disclaimer * unmodified other than the allowable addition of one or more * copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1996 John Birrell . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include "un-namespace.h" #include "thr_private.h" static size_t _get_kern_cpuset_size(void); __weak_reference(_pthread_attr_destroy, pthread_attr_destroy); int _pthread_attr_destroy(pthread_attr_t *attr) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL) /* Invalid argument: */ ret = EINVAL; else { if ((*attr)->cpuset != NULL) free((*attr)->cpuset); /* Free the memory allocated to the attribute object: */ free(*attr); /* * Leave the attribute pointer NULL now that the memory * has been freed: */ *attr = NULL; ret = 0; } return(ret); } __weak_reference(_pthread_attr_get_np, pthread_attr_get_np); int _pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) { struct pthread *curthread; struct pthread_attr attr, *dst; int ret; size_t kern_size; if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) return (EINVAL); kern_size = _get_kern_cpuset_size(); if (dst->cpuset == NULL) { dst->cpuset = calloc(1, kern_size); dst->cpusetsize = kern_size; } curthread = _get_curthread(); if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) return (ret); attr = pthread->attr; if (pthread->flags & THR_FLAGS_DETACHED) attr.flags |= PTHREAD_DETACHED; ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread), dst->cpusetsize, dst->cpuset); if (ret == -1) ret = errno; THR_THREAD_UNLOCK(curthread, pthread); if (ret == 0) { memcpy(&dst->pthread_attr_start_copy, &attr.pthread_attr_start_copy, offsetof(struct pthread_attr, pthread_attr_end_copy) - offsetof(struct pthread_attr, pthread_attr_start_copy)); } return (ret); } __weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate); int _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || detachstate == NULL) ret = EINVAL; else { /* Check if the detached flag is set: */ if ((*attr)->flags & PTHREAD_DETACHED) /* Return detached: */ *detachstate = PTHREAD_CREATE_DETACHED; else /* Return joinable: */ *detachstate = PTHREAD_CREATE_JOINABLE; ret = 0; } return(ret); } __weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize); int -_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) +_pthread_attr_getguardsize(const pthread_attr_t *__restrict attr, + size_t *__restrict guardsize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || guardsize == NULL) ret = EINVAL; else { /* Return the guard size: */ *guardsize = (*attr)->guardsize_attr; ret = 0; } return(ret); } __weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched); int -_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit) +_pthread_attr_getinheritsched(const pthread_attr_t * __restrict attr, + int * __restrict sched_inherit) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else *sched_inherit = (*attr)->sched_inherit; return(ret); } __weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam); int -_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param) +_pthread_attr_getschedparam(const pthread_attr_t * __restrict attr, + struct sched_param * __restrict param) { int ret = 0; if ((attr == NULL) || (*attr == NULL) || (param == NULL)) ret = EINVAL; else param->sched_priority = (*attr)->prio; return(ret); } __weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); int -_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +_pthread_attr_getschedpolicy(const pthread_attr_t * __restrict attr, + int * __restrict policy) { int ret = 0; if ((attr == NULL) || (*attr == NULL) || (policy == NULL)) ret = EINVAL; else *policy = (*attr)->sched_policy; return(ret); } __weak_reference(_pthread_attr_getscope, pthread_attr_getscope); int -_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope) +_pthread_attr_getscope(const pthread_attr_t * __restrict attr, + int * __restrict contentionscope) { int ret = 0; if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL)) /* Return an invalid argument: */ ret = EINVAL; else *contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ? PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS; return(ret); } __weak_reference(_pthread_attr_getstack, pthread_attr_getstack); int _pthread_attr_getstack(const pthread_attr_t * __restrict attr, void ** __restrict stackaddr, size_t * __restrict stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL || stacksize == NULL ) ret = EINVAL; else { /* Return the stack address and size */ *stackaddr = (*attr)->stackaddr_attr; *stacksize = (*attr)->stacksize_attr; ret = 0; } return(ret); } __weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr); int _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL) ret = EINVAL; else { /* Return the stack address: */ *stackaddr = (*attr)->stackaddr_attr; ret = 0; } return(ret); } __weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize); int -_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) +_pthread_attr_getstacksize(const pthread_attr_t * __restrict attr, + size_t * __restrict stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stacksize == NULL) ret = EINVAL; else { /* Return the stack size: */ *stacksize = (*attr)->stacksize_attr; ret = 0; } return(ret); } __weak_reference(_pthread_attr_init, pthread_attr_init); int _pthread_attr_init(pthread_attr_t *attr) { int ret; pthread_attr_t pattr; _thr_check_init(); /* Allocate memory for the attribute object: */ if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL) /* Insufficient memory: */ ret = ENOMEM; else { /* Initialise the attribute object with the defaults: */ memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr)); /* Return a pointer to the attribute object: */ *attr = pattr; ret = 0; } return(ret); } __weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np); int _pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) { int ret; if (attr == NULL || *attr == NULL) { ret = EINVAL; } else { (*attr)->suspend = THR_CREATE_SUSPENDED; ret = 0; } return(ret); } __weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate); int _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || (detachstate != PTHREAD_CREATE_DETACHED && detachstate != PTHREAD_CREATE_JOINABLE)) ret = EINVAL; else { /* Check if detached state: */ if (detachstate == PTHREAD_CREATE_DETACHED) /* Set the detached flag: */ (*attr)->flags |= PTHREAD_DETACHED; else /* Reset the detached flag: */ (*attr)->flags &= ~PTHREAD_DETACHED; ret = 0; } return(ret); } __weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize); int _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) { int ret; /* Check for invalid arguments. */ if (attr == NULL || *attr == NULL) ret = EINVAL; else { /* Save the stack size. */ (*attr)->guardsize_attr = guardsize; ret = 0; } return(ret); } __weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched); int _pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else if (sched_inherit != PTHREAD_INHERIT_SCHED && sched_inherit != PTHREAD_EXPLICIT_SCHED) ret = ENOTSUP; else (*attr)->sched_inherit = sched_inherit; return(ret); } __weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam); int -_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param) +_pthread_attr_setschedparam(pthread_attr_t * __restrict attr, + const struct sched_param * __restrict param) { int policy; if ((attr == NULL) || (*attr == NULL)) return (EINVAL); if (param == NULL) return (ENOTSUP); policy = (*attr)->sched_policy; if (policy == SCHED_FIFO || policy == SCHED_RR) { if (param->sched_priority < _thr_priorities[policy-1].pri_min || param->sched_priority > _thr_priorities[policy-1].pri_max) return (ENOTSUP); } else { /* * Ignore it for SCHED_OTHER now, patches for glib ports * are wrongly using M:N thread library's internal macro * THR_MIN_PRIORITY and THR_MAX_PRIORITY. */ } (*attr)->prio = param->sched_priority; return (0); } __weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); int _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) ret = EINVAL; else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) { ret = ENOTSUP; } else { (*attr)->sched_policy = policy; (*attr)->prio = _thr_priorities[policy-1].pri_default; } return(ret); } __weak_reference(_pthread_attr_setscope, pthread_attr_setscope); int _pthread_attr_setscope(pthread_attr_t *attr, int contentionscope) { int ret = 0; if ((attr == NULL) || (*attr == NULL)) { /* Return an invalid argument: */ ret = EINVAL; } else if ((contentionscope != PTHREAD_SCOPE_PROCESS) && (contentionscope != PTHREAD_SCOPE_SYSTEM)) { ret = EINVAL; } else if (contentionscope == PTHREAD_SCOPE_SYSTEM) { (*attr)->flags |= contentionscope; } else { (*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM; } return (ret); } __weak_reference(_pthread_attr_setstack, pthread_attr_setstack); int _pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL || stacksize < PTHREAD_STACK_MIN) ret = EINVAL; else { /* Save the stack address and stack size */ (*attr)->stackaddr_attr = stackaddr; (*attr)->stacksize_attr = stacksize; ret = 0; } return(ret); } __weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr); int _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stackaddr == NULL) ret = EINVAL; else { /* Save the stack address: */ (*attr)->stackaddr_attr = stackaddr; ret = 0; } return(ret); } __weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize); int _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { int ret; /* Check for invalid arguments: */ if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN) ret = EINVAL; else { /* Save the stack size: */ (*attr)->stacksize_attr = stacksize; ret = 0; } return(ret); } static size_t _get_kern_cpuset_size(void) { static int kern_cpuset_size = 0; if (kern_cpuset_size == 0) { size_t len; len = sizeof(kern_cpuset_size); if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size, &len, NULL, 0)) PANIC("failed to get sysctl kern.sched.cpusetsize"); } return (kern_cpuset_size); } __weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np); int _pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize, const cpuset_t *cpusetp) { pthread_attr_t attr; int ret; if (pattr == NULL || (attr = (*pattr)) == NULL) ret = EINVAL; else { if (cpusetsize == 0 || cpusetp == NULL) { if (attr->cpuset != NULL) { free(attr->cpuset); attr->cpuset = NULL; attr->cpusetsize = 0; } return (0); } size_t kern_size = _get_kern_cpuset_size(); /* Kernel rejects small set, we check it here too. */ if (cpusetsize < kern_size) return (ERANGE); if (cpusetsize > kern_size) { /* Kernel checks invalid bits, we check it here too. */ size_t i; for (i = kern_size; i < cpusetsize; ++i) { if (((const char *)cpusetp)[i]) return (EINVAL); } } if (attr->cpuset == NULL) { attr->cpuset = calloc(1, kern_size); if (attr->cpuset == NULL) return (errno); attr->cpusetsize = kern_size; } memcpy(attr->cpuset, cpusetp, kern_size); ret = 0; } return (ret); } __weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np); int _pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize, cpuset_t *cpusetp) { pthread_attr_t attr; int ret = 0; if (pattr == NULL || (attr = (*pattr)) == NULL) ret = EINVAL; else { /* Kernel rejects small set, we check it here too. */ size_t kern_size = _get_kern_cpuset_size(); if (cpusetsize < kern_size) return (ERANGE); if (attr->cpuset != NULL) memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, attr->cpusetsize)); else memset(cpusetp, -1, kern_size); if (cpusetsize > kern_size) memset(((char *)cpusetp) + kern_size, 0, cpusetsize - kern_size); } return (ret); } Index: head/lib/libthr/thread/thr_barrier.c =================================================================== --- head/lib/libthr/thread/thr_barrier.c (revision 337991) +++ head/lib/libthr/thread/thr_barrier.c (revision 337992) @@ -1,174 +1,174 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2003 David Xu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include "un-namespace.h" #include "thr_private.h" _Static_assert(sizeof(struct pthread_barrier) <= PAGE_SIZE, "pthread_barrier is too large for off-page"); __weak_reference(_pthread_barrier_init, pthread_barrier_init); __weak_reference(_pthread_barrier_wait, pthread_barrier_wait); __weak_reference(_pthread_barrier_destroy, pthread_barrier_destroy); int _pthread_barrier_destroy(pthread_barrier_t *barrier) { pthread_barrier_t bar; struct pthread *curthread; int pshared; if (barrier == NULL || *barrier == NULL) return (EINVAL); if (*barrier == THR_PSHARED_PTR) { bar = __thr_pshared_offpage(barrier, 0); if (bar == NULL) { *barrier = NULL; return (0); } pshared = 1; } else { bar = *barrier; pshared = 0; } curthread = _get_curthread(); THR_UMUTEX_LOCK(curthread, &bar->b_lock); if (bar->b_destroying) { THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); return (EBUSY); } bar->b_destroying = 1; do { if (bar->b_waiters > 0) { bar->b_destroying = 0; THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); return (EBUSY); } if (bar->b_refcount != 0) { _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); THR_UMUTEX_LOCK(curthread, &bar->b_lock); } else break; } while (1); bar->b_destroying = 0; THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); *barrier = NULL; if (pshared) __thr_pshared_destroy(barrier); else free(bar); return (0); } int -_pthread_barrier_init(pthread_barrier_t *barrier, - const pthread_barrierattr_t *attr, unsigned count) +_pthread_barrier_init(pthread_barrier_t * __restrict barrier, + const pthread_barrierattr_t * __restrict attr, unsigned count) { pthread_barrier_t bar; int pshared; if (barrier == NULL || count == 0 || count > INT_MAX) return (EINVAL); if (attr == NULL || *attr == NULL || (*attr)->pshared == PTHREAD_PROCESS_PRIVATE) { bar = calloc(1, sizeof(struct pthread_barrier)); if (bar == NULL) return (ENOMEM); *barrier = bar; pshared = 0; } else { bar = __thr_pshared_offpage(barrier, 1); if (bar == NULL) return (EFAULT); *barrier = THR_PSHARED_PTR; pshared = 1; } _thr_umutex_init(&bar->b_lock); _thr_ucond_init(&bar->b_cv); if (pshared) { bar->b_lock.m_flags |= USYNC_PROCESS_SHARED; bar->b_cv.c_flags |= USYNC_PROCESS_SHARED; } bar->b_count = count; return (0); } int _pthread_barrier_wait(pthread_barrier_t *barrier) { struct pthread *curthread; pthread_barrier_t bar; int64_t cycle; int ret; if (barrier == NULL || *barrier == NULL) return (EINVAL); if (*barrier == THR_PSHARED_PTR) { bar = __thr_pshared_offpage(barrier, 0); if (bar == NULL) return (EINVAL); } else { bar = *barrier; } curthread = _get_curthread(); THR_UMUTEX_LOCK(curthread, &bar->b_lock); if (++bar->b_waiters == bar->b_count) { /* Current thread is lastest thread */ bar->b_waiters = 0; bar->b_cycle++; _thr_ucond_broadcast(&bar->b_cv); THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); ret = PTHREAD_BARRIER_SERIAL_THREAD; } else { cycle = bar->b_cycle; bar->b_refcount++; do { _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); THR_UMUTEX_LOCK(curthread, &bar->b_lock); /* test cycle to avoid bogus wakeup */ } while (cycle == bar->b_cycle); if (--bar->b_refcount == 0 && bar->b_destroying) _thr_ucond_broadcast(&bar->b_cv); THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); ret = 0; } return (ret); } Index: head/lib/libthr/thread/thr_barrierattr.c =================================================================== --- head/lib/libthr/thread/thr_barrierattr.c (revision 337991) +++ head/lib/libthr/thread/thr_barrierattr.c (revision 337992) @@ -1,97 +1,97 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2003 David Xu . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice(s), this list of conditions and the following disclaimer as * the first lines of this file unmodified other than the possible * addition of one or more copyright notices. * 2. Redistributions in binary form must reproduce the above copyright * notice(s), this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include "un-namespace.h" #include "thr_private.h" __weak_reference(_pthread_barrierattr_destroy, pthread_barrierattr_destroy); __weak_reference(_pthread_barrierattr_init, pthread_barrierattr_init); __weak_reference(_pthread_barrierattr_setpshared, pthread_barrierattr_setpshared); __weak_reference(_pthread_barrierattr_getpshared, pthread_barrierattr_getpshared); int _pthread_barrierattr_destroy(pthread_barrierattr_t *attr) { if (attr == NULL || *attr == NULL) return (EINVAL); free(*attr); return (0); } int -_pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, - int *pshared) +_pthread_barrierattr_getpshared(const pthread_barrierattr_t * __restrict attr, + int * __restrict pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); *pshared = (*attr)->pshared; return (0); } int _pthread_barrierattr_init(pthread_barrierattr_t *attr) { if (attr == NULL) return (EINVAL); if ((*attr = malloc(sizeof(struct pthread_barrierattr))) == NULL) return (ENOMEM); (*attr)->pshared = PTHREAD_PROCESS_PRIVATE; return (0); } int _pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) { if (attr == NULL || *attr == NULL || (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)) return (EINVAL); (*attr)->pshared = pshared; return (0); } Index: head/lib/libthr/thread/thr_cond.c =================================================================== --- head/lib/libthr/thread/thr_cond.c (revision 337991) +++ head/lib/libthr/thread/thr_cond.c (revision 337992) @@ -1,543 +1,546 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2005 David Xu * Copyright (c) 2015 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Konstantin Belousov * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include "un-namespace.h" #include "thr_private.h" _Static_assert(sizeof(struct pthread_cond) <= PAGE_SIZE, "pthread_cond too large"); /* * Prototypes */ int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec * abstime); static int cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); static int cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime, int cancel); static int cond_signal_common(pthread_cond_t *cond); static int cond_broadcast_common(pthread_cond_t *cond); /* * Double underscore versions are cancellation points. Single underscore * versions are not and are provided for libc internal usage (which * shouldn't introduce cancellation points). */ __weak_reference(__pthread_cond_wait, pthread_cond_wait); __weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait); __weak_reference(_pthread_cond_init, pthread_cond_init); __weak_reference(_pthread_cond_destroy, pthread_cond_destroy); __weak_reference(_pthread_cond_signal, pthread_cond_signal); __weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast); #define CV_PSHARED(cvp) (((cvp)->kcond.c_flags & USYNC_PROCESS_SHARED) != 0) static void cond_init_body(struct pthread_cond *cvp, const struct pthread_cond_attr *cattr) { if (cattr == NULL) { cvp->kcond.c_clockid = CLOCK_REALTIME; } else { if (cattr->c_pshared) cvp->kcond.c_flags |= USYNC_PROCESS_SHARED; cvp->kcond.c_clockid = cattr->c_clockid; } } static int cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) { struct pthread_cond *cvp; const struct pthread_cond_attr *cattr; int pshared; cattr = cond_attr != NULL ? *cond_attr : NULL; if (cattr == NULL || cattr->c_pshared == PTHREAD_PROCESS_PRIVATE) { pshared = 0; cvp = calloc(1, sizeof(struct pthread_cond)); if (cvp == NULL) return (ENOMEM); } else { pshared = 1; cvp = __thr_pshared_offpage(cond, 1); if (cvp == NULL) return (EFAULT); } /* * Initialise the condition variable structure: */ cond_init_body(cvp, cattr); *cond = pshared ? THR_PSHARED_PTR : cvp; return (0); } static int init_static(struct pthread *thread, pthread_cond_t *cond) { int ret; THR_LOCK_ACQUIRE(thread, &_cond_static_lock); if (*cond == NULL) ret = cond_init(cond, NULL); else ret = 0; THR_LOCK_RELEASE(thread, &_cond_static_lock); return (ret); } #define CHECK_AND_INIT_COND \ if (*cond == THR_PSHARED_PTR) { \ cvp = __thr_pshared_offpage(cond, 0); \ if (cvp == NULL) \ return (EINVAL); \ } else if (__predict_false((cvp = (*cond)) <= THR_COND_DESTROYED)) { \ if (cvp == THR_COND_INITIALIZER) { \ int ret; \ ret = init_static(_get_curthread(), cond); \ if (ret) \ return (ret); \ } else if (cvp == THR_COND_DESTROYED) { \ return (EINVAL); \ } \ cvp = *cond; \ } int -_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) +_pthread_cond_init(pthread_cond_t * __restrict cond, + const pthread_condattr_t * __restrict cond_attr) { *cond = NULL; return (cond_init(cond, cond_attr)); } int _pthread_cond_destroy(pthread_cond_t *cond) { struct pthread_cond *cvp; int error; error = 0; if (*cond == THR_PSHARED_PTR) { cvp = __thr_pshared_offpage(cond, 0); if (cvp != NULL) __thr_pshared_destroy(cond); *cond = THR_COND_DESTROYED; } else if ((cvp = *cond) == THR_COND_INITIALIZER) { /* nothing */ } else if (cvp == THR_COND_DESTROYED) { error = EINVAL; } else { cvp = *cond; *cond = THR_COND_DESTROYED; free(cvp); } return (error); } /* * Cancellation behavior: * Thread may be canceled at start, if thread is canceled, it means it * did not get a wakeup from pthread_cond_signal(), otherwise, it is * not canceled. * Thread cancellation never cause wakeup from pthread_cond_signal() * to be lost. */ static int cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp, const struct timespec *abstime, int cancel) { struct pthread *curthread; int error, error2, recurse, robust; curthread = _get_curthread(); robust = _mutex_enter_robust(curthread, mp); error = _mutex_cv_detach(mp, &recurse); if (error != 0) { if (robust) _mutex_leave_robust(curthread, mp); return (error); } if (cancel) _thr_cancel_enter2(curthread, 0); error = _thr_ucond_wait(&cvp->kcond, &mp->m_lock, abstime, CVWAIT_ABSTIME | CVWAIT_CLOCKID); if (cancel) _thr_cancel_leave(curthread, 0); /* * Note that PP mutex and ROBUST mutex may return * interesting error codes. */ if (error == 0) { error2 = _mutex_cv_lock(mp, recurse, true); } else if (error == EINTR || error == ETIMEDOUT) { error2 = _mutex_cv_lock(mp, recurse, true); /* * Do not do cancellation on EOWNERDEAD there. The * cancellation cleanup handler will use the protected * state and unlock the mutex without making the state * consistent and the state will be unrecoverable. */ if (error2 == 0 && cancel) { if (robust) { _mutex_leave_robust(curthread, mp); robust = false; } _thr_testcancel(curthread); } if (error == EINTR) error = 0; } else { /* We know that it didn't unlock the mutex. */ _mutex_cv_attach(mp, recurse); if (cancel) { if (robust) { _mutex_leave_robust(curthread, mp); robust = false; } _thr_testcancel(curthread); } error2 = 0; } if (robust) _mutex_leave_robust(curthread, mp); return (error2 != 0 ? error2 : error); } /* * Thread waits in userland queue whenever possible, when thread * is signaled or broadcasted, it is removed from the queue, and * is saved in curthread's defer_waiters[] buffer, but won't be * woken up until mutex is unlocked. */ static int cond_wait_user(struct pthread_cond *cvp, struct pthread_mutex *mp, const struct timespec *abstime, int cancel) { struct pthread *curthread; struct sleepqueue *sq; int deferred, error, error2, recurse; curthread = _get_curthread(); if (curthread->wchan != NULL) PANIC("thread %p was already on queue.", curthread); if (cancel) _thr_testcancel(curthread); _sleepq_lock(cvp); /* * set __has_user_waiters before unlocking mutex, this allows * us to check it without locking in pthread_cond_signal(). */ cvp->__has_user_waiters = 1; deferred = 0; (void)_mutex_cv_unlock(mp, &recurse, &deferred); curthread->mutex_obj = mp; _sleepq_add(cvp, curthread); for(;;) { _thr_clear_wake(curthread); _sleepq_unlock(cvp); if (deferred) { deferred = 0; if ((mp->m_lock.m_owner & UMUTEX_CONTESTED) == 0) (void)_umtx_op_err(&mp->m_lock, UMTX_OP_MUTEX_WAKE2, mp->m_lock.m_flags, 0, 0); } if (curthread->nwaiter_defer > 0) { _thr_wake_all(curthread->defer_waiters, curthread->nwaiter_defer); curthread->nwaiter_defer = 0; } if (cancel) _thr_cancel_enter2(curthread, 0); error = _thr_sleep(curthread, cvp->kcond.c_clockid, abstime); if (cancel) _thr_cancel_leave(curthread, 0); _sleepq_lock(cvp); if (curthread->wchan == NULL) { error = 0; break; } else if (cancel && SHOULD_CANCEL(curthread)) { sq = _sleepq_lookup(cvp); cvp->__has_user_waiters = _sleepq_remove(sq, curthread); _sleepq_unlock(cvp); curthread->mutex_obj = NULL; error2 = _mutex_cv_lock(mp, recurse, false); if (!THR_IN_CRITICAL(curthread)) _pthread_exit(PTHREAD_CANCELED); else /* this should not happen */ return (error2); } else if (error == ETIMEDOUT) { sq = _sleepq_lookup(cvp); cvp->__has_user_waiters = _sleepq_remove(sq, curthread); break; } } _sleepq_unlock(cvp); curthread->mutex_obj = NULL; error2 = _mutex_cv_lock(mp, recurse, false); if (error == 0) error = error2; return (error); } static int cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime, int cancel) { struct pthread *curthread = _get_curthread(); struct pthread_cond *cvp; struct pthread_mutex *mp; int error; CHECK_AND_INIT_COND if (*mutex == THR_PSHARED_PTR) { mp = __thr_pshared_offpage(mutex, 0); if (mp == NULL) return (EINVAL); } else { mp = *mutex; } if ((error = _mutex_owned(curthread, mp)) != 0) return (error); if (curthread->attr.sched_policy != SCHED_OTHER || (mp->m_lock.m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT | USYNC_PROCESS_SHARED)) != 0 || CV_PSHARED(cvp)) return (cond_wait_kernel(cvp, mp, abstime, cancel)); else return (cond_wait_user(cvp, mp, abstime, cancel)); } int _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { return (cond_wait_common(cond, mutex, NULL, 0)); } int -__pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +__pthread_cond_wait(pthread_cond_t * __restrict cond, + pthread_mutex_t * __restrict mutex) { return (cond_wait_common(cond, mutex, NULL, 1)); } int -_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - const struct timespec * abstime) +_pthread_cond_timedwait(pthread_cond_t * __restrict cond, + pthread_mutex_t * __restrict mutex, + const struct timespec * __restrict abstime) { if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return (EINVAL); return (cond_wait_common(cond, mutex, abstime, 0)); } int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return (EINVAL); return (cond_wait_common(cond, mutex, abstime, 1)); } static int cond_signal_common(pthread_cond_t *cond) { struct pthread *curthread = _get_curthread(); struct pthread *td; struct pthread_cond *cvp; struct pthread_mutex *mp; struct sleepqueue *sq; int *waddr; int pshared; /* * If the condition variable is statically initialized, perform dynamic * initialization. */ CHECK_AND_INIT_COND pshared = CV_PSHARED(cvp); _thr_ucond_signal(&cvp->kcond); if (pshared || cvp->__has_user_waiters == 0) return (0); curthread = _get_curthread(); waddr = NULL; _sleepq_lock(cvp); sq = _sleepq_lookup(cvp); if (sq == NULL) { _sleepq_unlock(cvp); return (0); } td = _sleepq_first(sq); mp = td->mutex_obj; cvp->__has_user_waiters = _sleepq_remove(sq, td); if (PMUTEX_OWNER_ID(mp) == TID(curthread)) { if (curthread->nwaiter_defer >= MAX_DEFER_WAITERS) { _thr_wake_all(curthread->defer_waiters, curthread->nwaiter_defer); curthread->nwaiter_defer = 0; } curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_addr->value; mp->m_flags |= PMUTEX_FLAG_DEFERRED; } else { waddr = &td->wake_addr->value; } _sleepq_unlock(cvp); if (waddr != NULL) _thr_set_wake(waddr); return (0); } struct broadcast_arg { struct pthread *curthread; unsigned int *waddrs[MAX_DEFER_WAITERS]; int count; }; static void drop_cb(struct pthread *td, void *arg) { struct broadcast_arg *ba = arg; struct pthread_mutex *mp; struct pthread *curthread = ba->curthread; mp = td->mutex_obj; if (PMUTEX_OWNER_ID(mp) == TID(curthread)) { if (curthread->nwaiter_defer >= MAX_DEFER_WAITERS) { _thr_wake_all(curthread->defer_waiters, curthread->nwaiter_defer); curthread->nwaiter_defer = 0; } curthread->defer_waiters[curthread->nwaiter_defer++] = &td->wake_addr->value; mp->m_flags |= PMUTEX_FLAG_DEFERRED; } else { if (ba->count >= MAX_DEFER_WAITERS) { _thr_wake_all(ba->waddrs, ba->count); ba->count = 0; } ba->waddrs[ba->count++] = &td->wake_addr->value; } } static int cond_broadcast_common(pthread_cond_t *cond) { int pshared; struct pthread_cond *cvp; struct sleepqueue *sq; struct broadcast_arg ba; /* * If the condition variable is statically initialized, perform dynamic * initialization. */ CHECK_AND_INIT_COND pshared = CV_PSHARED(cvp); _thr_ucond_broadcast(&cvp->kcond); if (pshared || cvp->__has_user_waiters == 0) return (0); ba.curthread = _get_curthread(); ba.count = 0; _sleepq_lock(cvp); sq = _sleepq_lookup(cvp); if (sq == NULL) { _sleepq_unlock(cvp); return (0); } _sleepq_drop(sq, drop_cb, &ba); cvp->__has_user_waiters = 0; _sleepq_unlock(cvp); if (ba.count > 0) _thr_wake_all(ba.waddrs, ba.count); return (0); } int _pthread_cond_signal(pthread_cond_t * cond) { return (cond_signal_common(cond)); } int _pthread_cond_broadcast(pthread_cond_t * cond) { return (cond_broadcast_common(cond)); } Index: head/lib/libthr/thread/thr_condattr.c =================================================================== --- head/lib/libthr/thread/thr_condattr.c (revision 337991) +++ head/lib/libthr/thread/thr_condattr.c (revision 337992) @@ -1,128 +1,130 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1997 John Birrell . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include "un-namespace.h" #include "thr_private.h" __weak_reference(_pthread_condattr_init, pthread_condattr_init); __weak_reference(_pthread_condattr_destroy, pthread_condattr_destroy); __weak_reference(_pthread_condattr_getclock, pthread_condattr_getclock); __weak_reference(_pthread_condattr_setclock, pthread_condattr_setclock); __weak_reference(_pthread_condattr_getpshared, pthread_condattr_getpshared); __weak_reference(_pthread_condattr_setpshared, pthread_condattr_setpshared); int _pthread_condattr_init(pthread_condattr_t *attr) { pthread_condattr_t pattr; int ret; if ((pattr = (pthread_condattr_t) malloc(sizeof(struct pthread_cond_attr))) == NULL) { ret = ENOMEM; } else { memcpy(pattr, &_pthread_condattr_default, sizeof(struct pthread_cond_attr)); *attr = pattr; ret = 0; } return (ret); } int _pthread_condattr_destroy(pthread_condattr_t *attr) { int ret; if (attr == NULL || *attr == NULL) { ret = EINVAL; } else { free(*attr); *attr = NULL; ret = 0; } return(ret); } int -_pthread_condattr_getclock(const pthread_condattr_t *attr, clockid_t *clock_id) +_pthread_condattr_getclock(const pthread_condattr_t * __restrict attr, + clockid_t * __restrict clock_id) { if (attr == NULL || *attr == NULL) return (EINVAL); *clock_id = (*attr)->c_clockid; return (0); } int _pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id) { if (attr == NULL || *attr == NULL) return (EINVAL); if (clock_id != CLOCK_REALTIME && clock_id != CLOCK_VIRTUAL && clock_id != CLOCK_PROF && clock_id != CLOCK_MONOTONIC) { return (EINVAL); } (*attr)->c_clockid = clock_id; return (0); } int -_pthread_condattr_getpshared(const pthread_condattr_t *attr, int *pshared) +_pthread_condattr_getpshared(const pthread_condattr_t * __restrict attr, + int * __restrict pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); *pshared = (*attr)->c_pshared; return (0); } int _pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) { if (attr == NULL || *attr == NULL || (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)) return (EINVAL); (*attr)->c_pshared = pshared; return (0); } Index: head/lib/libthr/thread/thr_create.c =================================================================== --- head/lib/libthr/thread/thr_create.c (revision 337991) +++ head/lib/libthr/thread/thr_create.c (revision 337992) @@ -1,295 +1,296 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2003 Daniel M. Eischen * Copyright (c) 2005, David Xu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #include #include #include "un-namespace.h" #include "libc_private.h" #include "thr_private.h" static int create_stack(struct pthread_attr *pattr); static void thread_start(struct pthread *curthread); __weak_reference(_pthread_create, pthread_create); int -_pthread_create(pthread_t * thread, const pthread_attr_t * attr, - void *(*start_routine) (void *), void *arg) +_pthread_create(pthread_t * __restrict thread, + const pthread_attr_t * __restrict attr, void *(*start_routine) (void *), + void * __restrict arg) { struct pthread *curthread, *new_thread; struct thr_param param; struct sched_param sched_param; struct rtprio rtp; sigset_t set, oset; cpuset_t *cpusetp; int i, cpusetsize, create_suspended, locked, old_stack_prot, ret; cpusetp = NULL; ret = cpusetsize = 0; _thr_check_init(); /* * Tell libc and others now they need lock to protect their data. */ if (_thr_isthreaded() == 0) { _malloc_first_thread(); if (_thr_setthreaded(1)) return (EAGAIN); } curthread = _get_curthread(); if ((new_thread = _thr_alloc(curthread)) == NULL) return (EAGAIN); memset(¶m, 0, sizeof(param)); if (attr == NULL || *attr == NULL) /* Use the default thread attributes: */ new_thread->attr = _pthread_attr_default; else { new_thread->attr = *(*attr); cpusetp = new_thread->attr.cpuset; cpusetsize = new_thread->attr.cpusetsize; new_thread->attr.cpuset = NULL; new_thread->attr.cpusetsize = 0; } if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) { /* inherit scheduling contention scope */ if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) new_thread->attr.flags |= PTHREAD_SCOPE_SYSTEM; else new_thread->attr.flags &= ~PTHREAD_SCOPE_SYSTEM; new_thread->attr.prio = curthread->attr.prio; new_thread->attr.sched_policy = curthread->attr.sched_policy; } new_thread->tid = TID_TERMINATED; old_stack_prot = _rtld_get_stack_prot(); if (create_stack(&new_thread->attr) != 0) { /* Insufficient memory to create a stack: */ _thr_free(curthread, new_thread); return (EAGAIN); } /* * Write a magic value to the thread structure * to help identify valid ones: */ new_thread->magic = THR_MAGIC; new_thread->start_routine = start_routine; new_thread->arg = arg; new_thread->cancel_enable = 1; new_thread->cancel_async = 0; /* Initialize the mutex queue: */ for (i = 0; i < TMQ_NITEMS; i++) TAILQ_INIT(&new_thread->mq[i]); /* Initialise hooks in the thread structure: */ if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) { new_thread->flags = THR_FLAGS_NEED_SUSPEND; create_suspended = 1; } else { create_suspended = 0; } new_thread->state = PS_RUNNING; if (new_thread->attr.flags & PTHREAD_CREATE_DETACHED) new_thread->flags |= THR_FLAGS_DETACHED; /* Add the new thread. */ new_thread->refcount = 1; _thr_link(curthread, new_thread); /* * Handle the race between __pthread_map_stacks_exec and * thread linkage. */ if (old_stack_prot != _rtld_get_stack_prot()) _thr_stack_fix_protection(new_thread); /* Return thread pointer eariler so that new thread can use it. */ (*thread) = new_thread; if (SHOULD_REPORT_EVENT(curthread, TD_CREATE) || cpusetp != NULL) { THR_THREAD_LOCK(curthread, new_thread); locked = 1; } else locked = 0; param.start_func = (void (*)(void *)) thread_start; param.arg = new_thread; param.stack_base = new_thread->attr.stackaddr_attr; param.stack_size = new_thread->attr.stacksize_attr; param.tls_base = (char *)new_thread->tcb; param.tls_size = sizeof(struct tcb); param.child_tid = &new_thread->tid; param.parent_tid = &new_thread->tid; param.flags = 0; if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM) param.flags |= THR_SYSTEM_SCOPE; if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED) param.rtp = NULL; else { sched_param.sched_priority = new_thread->attr.prio; _schedparam_to_rtp(new_thread->attr.sched_policy, &sched_param, &rtp); param.rtp = &rtp; } /* Schedule the new thread. */ if (create_suspended) { SIGFILLSET(set); SIGDELSET(set, SIGTRAP); __sys_sigprocmask(SIG_SETMASK, &set, &oset); new_thread->sigmask = oset; SIGDELSET(new_thread->sigmask, SIGCANCEL); } ret = thr_new(¶m, sizeof(param)); if (ret != 0) { ret = errno; /* * Translate EPROCLIM into well-known POSIX code EAGAIN. */ if (ret == EPROCLIM) ret = EAGAIN; } if (create_suspended) __sys_sigprocmask(SIG_SETMASK, &oset, NULL); if (ret != 0) { if (!locked) THR_THREAD_LOCK(curthread, new_thread); new_thread->state = PS_DEAD; new_thread->tid = TID_TERMINATED; new_thread->flags |= THR_FLAGS_DETACHED; new_thread->refcount--; if (new_thread->flags & THR_FLAGS_NEED_SUSPEND) { new_thread->cycle++; _thr_umtx_wake(&new_thread->cycle, INT_MAX, 0); } _thr_try_gc(curthread, new_thread); /* thread lock released */ atomic_add_int(&_thread_active_threads, -1); } else if (locked) { if (cpusetp != NULL) { if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(new_thread), cpusetsize, cpusetp)) { ret = errno; /* kill the new thread */ new_thread->force_exit = 1; new_thread->flags |= THR_FLAGS_DETACHED; _thr_try_gc(curthread, new_thread); /* thread lock released */ goto out; } } _thr_report_creation(curthread, new_thread); THR_THREAD_UNLOCK(curthread, new_thread); } out: if (ret) (*thread) = 0; return (ret); } static int create_stack(struct pthread_attr *pattr) { int ret; /* Check if a stack was specified in the thread attributes: */ if ((pattr->stackaddr_attr) != NULL) { pattr->guardsize_attr = 0; pattr->flags |= THR_STACK_USER; ret = 0; } else ret = _thr_stack_alloc(pattr); return (ret); } static void thread_start(struct pthread *curthread) { sigset_t set; if (curthread->attr.suspend == THR_CREATE_SUSPENDED) set = curthread->sigmask; /* * This is used as a serialization point to allow parent * to report 'new thread' event to debugger or tweak new thread's * attributes before the new thread does real-world work. */ THR_LOCK(curthread); THR_UNLOCK(curthread); if (curthread->force_exit) _pthread_exit(PTHREAD_CANCELED); if (curthread->attr.suspend == THR_CREATE_SUSPENDED) { #if 0 /* Done in THR_UNLOCK() */ _thr_ast(curthread); #endif /* * Parent thread have stored signal mask for us, * we should restore it now. */ __sys_sigprocmask(SIG_SETMASK, &set, NULL); } #ifdef _PTHREAD_FORCED_UNWIND curthread->unwind_stackend = (char *)curthread->attr.stackaddr_attr + curthread->attr.stacksize_attr; #endif /* Run the current thread's start routine with argument: */ _pthread_exit(curthread->start_routine(curthread->arg)); /* This point should never be reached. */ PANIC("Thread has resumed after exit"); } Index: head/lib/libthr/thread/thr_getschedparam.c =================================================================== --- head/lib/libthr/thread/thr_getschedparam.c (revision 337991) +++ head/lib/libthr/thread/thr_getschedparam.c (revision 337992) @@ -1,71 +1,71 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1998 Daniel Eischen . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Daniel Eischen. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include "un-namespace.h" #include "thr_private.h" __weak_reference(_pthread_getschedparam, pthread_getschedparam); int -_pthread_getschedparam(pthread_t pthread, int *policy, - struct sched_param *param) +_pthread_getschedparam(pthread_t pthread, int * __restrict policy, + struct sched_param * __restrict param) { struct pthread *curthread = _get_curthread(); int ret = 0; if (policy == NULL || param == NULL) return (EINVAL); /* * Avoid searching the thread list when it is the current * thread. */ if (pthread == curthread) THR_LOCK(curthread); else if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0))) return (ret); *policy = pthread->attr.sched_policy; param->sched_priority = pthread->attr.prio; THR_THREAD_UNLOCK(curthread, pthread); return (ret); } Index: head/lib/libthr/thread/thr_mutex.c =================================================================== --- head/lib/libthr/thread/thr_mutex.c (revision 337991) +++ head/lib/libthr/thread/thr_mutex.c (revision 337992) @@ -1,1190 +1,1190 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995 John Birrell . * Copyright (c) 2006 David Xu . * Copyright (c) 2015, 2016 The FreeBSD Foundation * * All rights reserved. * * Portions of this software were developed by Konstantin Belousov * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by John Birrell. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include "un-namespace.h" #include "thr_private.h" _Static_assert(sizeof(struct pthread_mutex) <= PAGE_SIZE, "pthread_mutex is too large for off-page"); /* * For adaptive mutexes, how many times to spin doing trylock2 * before entering the kernel to block */ #define MUTEX_ADAPTIVE_SPINS 2000 /* * Prototypes */ int __pthread_mutex_consistent(pthread_mutex_t *mutex); -int __pthread_mutex_init(pthread_mutex_t *mutex, - const pthread_mutexattr_t *mutex_attr); +int __pthread_mutex_init(pthread_mutex_t * __restrict mutex, + const pthread_mutexattr_t * __restrict mutex_attr); int __pthread_mutex_trylock(pthread_mutex_t *mutex); int __pthread_mutex_lock(pthread_mutex_t *mutex); -int __pthread_mutex_timedlock(pthread_mutex_t *mutex, - const struct timespec *abstime); +int __pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex, + const struct timespec * __restrict abstime); int _pthread_mutex_getspinloops_np(pthread_mutex_t *mutex, int *count); int _pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count); int __pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count); int _pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count); int _pthread_mutex_getyieldloops_np(pthread_mutex_t *mutex, int *count); int __pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count); static int mutex_self_trylock(pthread_mutex_t); static int mutex_self_lock(pthread_mutex_t, const struct timespec *abstime); static int mutex_unlock_common(struct pthread_mutex *, bool, int *); static int mutex_lock_sleep(struct pthread *, pthread_mutex_t, const struct timespec *); static void mutex_init_robust(struct pthread *curthread); static int mutex_qidx(struct pthread_mutex *m); static bool is_robust_mutex(struct pthread_mutex *m); static bool is_pshared_mutex(struct pthread_mutex *m); __weak_reference(__pthread_mutex_init, pthread_mutex_init); __strong_reference(__pthread_mutex_init, _pthread_mutex_init); __weak_reference(__pthread_mutex_lock, pthread_mutex_lock); __strong_reference(__pthread_mutex_lock, _pthread_mutex_lock); __weak_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock); __strong_reference(__pthread_mutex_timedlock, _pthread_mutex_timedlock); __weak_reference(__pthread_mutex_trylock, pthread_mutex_trylock); __strong_reference(__pthread_mutex_trylock, _pthread_mutex_trylock); __weak_reference(_pthread_mutex_consistent, pthread_mutex_consistent); __strong_reference(_pthread_mutex_consistent, __pthread_mutex_consistent); /* Single underscore versions provided for libc internal usage: */ /* No difference between libc and application usage of these: */ __weak_reference(_pthread_mutex_destroy, pthread_mutex_destroy); __weak_reference(_pthread_mutex_unlock, pthread_mutex_unlock); __weak_reference(_pthread_mutex_getprioceiling, pthread_mutex_getprioceiling); __weak_reference(_pthread_mutex_setprioceiling, pthread_mutex_setprioceiling); __weak_reference(__pthread_mutex_setspinloops_np, pthread_mutex_setspinloops_np); __strong_reference(__pthread_mutex_setspinloops_np, _pthread_mutex_setspinloops_np); __weak_reference(_pthread_mutex_getspinloops_np, pthread_mutex_getspinloops_np); __weak_reference(__pthread_mutex_setyieldloops_np, pthread_mutex_setyieldloops_np); __strong_reference(__pthread_mutex_setyieldloops_np, _pthread_mutex_setyieldloops_np); __weak_reference(_pthread_mutex_getyieldloops_np, pthread_mutex_getyieldloops_np); __weak_reference(_pthread_mutex_isowned_np, pthread_mutex_isowned_np); static void mutex_init_link(struct pthread_mutex *m) { #if defined(_PTHREADS_INVARIANTS) m->m_qe.tqe_prev = NULL; m->m_qe.tqe_next = NULL; m->m_pqe.tqe_prev = NULL; m->m_pqe.tqe_next = NULL; #endif } static void mutex_assert_is_owned(struct pthread_mutex *m __unused) { #if defined(_PTHREADS_INVARIANTS) if (__predict_false(m->m_qe.tqe_prev == NULL)) PANIC("mutex %p own %#x is not on list %p %p", m, m->m_lock.m_owner, m->m_qe.tqe_prev, m->m_qe.tqe_next); #endif } static void mutex_assert_not_owned(struct pthread *curthread __unused, struct pthread_mutex *m __unused) { #if defined(_PTHREADS_INVARIANTS) if (__predict_false(m->m_qe.tqe_prev != NULL || m->m_qe.tqe_next != NULL)) PANIC("mutex %p own %#x is on list %p %p", m, m->m_lock.m_owner, m->m_qe.tqe_prev, m->m_qe.tqe_next); if (__predict_false(is_robust_mutex(m) && (m->m_lock.m_rb_lnk != 0 || m->m_rb_prev != NULL || (is_pshared_mutex(m) && curthread->robust_list == (uintptr_t)&m->m_lock) || (!is_pshared_mutex(m) && curthread->priv_robust_list == (uintptr_t)&m->m_lock)))) PANIC( "mutex %p own %#x is on robust linkage %p %p head %p phead %p", m, m->m_lock.m_owner, (void *)m->m_lock.m_rb_lnk, m->m_rb_prev, (void *)curthread->robust_list, (void *)curthread->priv_robust_list); #endif } static bool is_pshared_mutex(struct pthread_mutex *m) { return ((m->m_lock.m_flags & USYNC_PROCESS_SHARED) != 0); } static bool is_robust_mutex(struct pthread_mutex *m) { return ((m->m_lock.m_flags & UMUTEX_ROBUST) != 0); } int _mutex_enter_robust(struct pthread *curthread, struct pthread_mutex *m) { #if defined(_PTHREADS_INVARIANTS) if (__predict_false(curthread->inact_mtx != 0)) PANIC("inact_mtx enter"); #endif if (!is_robust_mutex(m)) return (0); mutex_init_robust(curthread); curthread->inact_mtx = (uintptr_t)&m->m_lock; return (1); } void _mutex_leave_robust(struct pthread *curthread, struct pthread_mutex *m __unused) { #if defined(_PTHREADS_INVARIANTS) if (__predict_false(curthread->inact_mtx != (uintptr_t)&m->m_lock)) PANIC("inact_mtx leave"); #endif curthread->inact_mtx = 0; } static int mutex_check_attr(const struct pthread_mutex_attr *attr) { if (attr->m_type < PTHREAD_MUTEX_ERRORCHECK || attr->m_type >= PTHREAD_MUTEX_TYPE_MAX) return (EINVAL); if (attr->m_protocol < PTHREAD_PRIO_NONE || attr->m_protocol > PTHREAD_PRIO_PROTECT) return (EINVAL); return (0); } static void mutex_init_robust(struct pthread *curthread) { struct umtx_robust_lists_params rb; if (curthread == NULL) curthread = _get_curthread(); if (curthread->robust_inited) return; rb.robust_list_offset = (uintptr_t)&curthread->robust_list; rb.robust_priv_list_offset = (uintptr_t)&curthread->priv_robust_list; rb.robust_inact_offset = (uintptr_t)&curthread->inact_mtx; _umtx_op(NULL, UMTX_OP_ROBUST_LISTS, sizeof(rb), &rb, NULL); curthread->robust_inited = 1; } static void mutex_init_body(struct pthread_mutex *pmutex, const struct pthread_mutex_attr *attr) { pmutex->m_flags = attr->m_type; pmutex->m_count = 0; pmutex->m_spinloops = 0; pmutex->m_yieldloops = 0; mutex_init_link(pmutex); switch (attr->m_protocol) { case PTHREAD_PRIO_NONE: pmutex->m_lock.m_owner = UMUTEX_UNOWNED; pmutex->m_lock.m_flags = 0; break; case PTHREAD_PRIO_INHERIT: pmutex->m_lock.m_owner = UMUTEX_UNOWNED; pmutex->m_lock.m_flags = UMUTEX_PRIO_INHERIT; break; case PTHREAD_PRIO_PROTECT: pmutex->m_lock.m_owner = UMUTEX_CONTESTED; pmutex->m_lock.m_flags = UMUTEX_PRIO_PROTECT; pmutex->m_lock.m_ceilings[0] = attr->m_ceiling; break; } if (attr->m_pshared == PTHREAD_PROCESS_SHARED) pmutex->m_lock.m_flags |= USYNC_PROCESS_SHARED; if (attr->m_robust == PTHREAD_MUTEX_ROBUST) { mutex_init_robust(NULL); pmutex->m_lock.m_flags |= UMUTEX_ROBUST; } if (PMUTEX_TYPE(pmutex->m_flags) == PTHREAD_MUTEX_ADAPTIVE_NP) { pmutex->m_spinloops = _thr_spinloops ? _thr_spinloops: MUTEX_ADAPTIVE_SPINS; pmutex->m_yieldloops = _thr_yieldloops; } } static int mutex_init(pthread_mutex_t *mutex, const struct pthread_mutex_attr *mutex_attr, void *(calloc_cb)(size_t, size_t)) { const struct pthread_mutex_attr *attr; struct pthread_mutex *pmutex; int error; if (mutex_attr == NULL) { attr = &_pthread_mutexattr_default; } else { attr = mutex_attr; error = mutex_check_attr(attr); if (error != 0) return (error); } if ((pmutex = (pthread_mutex_t) calloc_cb(1, sizeof(struct pthread_mutex))) == NULL) return (ENOMEM); mutex_init_body(pmutex, attr); *mutex = pmutex; return (0); } static int init_static(struct pthread *thread, pthread_mutex_t *mutex) { int ret; THR_LOCK_ACQUIRE(thread, &_mutex_static_lock); if (*mutex == THR_MUTEX_INITIALIZER) ret = mutex_init(mutex, &_pthread_mutexattr_default, calloc); else if (*mutex == THR_ADAPTIVE_MUTEX_INITIALIZER) ret = mutex_init(mutex, &_pthread_mutexattr_adaptive_default, calloc); else ret = 0; THR_LOCK_RELEASE(thread, &_mutex_static_lock); return (ret); } static void set_inherited_priority(struct pthread *curthread, struct pthread_mutex *m) { struct pthread_mutex *m2; m2 = TAILQ_LAST(&curthread->mq[mutex_qidx(m)], mutex_queue); if (m2 != NULL) m->m_lock.m_ceilings[1] = m2->m_lock.m_ceilings[0]; else m->m_lock.m_ceilings[1] = -1; } static void shared_mutex_init(struct pthread_mutex *pmtx, const struct pthread_mutex_attr *mutex_attr) { static const struct pthread_mutex_attr foobar_mutex_attr = { .m_type = PTHREAD_MUTEX_DEFAULT, .m_protocol = PTHREAD_PRIO_NONE, .m_ceiling = 0, .m_pshared = PTHREAD_PROCESS_SHARED, .m_robust = PTHREAD_MUTEX_STALLED, }; bool done; /* * Hack to allow multiple pthread_mutex_init() calls on the * same process-shared mutex. We rely on kernel allocating * zeroed offpage for the mutex, i.e. the * PMUTEX_INITSTAGE_ALLOC value must be zero. */ for (done = false; !done;) { switch (pmtx->m_ps) { case PMUTEX_INITSTAGE_DONE: atomic_thread_fence_acq(); done = true; break; case PMUTEX_INITSTAGE_ALLOC: if (atomic_cmpset_int(&pmtx->m_ps, PMUTEX_INITSTAGE_ALLOC, PMUTEX_INITSTAGE_BUSY)) { if (mutex_attr == NULL) mutex_attr = &foobar_mutex_attr; mutex_init_body(pmtx, mutex_attr); atomic_store_rel_int(&pmtx->m_ps, PMUTEX_INITSTAGE_DONE); done = true; } break; case PMUTEX_INITSTAGE_BUSY: _pthread_yield(); break; default: PANIC("corrupted offpage"); break; } } } int -__pthread_mutex_init(pthread_mutex_t *mutex, - const pthread_mutexattr_t *mutex_attr) +__pthread_mutex_init(pthread_mutex_t * __restrict mutex, + const pthread_mutexattr_t * __restrict mutex_attr) { struct pthread_mutex *pmtx; int ret; if (mutex_attr != NULL) { ret = mutex_check_attr(*mutex_attr); if (ret != 0) return (ret); } if (mutex_attr == NULL || (*mutex_attr)->m_pshared == PTHREAD_PROCESS_PRIVATE) { return (mutex_init(mutex, mutex_attr ? *mutex_attr : NULL, calloc)); } - pmtx = __thr_pshared_offpage(mutex, 1); + pmtx = __thr_pshared_offpage(__DECONST(void *, mutex), 1); if (pmtx == NULL) return (EFAULT); *mutex = THR_PSHARED_PTR; shared_mutex_init(pmtx, *mutex_attr); return (0); } /* This function is used internally by malloc. */ int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, void *(calloc_cb)(size_t, size_t)) { static const struct pthread_mutex_attr attr = { .m_type = PTHREAD_MUTEX_NORMAL, .m_protocol = PTHREAD_PRIO_NONE, .m_ceiling = 0, .m_pshared = PTHREAD_PROCESS_PRIVATE, .m_robust = PTHREAD_MUTEX_STALLED, }; int ret; ret = mutex_init(mutex, &attr, calloc_cb); if (ret == 0) (*mutex)->m_flags |= PMUTEX_FLAG_PRIVATE; return (ret); } /* * Fix mutex ownership for child process. * * Process private mutex ownership is transmitted from the forking * thread to the child process. * * Process shared mutex should not be inherited because owner is * forking thread which is in parent process, they are removed from * the owned mutex list. */ static void queue_fork(struct pthread *curthread, struct mutex_queue *q, struct mutex_queue *qp, uint bit) { struct pthread_mutex *m; TAILQ_INIT(q); TAILQ_FOREACH(m, qp, m_pqe) { TAILQ_INSERT_TAIL(q, m, m_qe); m->m_lock.m_owner = TID(curthread) | bit; } } void _mutex_fork(struct pthread *curthread) { queue_fork(curthread, &curthread->mq[TMQ_NORM], &curthread->mq[TMQ_NORM_PRIV], 0); queue_fork(curthread, &curthread->mq[TMQ_NORM_PP], &curthread->mq[TMQ_NORM_PP_PRIV], UMUTEX_CONTESTED); queue_fork(curthread, &curthread->mq[TMQ_ROBUST_PP], &curthread->mq[TMQ_ROBUST_PP_PRIV], UMUTEX_CONTESTED); curthread->robust_list = 0; } int _pthread_mutex_destroy(pthread_mutex_t *mutex) { pthread_mutex_t m, m1; int ret; m = *mutex; if (m < THR_MUTEX_DESTROYED) { ret = 0; } else if (m == THR_MUTEX_DESTROYED) { ret = EINVAL; } else { if (m == THR_PSHARED_PTR) { m1 = __thr_pshared_offpage(mutex, 0); if (m1 != NULL) { mutex_assert_not_owned(_get_curthread(), m1); __thr_pshared_destroy(mutex); } *mutex = THR_MUTEX_DESTROYED; return (0); } if (PMUTEX_OWNER_ID(m) != 0 && (uint32_t)m->m_lock.m_owner != UMUTEX_RB_NOTRECOV) { ret = EBUSY; } else { *mutex = THR_MUTEX_DESTROYED; mutex_assert_not_owned(_get_curthread(), m); free(m); ret = 0; } } return (ret); } static int mutex_qidx(struct pthread_mutex *m) { if ((m->m_lock.m_flags & UMUTEX_PRIO_PROTECT) == 0) return (TMQ_NORM); return (is_robust_mutex(m) ? TMQ_ROBUST_PP : TMQ_NORM_PP); } /* * Both enqueue_mutex() and dequeue_mutex() operate on the * thread-private linkage of the locked mutexes and on the robust * linkage. * * Robust list, as seen by kernel, must be consistent even in the case * of thread termination at arbitrary moment. Since either enqueue or * dequeue for list walked by kernel consists of rewriting a single * forward pointer, it is safe. On the other hand, rewrite of the * back pointer is not atomic WRT the forward one, but kernel does not * care. */ static void enqueue_mutex(struct pthread *curthread, struct pthread_mutex *m, int error) { struct pthread_mutex *m1; uintptr_t *rl; int qidx; /* Add to the list of owned mutexes: */ if (error != EOWNERDEAD) mutex_assert_not_owned(curthread, m); qidx = mutex_qidx(m); TAILQ_INSERT_TAIL(&curthread->mq[qidx], m, m_qe); if (!is_pshared_mutex(m)) TAILQ_INSERT_TAIL(&curthread->mq[qidx + 1], m, m_pqe); if (is_robust_mutex(m)) { rl = is_pshared_mutex(m) ? &curthread->robust_list : &curthread->priv_robust_list; m->m_rb_prev = NULL; if (*rl != 0) { m1 = __containerof((void *)*rl, struct pthread_mutex, m_lock); m->m_lock.m_rb_lnk = (uintptr_t)&m1->m_lock; m1->m_rb_prev = m; } else { m1 = NULL; m->m_lock.m_rb_lnk = 0; } *rl = (uintptr_t)&m->m_lock; } } static void dequeue_mutex(struct pthread *curthread, struct pthread_mutex *m) { struct pthread_mutex *mp, *mn; int qidx; mutex_assert_is_owned(m); qidx = mutex_qidx(m); if (is_robust_mutex(m)) { mp = m->m_rb_prev; if (mp == NULL) { if (is_pshared_mutex(m)) { curthread->robust_list = m->m_lock.m_rb_lnk; } else { curthread->priv_robust_list = m->m_lock.m_rb_lnk; } } else { mp->m_lock.m_rb_lnk = m->m_lock.m_rb_lnk; } if (m->m_lock.m_rb_lnk != 0) { mn = __containerof((void *)m->m_lock.m_rb_lnk, struct pthread_mutex, m_lock); mn->m_rb_prev = m->m_rb_prev; } m->m_lock.m_rb_lnk = 0; m->m_rb_prev = NULL; } TAILQ_REMOVE(&curthread->mq[qidx], m, m_qe); if (!is_pshared_mutex(m)) TAILQ_REMOVE(&curthread->mq[qidx + 1], m, m_pqe); if ((m->m_lock.m_flags & UMUTEX_PRIO_PROTECT) != 0) set_inherited_priority(curthread, m); mutex_init_link(m); } static int check_and_init_mutex(pthread_mutex_t *mutex, struct pthread_mutex **m) { int ret; *m = *mutex; ret = 0; if (*m == THR_PSHARED_PTR) { *m = __thr_pshared_offpage(mutex, 0); if (*m == NULL) ret = EINVAL; else shared_mutex_init(*m, NULL); } else if (__predict_false(*m <= THR_MUTEX_DESTROYED)) { if (*m == THR_MUTEX_DESTROYED) { ret = EINVAL; } else { ret = init_static(_get_curthread(), mutex); if (ret == 0) *m = *mutex; } } return (ret); } int __pthread_mutex_trylock(pthread_mutex_t *mutex) { struct pthread *curthread; struct pthread_mutex *m; uint32_t id; int ret, robust; ret = check_and_init_mutex(mutex, &m); if (ret != 0) return (ret); curthread = _get_curthread(); id = TID(curthread); if (m->m_flags & PMUTEX_FLAG_PRIVATE) THR_CRITICAL_ENTER(curthread); robust = _mutex_enter_robust(curthread, m); ret = _thr_umutex_trylock(&m->m_lock, id); if (__predict_true(ret == 0) || ret == EOWNERDEAD) { enqueue_mutex(curthread, m, ret); if (ret == EOWNERDEAD) m->m_lock.m_flags |= UMUTEX_NONCONSISTENT; } else if (PMUTEX_OWNER_ID(m) == id) { ret = mutex_self_trylock(m); } /* else {} */ if (robust) _mutex_leave_robust(curthread, m); if (ret != 0 && ret != EOWNERDEAD && (m->m_flags & PMUTEX_FLAG_PRIVATE) != 0) THR_CRITICAL_LEAVE(curthread); return (ret); } static int mutex_lock_sleep(struct pthread *curthread, struct pthread_mutex *m, const struct timespec *abstime) { uint32_t id, owner; int count, ret; id = TID(curthread); if (PMUTEX_OWNER_ID(m) == id) return (mutex_self_lock(m, abstime)); /* * For adaptive mutexes, spin for a bit in the expectation * that if the application requests this mutex type then * the lock is likely to be released quickly and it is * faster than entering the kernel */ if (__predict_false((m->m_lock.m_flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT | UMUTEX_ROBUST | UMUTEX_NONCONSISTENT)) != 0)) goto sleep_in_kernel; if (!_thr_is_smp) goto yield_loop; count = m->m_spinloops; while (count--) { owner = m->m_lock.m_owner; if ((owner & ~UMUTEX_CONTESTED) == 0) { if (atomic_cmpset_acq_32(&m->m_lock.m_owner, owner, id | owner)) { ret = 0; goto done; } } CPU_SPINWAIT; } yield_loop: count = m->m_yieldloops; while (count--) { _sched_yield(); owner = m->m_lock.m_owner; if ((owner & ~UMUTEX_CONTESTED) == 0) { if (atomic_cmpset_acq_32(&m->m_lock.m_owner, owner, id | owner)) { ret = 0; goto done; } } } sleep_in_kernel: if (abstime == NULL) ret = __thr_umutex_lock(&m->m_lock, id); else if (__predict_false(abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) ret = EINVAL; else ret = __thr_umutex_timedlock(&m->m_lock, id, abstime); done: if (ret == 0 || ret == EOWNERDEAD) { enqueue_mutex(curthread, m, ret); if (ret == EOWNERDEAD) m->m_lock.m_flags |= UMUTEX_NONCONSISTENT; } return (ret); } static inline int mutex_lock_common(struct pthread_mutex *m, const struct timespec *abstime, bool cvattach, bool rb_onlist) { struct pthread *curthread; int ret, robust; robust = 0; /* pacify gcc */ curthread = _get_curthread(); if (!cvattach && m->m_flags & PMUTEX_FLAG_PRIVATE) THR_CRITICAL_ENTER(curthread); if (!rb_onlist) robust = _mutex_enter_robust(curthread, m); ret = _thr_umutex_trylock2(&m->m_lock, TID(curthread)); if (ret == 0 || ret == EOWNERDEAD) { enqueue_mutex(curthread, m, ret); if (ret == EOWNERDEAD) m->m_lock.m_flags |= UMUTEX_NONCONSISTENT; } else { ret = mutex_lock_sleep(curthread, m, abstime); } if (!rb_onlist && robust) _mutex_leave_robust(curthread, m); if (ret != 0 && ret != EOWNERDEAD && (m->m_flags & PMUTEX_FLAG_PRIVATE) != 0 && !cvattach) THR_CRITICAL_LEAVE(curthread); return (ret); } int __pthread_mutex_lock(pthread_mutex_t *mutex) { struct pthread_mutex *m; int ret; _thr_check_init(); ret = check_and_init_mutex(mutex, &m); if (ret == 0) ret = mutex_lock_common(m, NULL, false, false); return (ret); } int -__pthread_mutex_timedlock(pthread_mutex_t *mutex, - const struct timespec *abstime) +__pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex, + const struct timespec * __restrict abstime) { struct pthread_mutex *m; int ret; _thr_check_init(); ret = check_and_init_mutex(mutex, &m); if (ret == 0) ret = mutex_lock_common(m, abstime, false, false); return (ret); } int _pthread_mutex_unlock(pthread_mutex_t *mutex) { struct pthread_mutex *mp; if (*mutex == THR_PSHARED_PTR) { mp = __thr_pshared_offpage(mutex, 0); if (mp == NULL) return (EINVAL); shared_mutex_init(mp, NULL); } else { mp = *mutex; } return (mutex_unlock_common(mp, false, NULL)); } int _mutex_cv_lock(struct pthread_mutex *m, int count, bool rb_onlist) { int error; error = mutex_lock_common(m, NULL, true, rb_onlist); if (error == 0 || error == EOWNERDEAD) m->m_count = count; return (error); } int _mutex_cv_unlock(struct pthread_mutex *m, int *count, int *defer) { /* * Clear the count in case this is a recursive mutex. */ *count = m->m_count; m->m_count = 0; (void)mutex_unlock_common(m, true, defer); return (0); } int _mutex_cv_attach(struct pthread_mutex *m, int count) { struct pthread *curthread; curthread = _get_curthread(); enqueue_mutex(curthread, m, 0); m->m_count = count; return (0); } int _mutex_cv_detach(struct pthread_mutex *mp, int *recurse) { struct pthread *curthread; int deferred, error; curthread = _get_curthread(); if ((error = _mutex_owned(curthread, mp)) != 0) return (error); /* * Clear the count in case this is a recursive mutex. */ *recurse = mp->m_count; mp->m_count = 0; dequeue_mutex(curthread, mp); /* Will this happen in real-world ? */ if ((mp->m_flags & PMUTEX_FLAG_DEFERRED) != 0) { deferred = 1; mp->m_flags &= ~PMUTEX_FLAG_DEFERRED; } else deferred = 0; if (deferred) { _thr_wake_all(curthread->defer_waiters, curthread->nwaiter_defer); curthread->nwaiter_defer = 0; } return (0); } static int mutex_self_trylock(struct pthread_mutex *m) { int ret; switch (PMUTEX_TYPE(m->m_flags)) { case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_ADAPTIVE_NP: ret = EBUSY; break; case PTHREAD_MUTEX_RECURSIVE: /* Increment the lock count: */ if (m->m_count + 1 > 0) { m->m_count++; ret = 0; } else ret = EAGAIN; break; default: /* Trap invalid mutex types; */ ret = EINVAL; } return (ret); } static int mutex_self_lock(struct pthread_mutex *m, const struct timespec *abstime) { struct timespec ts1, ts2; int ret; switch (PMUTEX_TYPE(m->m_flags)) { case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_ADAPTIVE_NP: if (abstime) { if (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { ret = EINVAL; } else { clock_gettime(CLOCK_REALTIME, &ts1); TIMESPEC_SUB(&ts2, abstime, &ts1); __sys_nanosleep(&ts2, NULL); ret = ETIMEDOUT; } } else { /* * POSIX specifies that mutexes should return * EDEADLK if a recursive lock is detected. */ ret = EDEADLK; } break; case PTHREAD_MUTEX_NORMAL: /* * What SS2 define as a 'normal' mutex. Intentionally * deadlock on attempts to get a lock you already own. */ ret = 0; if (abstime) { if (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { ret = EINVAL; } else { clock_gettime(CLOCK_REALTIME, &ts1); TIMESPEC_SUB(&ts2, abstime, &ts1); __sys_nanosleep(&ts2, NULL); ret = ETIMEDOUT; } } else { ts1.tv_sec = 30; ts1.tv_nsec = 0; for (;;) __sys_nanosleep(&ts1, NULL); } break; case PTHREAD_MUTEX_RECURSIVE: /* Increment the lock count: */ if (m->m_count + 1 > 0) { m->m_count++; ret = 0; } else ret = EAGAIN; break; default: /* Trap invalid mutex types; */ ret = EINVAL; } return (ret); } static int mutex_unlock_common(struct pthread_mutex *m, bool cv, int *mtx_defer) { struct pthread *curthread; uint32_t id; int deferred, error, robust; if (__predict_false(m <= THR_MUTEX_DESTROYED)) { if (m == THR_MUTEX_DESTROYED) return (EINVAL); return (EPERM); } curthread = _get_curthread(); id = TID(curthread); /* * Check if the running thread is not the owner of the mutex. */ if (__predict_false(PMUTEX_OWNER_ID(m) != id)) return (EPERM); error = 0; if (__predict_false(PMUTEX_TYPE(m->m_flags) == PTHREAD_MUTEX_RECURSIVE && m->m_count > 0)) { m->m_count--; } else { if ((m->m_flags & PMUTEX_FLAG_DEFERRED) != 0) { deferred = 1; m->m_flags &= ~PMUTEX_FLAG_DEFERRED; } else deferred = 0; robust = _mutex_enter_robust(curthread, m); dequeue_mutex(curthread, m); error = _thr_umutex_unlock2(&m->m_lock, id, mtx_defer); if (deferred) { if (mtx_defer == NULL) { _thr_wake_all(curthread->defer_waiters, curthread->nwaiter_defer); curthread->nwaiter_defer = 0; } else *mtx_defer = 1; } if (robust) _mutex_leave_robust(curthread, m); } if (!cv && m->m_flags & PMUTEX_FLAG_PRIVATE) THR_CRITICAL_LEAVE(curthread); return (error); } int -_pthread_mutex_getprioceiling(pthread_mutex_t *mutex, - int *prioceiling) +_pthread_mutex_getprioceiling(const pthread_mutex_t * __restrict mutex, + int * __restrict prioceiling) { struct pthread_mutex *m; if (*mutex == THR_PSHARED_PTR) { - m = __thr_pshared_offpage(mutex, 0); + m = __thr_pshared_offpage(__DECONST(void *, mutex), 0); if (m == NULL) return (EINVAL); shared_mutex_init(m, NULL); } else { m = *mutex; if (m <= THR_MUTEX_DESTROYED) return (EINVAL); } if ((m->m_lock.m_flags & UMUTEX_PRIO_PROTECT) == 0) return (EINVAL); *prioceiling = m->m_lock.m_ceilings[0]; return (0); } int -_pthread_mutex_setprioceiling(pthread_mutex_t *mutex, - int ceiling, int *old_ceiling) +_pthread_mutex_setprioceiling(pthread_mutex_t * __restrict mutex, + int ceiling, int * __restrict old_ceiling) { struct pthread *curthread; struct pthread_mutex *m, *m1, *m2; struct mutex_queue *q, *qp; int qidx, ret; if (*mutex == THR_PSHARED_PTR) { m = __thr_pshared_offpage(mutex, 0); if (m == NULL) return (EINVAL); shared_mutex_init(m, NULL); } else { m = *mutex; if (m <= THR_MUTEX_DESTROYED) return (EINVAL); } if ((m->m_lock.m_flags & UMUTEX_PRIO_PROTECT) == 0) return (EINVAL); ret = __thr_umutex_set_ceiling(&m->m_lock, ceiling, old_ceiling); if (ret != 0) return (ret); curthread = _get_curthread(); if (PMUTEX_OWNER_ID(m) == TID(curthread)) { mutex_assert_is_owned(m); m1 = TAILQ_PREV(m, mutex_queue, m_qe); m2 = TAILQ_NEXT(m, m_qe); if ((m1 != NULL && m1->m_lock.m_ceilings[0] > (u_int)ceiling) || (m2 != NULL && m2->m_lock.m_ceilings[0] < (u_int)ceiling)) { qidx = mutex_qidx(m); q = &curthread->mq[qidx]; qp = &curthread->mq[qidx + 1]; TAILQ_REMOVE(q, m, m_qe); if (!is_pshared_mutex(m)) TAILQ_REMOVE(qp, m, m_pqe); TAILQ_FOREACH(m2, q, m_qe) { if (m2->m_lock.m_ceilings[0] > (u_int)ceiling) { TAILQ_INSERT_BEFORE(m2, m, m_qe); if (!is_pshared_mutex(m)) { while (m2 != NULL && is_pshared_mutex(m2)) { m2 = TAILQ_PREV(m2, mutex_queue, m_qe); } if (m2 == NULL) { TAILQ_INSERT_HEAD(qp, m, m_pqe); } else { TAILQ_INSERT_BEFORE(m2, m, m_pqe); } } return (0); } } TAILQ_INSERT_TAIL(q, m, m_qe); if (!is_pshared_mutex(m)) TAILQ_INSERT_TAIL(qp, m, m_pqe); } } return (0); } int _pthread_mutex_getspinloops_np(pthread_mutex_t *mutex, int *count) { struct pthread_mutex *m; int ret; ret = check_and_init_mutex(mutex, &m); if (ret == 0) *count = m->m_spinloops; return (ret); } int __pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count) { struct pthread_mutex *m; int ret; ret = check_and_init_mutex(mutex, &m); if (ret == 0) m->m_spinloops = count; return (ret); } int _pthread_mutex_getyieldloops_np(pthread_mutex_t *mutex, int *count) { struct pthread_mutex *m; int ret; ret = check_and_init_mutex(mutex, &m); if (ret == 0) *count = m->m_yieldloops; return (ret); } int __pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count) { struct pthread_mutex *m; int ret; ret = check_and_init_mutex(mutex, &m); if (ret == 0) m->m_yieldloops = count; return (0); } int _pthread_mutex_isowned_np(pthread_mutex_t *mutex) { struct pthread_mutex *m; if (*mutex == THR_PSHARED_PTR) { m = __thr_pshared_offpage(mutex, 0); if (m == NULL) return (0); shared_mutex_init(m, NULL); } else { m = *mutex; if (m <= THR_MUTEX_DESTROYED) return (0); } return (PMUTEX_OWNER_ID(m) == TID(_get_curthread())); } int _mutex_owned(struct pthread *curthread, const struct pthread_mutex *mp) { if (__predict_false(mp <= THR_MUTEX_DESTROYED)) { if (mp == THR_MUTEX_DESTROYED) return (EINVAL); return (EPERM); } if (PMUTEX_OWNER_ID(mp) != TID(curthread)) return (EPERM); return (0); } int _pthread_mutex_consistent(pthread_mutex_t *mutex) { struct pthread_mutex *m; struct pthread *curthread; if (*mutex == THR_PSHARED_PTR) { m = __thr_pshared_offpage(mutex, 0); if (m == NULL) return (EINVAL); shared_mutex_init(m, NULL); } else { m = *mutex; if (m <= THR_MUTEX_DESTROYED) return (EINVAL); } curthread = _get_curthread(); if ((m->m_lock.m_flags & (UMUTEX_ROBUST | UMUTEX_NONCONSISTENT)) != (UMUTEX_ROBUST | UMUTEX_NONCONSISTENT)) return (EINVAL); if (PMUTEX_OWNER_ID(m) != TID(curthread)) return (EPERM); m->m_lock.m_flags &= ~UMUTEX_NONCONSISTENT; return (0); } Index: head/lib/libthr/thread/thr_mutexattr.c =================================================================== --- head/lib/libthr/thread/thr_mutexattr.c (revision 337991) +++ head/lib/libthr/thread/thr_mutexattr.c (revision 337992) @@ -1,292 +1,295 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1996 Jeffrey Hsu . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1997 John Birrell . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include "un-namespace.h" #include "thr_private.h" __weak_reference(_pthread_mutexattr_init, pthread_mutexattr_init); __weak_reference(_pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np); __weak_reference(_pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np); __weak_reference(_pthread_mutexattr_gettype, pthread_mutexattr_gettype); __weak_reference(_pthread_mutexattr_settype, pthread_mutexattr_settype); __weak_reference(_pthread_mutexattr_destroy, pthread_mutexattr_destroy); __weak_reference(_pthread_mutexattr_getpshared, pthread_mutexattr_getpshared); __weak_reference(_pthread_mutexattr_setpshared, pthread_mutexattr_setpshared); __weak_reference(_pthread_mutexattr_getprotocol, pthread_mutexattr_getprotocol); __weak_reference(_pthread_mutexattr_setprotocol, pthread_mutexattr_setprotocol); __weak_reference(_pthread_mutexattr_getprioceiling, pthread_mutexattr_getprioceiling); __weak_reference(_pthread_mutexattr_setprioceiling, pthread_mutexattr_setprioceiling); __weak_reference(_pthread_mutexattr_getrobust, pthread_mutexattr_getrobust); __weak_reference(_pthread_mutexattr_setrobust, pthread_mutexattr_setrobust); int _pthread_mutexattr_init(pthread_mutexattr_t *attr) { int ret; pthread_mutexattr_t pattr; if ((pattr = (pthread_mutexattr_t) malloc(sizeof(struct pthread_mutex_attr))) == NULL) { ret = ENOMEM; } else { memcpy(pattr, &_pthread_mutexattr_default, sizeof(struct pthread_mutex_attr)); *attr = pattr; ret = 0; } return (ret); } int _pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind) { int ret; if (attr == NULL || *attr == NULL) { errno = EINVAL; ret = -1; } else { (*attr)->m_type = kind; ret = 0; } return(ret); } int _pthread_mutexattr_getkind_np(pthread_mutexattr_t attr) { int ret; if (attr == NULL) { errno = EINVAL; ret = -1; } else { ret = attr->m_type; } return (ret); } int _pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { int ret; if (attr == NULL || *attr == NULL || type >= PTHREAD_MUTEX_TYPE_MAX) { ret = EINVAL; } else { (*attr)->m_type = type; ret = 0; } return (ret); } int -_pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *type) +_pthread_mutexattr_gettype(const pthread_mutexattr_t * __restrict attr, + int * __restrict type) { int ret; if (attr == NULL || *attr == NULL || (*attr)->m_type >= PTHREAD_MUTEX_TYPE_MAX) { ret = EINVAL; } else { *type = (*attr)->m_type; ret = 0; } return (ret); } int _pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { int ret; if (attr == NULL || *attr == NULL) { ret = EINVAL; } else { free(*attr); *attr = NULL; ret = 0; } return (ret); } int _pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared) { if (attr == NULL || *attr == NULL) return (EINVAL); *pshared = (*attr)->m_pshared; return (0); } int _pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) { if (attr == NULL || *attr == NULL || (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)) return (EINVAL); (*attr)->m_pshared = pshared; return (0); } int -_pthread_mutexattr_getprotocol(pthread_mutexattr_t *mattr, int *protocol) +_pthread_mutexattr_getprotocol(const pthread_mutexattr_t * __restrict mattr, + int * __restrict protocol) { int ret = 0; if (mattr == NULL || *mattr == NULL) ret = EINVAL; else *protocol = (*mattr)->m_protocol; return (ret); } int _pthread_mutexattr_setprotocol(pthread_mutexattr_t *mattr, int protocol) { int ret = 0; if (mattr == NULL || *mattr == NULL || protocol < PTHREAD_PRIO_NONE || protocol > PTHREAD_PRIO_PROTECT) ret = EINVAL; else { (*mattr)->m_protocol = protocol; (*mattr)->m_ceiling = THR_MAX_RR_PRIORITY; } return (ret); } int -_pthread_mutexattr_getprioceiling(pthread_mutexattr_t *mattr, int *prioceiling) +_pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * __restrict mattr, + int * __restrict prioceiling) { int ret = 0; if (mattr == NULL || *mattr == NULL) ret = EINVAL; else if ((*mattr)->m_protocol != PTHREAD_PRIO_PROTECT) ret = EINVAL; else *prioceiling = (*mattr)->m_ceiling; return (ret); } int _pthread_mutexattr_setprioceiling(pthread_mutexattr_t *mattr, int prioceiling) { int ret = 0; if (mattr == NULL || *mattr == NULL) ret = EINVAL; else if ((*mattr)->m_protocol != PTHREAD_PRIO_PROTECT) ret = EINVAL; else (*mattr)->m_ceiling = prioceiling; return (ret); } int _pthread_mutexattr_getrobust(pthread_mutexattr_t *mattr, int *robust) { int ret; if (mattr == NULL || *mattr == NULL) { ret = EINVAL; } else { ret = 0; *robust = (*mattr)->m_robust; } return (ret); } int _pthread_mutexattr_setrobust(pthread_mutexattr_t *mattr, int robust) { int ret; if (mattr == NULL || *mattr == NULL) { ret = EINVAL; } else if (robust != PTHREAD_MUTEX_STALLED && robust != PTHREAD_MUTEX_ROBUST) { ret = EINVAL; } else { ret = 0; (*mattr)->m_robust = robust; } return (ret); } Index: head/lib/libthr/thread/thr_rwlock.c =================================================================== --- head/lib/libthr/thread/thr_rwlock.c (revision 337991) +++ head/lib/libthr/thread/thr_rwlock.c (revision 337992) @@ -1,377 +1,377 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include "namespace.h" #include #include "un-namespace.h" #include "thr_private.h" _Static_assert(sizeof(struct pthread_rwlock) <= PAGE_SIZE, "pthread_rwlock is too large for off-page"); __weak_reference(_pthread_rwlock_destroy, pthread_rwlock_destroy); __weak_reference(_pthread_rwlock_init, pthread_rwlock_init); __weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); __weak_reference(_pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock); __weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); __weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); __weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); __weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); __weak_reference(_pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock); static int init_static(struct pthread *thread, pthread_rwlock_t *rwlock); static int init_rwlock(pthread_rwlock_t *rwlock, pthread_rwlock_t *rwlock_out); static int __always_inline check_and_init_rwlock(pthread_rwlock_t *rwlock, pthread_rwlock_t *rwlock_out) { if (__predict_false(*rwlock == THR_PSHARED_PTR || *rwlock <= THR_RWLOCK_DESTROYED)) return (init_rwlock(rwlock, rwlock_out)); *rwlock_out = *rwlock; return (0); } static int __noinline init_rwlock(pthread_rwlock_t *rwlock, pthread_rwlock_t *rwlock_out) { pthread_rwlock_t prwlock; int ret; if (*rwlock == THR_PSHARED_PTR) { prwlock = __thr_pshared_offpage(rwlock, 0); if (prwlock == NULL) return (EINVAL); } else if ((prwlock = *rwlock) <= THR_RWLOCK_DESTROYED) { if (prwlock == THR_RWLOCK_INITIALIZER) { ret = init_static(_get_curthread(), rwlock); if (ret != 0) return (ret); } else if (prwlock == THR_RWLOCK_DESTROYED) { return (EINVAL); } prwlock = *rwlock; } *rwlock_out = prwlock; return (0); } static int rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { pthread_rwlock_t prwlock; if (attr == NULL || *attr == NULL || (*attr)->pshared == PTHREAD_PROCESS_PRIVATE) { prwlock = calloc(1, sizeof(struct pthread_rwlock)); if (prwlock == NULL) return (ENOMEM); *rwlock = prwlock; } else { prwlock = __thr_pshared_offpage(rwlock, 1); if (prwlock == NULL) return (EFAULT); prwlock->lock.rw_flags |= USYNC_PROCESS_SHARED; *rwlock = THR_PSHARED_PTR; } return (0); } int _pthread_rwlock_destroy (pthread_rwlock_t *rwlock) { pthread_rwlock_t prwlock; int ret; prwlock = *rwlock; if (prwlock == THR_RWLOCK_INITIALIZER) ret = 0; else if (prwlock == THR_RWLOCK_DESTROYED) ret = EINVAL; else if (prwlock == THR_PSHARED_PTR) { *rwlock = THR_RWLOCK_DESTROYED; __thr_pshared_destroy(rwlock); ret = 0; } else { *rwlock = THR_RWLOCK_DESTROYED; free(prwlock); ret = 0; } return (ret); } static int init_static(struct pthread *thread, pthread_rwlock_t *rwlock) { int ret; THR_LOCK_ACQUIRE(thread, &_rwlock_static_lock); if (*rwlock == THR_RWLOCK_INITIALIZER) ret = rwlock_init(rwlock, NULL); else ret = 0; THR_LOCK_RELEASE(thread, &_rwlock_static_lock); return (ret); } int _pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { *rwlock = NULL; return (rwlock_init(rwlock, attr)); } static int rwlock_rdlock_common(pthread_rwlock_t *rwlock, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; int flags; int ret; ret = check_and_init_rwlock(rwlock, &prwlock); if (ret != 0) return (ret); if (curthread->rdlock_count) { /* * To avoid having to track all the rdlocks held by * a thread or all of the threads that hold a rdlock, * we keep a simple count of all the rdlocks held by * a thread. If a thread holds any rdlocks it is * possible that it is attempting to take a recursive * rdlock. If there are blocked writers and precedence * is given to them, then that would result in the thread * deadlocking. So allowing a thread to take the rdlock * when it already has one or more rdlocks avoids the * deadlock. I hope the reader can follow that logic ;-) */ flags = URWLOCK_PREFER_READER; } else { flags = 0; } /* * POSIX said the validity of the abstimeout parameter need * not be checked if the lock can be immediately acquired. */ ret = _thr_rwlock_tryrdlock(&prwlock->lock, flags); if (ret == 0) { curthread->rdlock_count++; return (ret); } if (__predict_false(abstime && (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0))) return (EINVAL); for (;;) { /* goto kernel and lock it */ ret = __thr_rwlock_rdlock(&prwlock->lock, flags, abstime); if (ret != EINTR) break; /* if interrupted, try to lock it in userland again. */ if (_thr_rwlock_tryrdlock(&prwlock->lock, flags) == 0) { ret = 0; break; } } if (ret == 0) curthread->rdlock_count++; return (ret); } int _pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) { return (rwlock_rdlock_common(rwlock, NULL)); } int -_pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, - const struct timespec *abstime) +_pthread_rwlock_timedrdlock(pthread_rwlock_t * __restrict rwlock, + const struct timespec * __restrict abstime) { return (rwlock_rdlock_common(rwlock, abstime)); } int _pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; int flags; int ret; ret = check_and_init_rwlock(rwlock, &prwlock); if (ret != 0) return (ret); if (curthread->rdlock_count) { /* * To avoid having to track all the rdlocks held by * a thread or all of the threads that hold a rdlock, * we keep a simple count of all the rdlocks held by * a thread. If a thread holds any rdlocks it is * possible that it is attempting to take a recursive * rdlock. If there are blocked writers and precedence * is given to them, then that would result in the thread * deadlocking. So allowing a thread to take the rdlock * when it already has one or more rdlocks avoids the * deadlock. I hope the reader can follow that logic ;-) */ flags = URWLOCK_PREFER_READER; } else { flags = 0; } ret = _thr_rwlock_tryrdlock(&prwlock->lock, flags); if (ret == 0) curthread->rdlock_count++; return (ret); } int _pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; int ret; ret = check_and_init_rwlock(rwlock, &prwlock); if (ret != 0) return (ret); ret = _thr_rwlock_trywrlock(&prwlock->lock); if (ret == 0) prwlock->owner = TID(curthread); return (ret); } static int rwlock_wrlock_common (pthread_rwlock_t *rwlock, const struct timespec *abstime) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; int ret; ret = check_and_init_rwlock(rwlock, &prwlock); if (ret != 0) return (ret); /* * POSIX said the validity of the abstimeout parameter need * not be checked if the lock can be immediately acquired. */ ret = _thr_rwlock_trywrlock(&prwlock->lock); if (ret == 0) { prwlock->owner = TID(curthread); return (ret); } if (__predict_false(abstime && (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0))) return (EINVAL); for (;;) { /* goto kernel and lock it */ ret = __thr_rwlock_wrlock(&prwlock->lock, abstime); if (ret == 0) { prwlock->owner = TID(curthread); break; } if (ret != EINTR) break; /* if interrupted, try to lock it in userland again. */ if (_thr_rwlock_trywrlock(&prwlock->lock) == 0) { ret = 0; prwlock->owner = TID(curthread); break; } } return (ret); } int _pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) { return (rwlock_wrlock_common (rwlock, NULL)); } int -_pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, - const struct timespec *abstime) +_pthread_rwlock_timedwrlock(pthread_rwlock_t * __restrict rwlock, + const struct timespec * __restrict abstime) { return (rwlock_wrlock_common (rwlock, abstime)); } int _pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { struct pthread *curthread = _get_curthread(); pthread_rwlock_t prwlock; int ret; int32_t state; if (*rwlock == THR_PSHARED_PTR) { prwlock = __thr_pshared_offpage(rwlock, 0); if (prwlock == NULL) return (EINVAL); } else { prwlock = *rwlock; } if (__predict_false(prwlock <= THR_RWLOCK_DESTROYED)) return (EINVAL); state = prwlock->lock.rw_state; if (state & URWLOCK_WRITE_OWNER) { if (__predict_false(prwlock->owner != TID(curthread))) return (EPERM); prwlock->owner = 0; } ret = _thr_rwlock_unlock(&prwlock->lock); if (ret == 0 && (state & URWLOCK_WRITE_OWNER) == 0) curthread->rdlock_count--; return (ret); } Index: head/lib/libthr/thread/thr_rwlockattr.c =================================================================== --- head/lib/libthr/thread/thr_rwlockattr.c (revision 337991) +++ head/lib/libthr/thread/thr_rwlockattr.c (revision 337992) @@ -1,94 +1,95 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * 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. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include "un-namespace.h" #include "thr_private.h" __weak_reference(_pthread_rwlockattr_destroy, pthread_rwlockattr_destroy); __weak_reference(_pthread_rwlockattr_getpshared, pthread_rwlockattr_getpshared); __weak_reference(_pthread_rwlockattr_init, pthread_rwlockattr_init); __weak_reference(_pthread_rwlockattr_setpshared, pthread_rwlockattr_setpshared); int _pthread_rwlockattr_destroy(pthread_rwlockattr_t *rwlockattr) { pthread_rwlockattr_t prwlockattr; if (rwlockattr == NULL) return (EINVAL); prwlockattr = *rwlockattr; if (prwlockattr == NULL) return (EINVAL); free(prwlockattr); return (0); } int -_pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *rwlockattr, - int *pshared) +_pthread_rwlockattr_getpshared( + const pthread_rwlockattr_t * __restrict rwlockattr, + int * __restrict pshared) { *pshared = (*rwlockattr)->pshared; return (0); } int _pthread_rwlockattr_init(pthread_rwlockattr_t *rwlockattr) { pthread_rwlockattr_t prwlockattr; if (rwlockattr == NULL) return (EINVAL); prwlockattr = malloc(sizeof(struct pthread_rwlockattr)); if (prwlockattr == NULL) return (ENOMEM); prwlockattr->pshared = PTHREAD_PROCESS_PRIVATE; *rwlockattr = prwlockattr; return (0); } int _pthread_rwlockattr_setpshared(pthread_rwlockattr_t *rwlockattr, int pshared) { if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) return (EINVAL); (*rwlockattr)->pshared = pshared; return (0); } Index: head/share/man/man3/pthread.3 =================================================================== --- head/share/man/man3/pthread.3 (revision 337991) +++ head/share/man/man3/pthread.3 (revision 337992) @@ -1,550 +1,550 @@ .\" 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$ .\" -.Dd August 12, 2014 +.Dd August 17, 2018 .Dt PTHREAD 3 .Os .Sh NAME .Nm pthread .Nd POSIX thread functions .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Sh DESCRIPTION POSIX threads are a set of functions that support applications with requirements for multiple flows of control, called .Em threads , within a process. Multithreading is used to improve the performance of a program. .Pp The POSIX thread functions are summarized in this section in the following groups: .Pp .Bl -bullet -offset indent -compact .It Thread Routines .It Attribute Object Routines .It Mutex Routines .It Condition Variable Routines .It Read/Write Lock Routines .It Per-Thread Context Routines .It Cleanup Routines .El .Ss Thread Routines .Bl -tag -width indent .It Xo .Ft int .Fo pthread_create .Fa "pthread_t *thread" "const pthread_attr_t *attr" .Fa "void *\*[lp]*start_routine\*[rp]\*[lp]void *\*[rp]" "void *arg" .Fc .Xc Creates a new thread of execution. .It Xo .Ft int .Fn pthread_cancel "pthread_t thread" .Xc Cancels execution of a thread. .It Xo .Ft int .Fn pthread_detach "pthread_t thread" .Xc Marks a thread for deletion. .It Xo .Ft int .Fn pthread_equal "pthread_t t1" "pthread_t t2" .Xc Compares two thread IDs. .It Xo .Ft void .Fn pthread_exit "void *value_ptr" .Xc Terminates the calling thread. .It Xo .Ft int .Fn pthread_join "pthread_t thread" "void **value_ptr" .Xc Causes the calling thread to wait for the termination of the specified thread. .It Xo .Ft int .Fn pthread_kill "pthread_t thread" "int sig" .Xc Delivers a signal to a specified thread. .It Xo .Ft int .Fn pthread_once "pthread_once_t *once_control" "void \*[lp]*init_routine\*[rp]\*[lp]void\*[rp]" .Xc Calls an initialization routine once. .It Xo .Ft pthread_t .Fn pthread_self void .Xc Returns the thread ID of the calling thread. .It Xo .Ft int .Fn pthread_setcancelstate "int state" "int *oldstate" .Xc Sets the current thread's cancelability state. .It Xo .Ft int .Fn pthread_setcanceltype "int type" "int *oldtype" .Xc Sets the current thread's cancelability type. .It Xo .Ft void .Fn pthread_testcancel void .Xc Creates a cancellation point in the calling thread. .It Xo .Ft void .Fn pthread_yield void .Xc Allows the scheduler to run another thread instead of the current one. .El .Ss Attribute Object Routines .Bl -tag -width indent .It Xo .Ft int .Fn pthread_attr_destroy "pthread_attr_t *attr" .Xc Destroy a thread attributes object. .It Xo .Ft int .Fo pthread_attr_getinheritsched .Fa "const pthread_attr_t *attr" "int *inheritsched" .Fc .Xc Get the inherit scheduling attribute from a thread attributes object. .It Xo .Ft int .Fo pthread_attr_getschedparam .Fa "const pthread_attr_t *attr" "struct sched_param *param" .Fc .Xc Get the scheduling parameter attribute from a thread attributes object. .It Xo .Ft int .Fn pthread_attr_getschedpolicy "const pthread_attr_t *attr" "int *policy" .Xc Get the scheduling policy attribute from a thread attributes object. .It Xo .Ft int .Fn pthread_attr_getscope "const pthread_attr_t *attr" "int *contentionscope" .Xc Get the contention scope attribute from a thread attributes object. .It Xo .Ft int .Fn pthread_attr_getstacksize "const pthread_attr_t *attr" "size_t *stacksize" .Xc Get the stack size attribute from a thread attributes object. .It Xo .Ft int .Fn pthread_attr_getstackaddr "const pthread_attr_t *attr" "void **stackaddr" .Xc Get the stack address attribute from a thread attributes object. .It Xo .Ft int .Fn pthread_attr_getdetachstate "const pthread_attr_t *attr" "int *detachstate" .Xc Get the detach state attribute from a thread attributes object. .It Xo .Ft int .Fn pthread_attr_init "pthread_attr_t *attr" .Xc Initialize a thread attributes object with default values. .It Xo .Ft int .Fn pthread_attr_setinheritsched "pthread_attr_t *attr" "int inheritsched" .Xc Set the inherit scheduling attribute in a thread attributes object. .It Xo .Ft int .Fo pthread_attr_setschedparam .Fa "pthread_attr_t *attr" "const struct sched_param *param" .Fc .Xc Set the scheduling parameter attribute in a thread attributes object. .It Xo .Ft int .Fn pthread_attr_setschedpolicy "pthread_attr_t *attr" "int policy" .Xc Set the scheduling policy attribute in a thread attributes object. .It Xo .Ft int .Fn pthread_attr_setscope "pthread_attr_t *attr" "int contentionscope" .Xc Set the contention scope attribute in a thread attributes object. .It Xo .Ft int .Fn pthread_attr_setstacksize "pthread_attr_t *attr" "size_t stacksize" .Xc Set the stack size attribute in a thread attributes object. .It Xo .Ft int .Fn pthread_attr_setstackaddr "pthread_attr_t *attr" "void *stackaddr" .Xc Set the stack address attribute in a thread attributes object. .It Xo .Ft int .Fn pthread_attr_setdetachstate "pthread_attr_t *attr" "int detachstate" .Xc Set the detach state in a thread attributes object. .El .Ss Mutex Routines .Bl -tag -width indent .It Xo .Ft int .Fn pthread_mutexattr_destroy "pthread_mutexattr_t *attr" .Xc Destroy a mutex attributes object. .It Xo .Ft int -.Fn pthread_mutexattr_getprioceiling "pthread_mutexattr_t *attr" "int *ceiling" +.Fn pthread_mutexattr_getprioceiling "const pthread_mutexattr_t *restrict attr" "int *restrict ceiling" .Xc Obtain priority ceiling attribute of mutex attribute object. .It Xo .Ft int -.Fn pthread_mutexattr_getprotocol "pthread_mutexattr_t *attr" "int *protocol" +.Fn pthread_mutexattr_getprotocol "const pthread_mutexattr_t *restrict attr" "int *restrict protocol" .Xc Obtain protocol attribute of mutex attribute object. .It Xo .Ft int -.Fn pthread_mutexattr_gettype "pthread_mutexattr_t *attr" "int *type" +.Fn pthread_mutexattr_gettype "const pthread_mutexattr_t *restrict attr" "int *restrict type" .Xc Obtain the mutex type attribute in the specified mutex attributes object. .It Xo .Ft int .Fn pthread_mutexattr_init "pthread_mutexattr_t *attr" .Xc Initialize a mutex attributes object with default values. .It Xo .Ft int .Fn pthread_mutexattr_setprioceiling "pthread_mutexattr_t *attr" "int ceiling" .Xc Set priority ceiling attribute of mutex attribute object. .It Xo .Ft int .Fn pthread_mutexattr_setprotocol "pthread_mutexattr_t *attr" "int protocol" .Xc Set protocol attribute of mutex attribute object. .It Xo .Ft int .Fn pthread_mutexattr_settype "pthread_mutexattr_t *attr" "int type" .Xc Set the mutex type attribute that is used when a mutex is created. .It Xo .Ft int .Fn pthread_mutex_destroy "pthread_mutex_t *mutex" .Xc Destroy a mutex. .It Xo .Ft int .Fo pthread_mutex_init .Fa "pthread_mutex_t *mutex" "const pthread_mutexattr_t *attr" .Fc .Xc Initialize a mutex with specified attributes. .It Xo .Ft int .Fn pthread_mutex_lock "pthread_mutex_t *mutex" .Xc Lock a mutex and block until it becomes available. .It Xo .Ft int .Fo pthread_mutex_timedlock .Fa "pthread_mutex_t *mutex" "const struct timespec *abstime" .Fc .Xc Lock a mutex and block until it becomes available or until the timeout expires. .It Xo .Ft int .Fn pthread_mutex_trylock "pthread_mutex_t *mutex" .Xc Try to lock a mutex, but do not block if the mutex is locked by another thread, including the current thread. .It Xo .Ft int .Fn pthread_mutex_unlock "pthread_mutex_t *mutex" .Xc Unlock a mutex. .El .Ss Condition Variable Routines .Bl -tag -width indent .It Xo .Ft int .Fn pthread_condattr_destroy "pthread_condattr_t *attr" .Xc Destroy a condition variable attributes object. .It Xo .Ft int .Fn pthread_condattr_init "pthread_condattr_t *attr" .Xc Initialize a condition variable attributes object with default values. .It Xo .Ft int .Fn pthread_cond_broadcast "pthread_cond_t *cond" .Xc Unblock all threads currently blocked on the specified condition variable. .It Xo .Ft int .Fn pthread_cond_destroy "pthread_cond_t *cond" .Xc Destroy a condition variable. .It Xo .Ft int .Fn pthread_cond_init "pthread_cond_t *cond" "const pthread_condattr_t *attr" .Xc Initialize a condition variable with specified attributes. .It Xo .Ft int .Fn pthread_cond_signal "pthread_cond_t *cond" .Xc Unblock at least one of the threads blocked on the specified condition variable. .It Xo .Ft int .Fo pthread_cond_timedwait .Fa "pthread_cond_t *cond" "pthread_mutex_t *mutex" .Fa "const struct timespec *abstime" .Fc .Xc Unlock the specified mutex, wait no longer than the specified time for a condition, and then relock the mutex. .It Xo .Ft int .Fn pthread_cond_wait "pthread_cond_t *" "pthread_mutex_t *mutex" .Xc Unlock the specified mutex, wait for a condition, and relock the mutex. .El .Ss Read/Write Lock Routines .Bl -tag -width indent .It Xo .Ft int .Fn pthread_rwlock_destroy "pthread_rwlock_t *lock" .Xc Destroy a read/write lock object. .It Xo .Ft int .Fo pthread_rwlock_init .Fa "pthread_rwlock_t *lock" "const pthread_rwlockattr_t *attr" .Fc .Xc Initialize a read/write lock object. .It Xo .Ft int .Fn pthread_rwlock_rdlock "pthread_rwlock_t *lock" .Xc Lock a read/write lock for reading, blocking until the lock can be acquired. .It Xo .Ft int .Fn pthread_rwlock_tryrdlock "pthread_rwlock_t *lock" .Xc Attempt to lock a read/write lock for reading, without blocking if the lock is unavailable. .It Xo .Ft int .Fn pthread_rwlock_trywrlock "pthread_rwlock_t *lock" .Xc Attempt to lock a read/write lock for writing, without blocking if the lock is unavailable. .It Xo .Ft int .Fn pthread_rwlock_unlock "pthread_rwlock_t *lock" .Xc Unlock a read/write lock. .It Xo .Ft int .Fn pthread_rwlock_wrlock "pthread_rwlock_t *lock" .Xc Lock a read/write lock for writing, blocking until the lock can be acquired. .It Xo .Ft int .Fn pthread_rwlockattr_destroy "pthread_rwlockattr_t *attr" .Xc Destroy a read/write lock attribute object. .It Xo .Ft int .Fo pthread_rwlockattr_getpshared .Fa "const pthread_rwlockattr_t *attr" "int *pshared" .Fc .Xc Retrieve the process shared setting for the read/write lock attribute object. .It Xo .Ft int .Fn pthread_rwlockattr_init "pthread_rwlockattr_t *attr" .Xc Initialize a read/write lock attribute object. .It Xo .Ft int .Fn pthread_rwlockattr_setpshared "pthread_rwlockattr_t *attr" "int pshared" .Xc Set the process shared setting for the read/write lock attribute object. .El .Ss Per-Thread Context Routines .Bl -tag -width indent .It Xo .Ft int .Fn pthread_key_create "pthread_key_t *key" "void \*[lp]*routine\*[rp]\*[lp]void *\*[rp]" .Xc Create a thread-specific data key. .It Xo .Ft int .Fn pthread_key_delete "pthread_key_t key" .Xc Delete a thread-specific data key. .It Xo .Ft "void *" .Fn pthread_getspecific "pthread_key_t key" .Xc Get the thread-specific value for the specified key. .It Xo .Ft int .Fn pthread_setspecific "pthread_key_t key" "const void *value_ptr" .Xc Set the thread-specific value for the specified key. .El .Ss Cleanup Routines .Bl -tag -width indent .It Xo .Ft int .Fo pthread_atfork .Fa "void \*[lp]*prepare\*[rp]\*[lp]void\*[rp]" .Fa "void \*[lp]*parent\*[rp]\*[lp]void\*[rp]" .Fa "void \*[lp]*child\*[rp]\*[lp]void\*[rp]" .Fc .Xc Register fork handlers. .It Xo .Ft void .Fn pthread_cleanup_pop "int execute" .Xc Remove the routine at the top of the calling thread's cancellation cleanup stack and optionally invoke it. .It Xo .Ft void .Fn pthread_cleanup_push "void \*[lp]*routine\*[rp]\*[lp]void *\*[rp]" "void *routine_arg" .Xc Push the specified cancellation cleanup handler onto the calling thread's cancellation stack. .El .Sh IMPLEMENTATION NOTES The current .Fx POSIX thread implementation is built into the .Lb libthr library. It contains thread-safe versions of .Lb libc functions and the thread functions. Threaded applications are linked with this library. .Sh SEE ALSO .Xr libthr 3 , .Xr pthread_affinity_np 3 , .Xr pthread_atfork 3 , .Xr pthread_attr 3 , .Xr pthread_cancel 3 , .Xr pthread_cleanup_pop 3 , .Xr pthread_cleanup_push 3 , .Xr pthread_cond_broadcast 3 , .Xr pthread_cond_destroy 3 , .Xr pthread_cond_init 3 , .Xr pthread_cond_signal 3 , .Xr pthread_cond_timedwait 3 , .Xr pthread_cond_wait 3 , .Xr pthread_condattr_destroy 3 , .Xr pthread_condattr_init 3 , .Xr pthread_create 3 , .Xr pthread_detach 3 , .Xr pthread_equal 3 , .Xr pthread_exit 3 , .Xr pthread_getspecific 3 , .Xr pthread_join 3 , .Xr pthread_key_delete 3 , .Xr pthread_kill 3 , .Xr pthread_mutex_destroy 3 , .Xr pthread_mutex_init 3 , .Xr pthread_mutex_lock 3 , .Xr pthread_mutex_trylock 3 , .Xr pthread_mutex_unlock 3 , .Xr pthread_mutexattr_destroy 3 , .Xr pthread_mutexattr_getprioceiling 3 , .Xr pthread_mutexattr_getprotocol 3 , .Xr pthread_mutexattr_gettype 3 , .Xr pthread_mutexattr_init 3 , .Xr pthread_mutexattr_setprioceiling 3 , .Xr pthread_mutexattr_setprotocol 3 , .Xr pthread_mutexattr_settype 3 , .Xr pthread_once 3 , .Xr pthread_rwlock_destroy 3 , .Xr pthread_rwlock_init 3 , .Xr pthread_rwlock_rdlock 3 , .Xr pthread_rwlock_unlock 3 , .Xr pthread_rwlock_wrlock 3 , .Xr pthread_rwlockattr_destroy 3 , .Xr pthread_rwlockattr_getpshared 3 , .Xr pthread_rwlockattr_init 3 , .Xr pthread_rwlockattr_setpshared 3 , .Xr pthread_self 3 , .Xr pthread_setcancelstate 3 , .Xr pthread_setcanceltype 3 , .Xr pthread_setspecific 3 , .Xr pthread_testcancel 3 .Sh STANDARDS The functions with the .Nm pthread_ prefix and not .Nm _np suffix or .Nm pthread_rwlock prefix conform to .St -p1003.1-96 . .Pp The functions with the .Nm pthread_ prefix and .Nm _np suffix are non-portable extensions to POSIX threads. .Pp The functions with the .Nm pthread_rwlock prefix are extensions created by The Open Group as part of the .St -susv2 . Index: head/share/man/man3/pthread_attr.3 =================================================================== --- head/share/man/man3/pthread_attr.3 (revision 337991) +++ head/share/man/man3/pthread_attr.3 (revision 337992) @@ -1,238 +1,238 @@ .\" 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$ -.Dd January 8, 2010 +.Dd August 17, 2018 .Dt PTHREAD_ATTR 3 .Os .Sh NAME .Nm pthread_attr_init , .Nm pthread_attr_destroy , .Nm pthread_attr_setstack , .Nm pthread_attr_getstack , .Nm pthread_attr_setstacksize , .Nm pthread_attr_getstacksize , .Nm pthread_attr_setguardsize , .Nm pthread_attr_getguardsize , .Nm pthread_attr_setstackaddr , .Nm pthread_attr_getstackaddr , .Nm pthread_attr_setdetachstate , .Nm pthread_attr_getdetachstate , .Nm pthread_attr_setinheritsched , .Nm pthread_attr_getinheritsched , .Nm pthread_attr_setschedparam , .Nm pthread_attr_getschedparam , .Nm pthread_attr_setschedpolicy , .Nm pthread_attr_getschedpolicy , .Nm pthread_attr_setscope , .Nm pthread_attr_getscope .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" .Ft int .Fn pthread_attr_setstack "pthread_attr_t *attr" " void *stackaddr" "size_t stacksize" .Ft int .Fn pthread_attr_getstack "const pthread_attr_t * restrict attr" "void ** restrict stackaddr" "size_t * restrict stacksize" .Ft int .Fn pthread_attr_setstacksize "pthread_attr_t *attr" "size_t stacksize" .Ft int -.Fn pthread_attr_getstacksize "const pthread_attr_t *attr" "size_t *stacksize" +.Fn pthread_attr_getstacksize "const pthread_attr_t *restrict attr" "size_t *restrict stacksize" .Ft int .Fn pthread_attr_setguardsize "pthread_attr_t *attr" "size_t guardsize" .Ft int -.Fn pthread_attr_getguardsize "const pthread_attr_t *attr" "size_t *guardsize" +.Fn pthread_attr_getguardsize "const pthread_attr_t * restrict attr" "size_t * restrict guardsize" .Ft int .Fn pthread_attr_setstackaddr "pthread_attr_t *attr" "void *stackaddr" .Ft int .Fn pthread_attr_getstackaddr "const pthread_attr_t *attr" "void **stackaddr" .Ft int .Fn pthread_attr_setdetachstate "pthread_attr_t *attr" "int detachstate" .Ft int .Fn pthread_attr_getdetachstate "const pthread_attr_t *attr" "int *detachstate" .Ft int .Fn pthread_attr_setinheritsched "pthread_attr_t *attr" "int inheritsched" .Ft int -.Fn pthread_attr_getinheritsched "const pthread_attr_t *attr" "int *inheritsched" +.Fn pthread_attr_getinheritsched "const pthread_attr_t *restrict attr" "int *restrct inheritsched" .Ft int .Fn pthread_attr_setschedparam "pthread_attr_t *attr" "const struct sched_param *param" .Ft int .Fn pthread_attr_getschedparam "const pthread_attr_t *attr" "struct sched_param *param" .Ft int .Fn pthread_attr_setschedpolicy "pthread_attr_t *attr" "int policy" .Ft int -.Fn pthread_attr_getschedpolicy "const pthread_attr_t *attr" "int *policy" +.Fn pthread_attr_getschedpolicy "const pthread_attr_t *restrict attr" "int *restrict policy" .Ft int .Fn pthread_attr_setscope "pthread_attr_t *attr" "int contentionscope" .Ft int -.Fn pthread_attr_getscope "const pthread_attr_t *attr" "int *contentionscope" +.Fn pthread_attr_getscope "const pthread_attr_t *restrict attr" "int *restrict contentionscope" .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 calls. .Pp The .Fn pthread_attr_init function initializes .Fa attr with all the default thread attributes. .Pp The .Fn pthread_attr_destroy function destroys .Fa attr . .Pp The .Fn pthread_attr_set* functions set the attribute that corresponds to each function name. .Pp The .Fn pthread_attr_get* functions copy the value of the attribute that corresponds to each function name to the location pointed to by the second function 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_attr_init function will fail if: .Bl -tag -width Er .It Bq Er ENOMEM Out of memory. .El .Pp The .Fn pthread_attr_destroy function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Pp The .Fn pthread_attr_setstacksize and .Fn pthread_attr_setstack functions will fail if: .Bl -tag -width Er .It Bq Er EINVAL .Fa stacksize is less than .Dv PTHREAD_STACK_MIN . .El .Pp The .Fn pthread_attr_setdetachstate function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa detachstate . .El .Pp The .Fn pthread_attr_setinheritsched function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Pp The .Fn pthread_attr_setschedparam function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .It Bq Er ENOTSUP Invalid value for .Fa param . .El .Pp The .Fn pthread_attr_setschedpolicy function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .It Bq Er ENOTSUP Invalid or unsupported value for .Fa policy . .El .Pp The .Fn pthread_attr_setscope function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .It Bq Er ENOTSUP Invalid or unsupported value for .Fa contentionscope . .El .Sh SEE ALSO .Xr pthread_attr_affinity_np 3 , .Xr pthread_attr_get_np 3 , .Xr pthread_create 3 .Sh STANDARDS .Fn pthread_attr_init , .Fn pthread_attr_destroy , .Fn pthread_attr_setstacksize , .Fn pthread_attr_getstacksize , .Fn pthread_attr_setstackaddr , .Fn pthread_attr_getstackaddr , .Fn pthread_attr_setdetachstate , and .Fn pthread_attr_getdetachstate functions conform to .St -p1003.1-96 .Pp The .Fn pthread_attr_setinheritsched , .Fn pthread_attr_getinheritsched , .Fn pthread_attr_setschedparam , .Fn pthread_attr_getschedparam , .Fn pthread_attr_setschedpolicy , .Fn pthread_attr_getschedpolicy , .Fn pthread_attr_setscope , and .Fn pthread_attr_getscope functions conform to .St -susv2 Index: head/share/man/man3/pthread_barrier_destroy.3 =================================================================== --- head/share/man/man3/pthread_barrier_destroy.3 (revision 337991) +++ head/share/man/man3/pthread_barrier_destroy.3 (revision 337992) @@ -1,156 +1,156 @@ .\" Copyright (c) 2004 Michael Telahun Makonnen .\" 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$ .\" -.Dd February 19, 2004 +.Dd August 17, 2018 .Dt PTHREAD_BARRIER 3 .Os .Sh NAME .Nm pthread_barrier_destroy , pthread_barrier_init , pthread_barrier_wait .Nd "destroy, initialize or wait on a barrier object" .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int .Fn pthread_barrier_destroy "pthread_barrier_t *barrier" .Ft int -.Fn pthread_barrier_init "pthread_barrier_t *barrier" "const pthread_barrierattr_t *attr" "unsigned count" +.Fn pthread_barrier_init "pthread_barrier_t *restrict barrier" "const pthread_barrierattr_t *attr" "unsigned count" .Ft int .Fn pthread_barrier_wait "pthread_barrier_t *barrier" .Sh DESCRIPTION The .Fn pthread_barrier_init function will initialize .Fa barrier with attributes specified in .Fa attr , or if it is .Dv NULL , with default attributes. The number of threads that must call .Fn pthread_barrier_wait before any of the waiting threads can be released is specified by .Fa count . The .Fn pthread_barrier_destroy function will destroy .Fa barrier and release any resources that may have been allocated on its behalf. .Pp The .Fn pthread_barrier_wait function will synchronize calling threads at .Fa barrier . The threads will be blocked from making further progress until a sufficient number of threads calls this function. The number of threads that must call it before any of them will be released is determined by the .Fa count argument to .Fn pthread_barrier_init . Once the threads have been released the barrier will be reset. .Sh IMPLEMENTATION NOTES In .Lb libthr the .Dv PTHREAD_BARRIER_SERIAL_THREAD return value will always be returned by the last thread to reach the barrier. .Sh RETURN VALUES If successful, both .Fn pthread_barrier_destroy and .Fn pthread_barrier_init will return zero. Otherwise, an error number will be returned to indicate the error. If the call to .Fn pthread_barrier_wait is successful, all but one of the threads will return zero. That one thread will return .Dv PTHREAD_BARRIER_SERIAL_THREAD . Otherwise, an error number will be returned to indicate the error. .Pp None of these functions will return .Er EINTR . .Sh ERRORS The .Fn pthread_barrier_destroy function will fail if: .Bl -tag -width Er .It Bq Er EBUSY An attempt was made to destroy .Fa barrier while it was in use. .El .Pp The .Fn pthread_barrier_destroy and .Fn pthread_barrier_wait functions may fail if: .Bl -tag -width Er .It Bq Er EINVAL The value specified by .Fa barrier is invalid. .El .Pp The .Fn pthread_barrier_init function will fail if: .Bl -tag -width Er .It Bq Er EAGAIN The system lacks resources, other than memory, to initialize .Fa barrier . .It Bq Er EINVAL The .Fa count argument is less than 1. .It Bq Er ENOMEM Insufficient memory to initialize .Fa barrier . .El .Sh SEE ALSO .Xr pthread_barrierattr 3 .Sh HISTORY The .Fn pthread_barrier_destroy , .Fn pthread_barrier_init and .Fn pthread_barrier_wait functions first appeared in .Lb libkse in .Fx 5.2 , and in .Lb libthr in .Fx 5.3 . Index: head/share/man/man3/pthread_barrierattr.3 =================================================================== --- head/share/man/man3/pthread_barrierattr.3 (revision 337991) +++ head/share/man/man3/pthread_barrierattr.3 (revision 337992) @@ -1,135 +1,135 @@ .\" Copyright (c) 2004 Michael Telahun Makonnen .\" 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$ .\" -.Dd May 31, 2016 +.Dd August 17, 2018 .Dt PTHREAD_BARRIERATTR 3 .Os .Sh NAME .Nm pthread_barrierattr_destroy , pthread_barrierattr_getpshared , .Nm pthread_barrierattr_init , pthread_barrierattr_setpshared .Nd "manipulate a barrier attribute object" .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int .Fn pthread_barrierattr_destroy "pthread_barrierattr_t *attr" .Ft int -.Fn pthread_barrierattr_getpshared "const pthread_barrierattr_t *attr" "int *pshared" +.Fn pthread_barrierattr_getpshared "const pthread_barrierattr_t *restrict attr" "int *restrict pshared" .Ft int .Fn pthread_barrierattr_init "pthread_barrierattr_t *attr" .Ft int .Fn pthread_barrierattr_setpshared "pthread_barrierattr_t *attr" "int pshared" .Sh DESCRIPTION The .Fn pthread_barrierattr_init function will initialize .Fa attr with default attributes. The .Fn pthread_barrierattr_destroy function will destroy .Fa attr and release any resources that may have been allocated on its behalf. .Pp The .Fn pthread_barrierattr_getpshared function will put the value of the process-shared attribute from .Fa attr into the memory area pointed to by .Fa pshared . The .Fn pthread_barrierattr_setpshared function will set the process-shared attribute of .Fa attr to the value specified in .Fa pshared . The argument .Fa pshared may have one of the following values: .Bl -tag -width ".Dv PTHREAD_PROCESS_PRIVATE" .It Dv PTHREAD_PROCESS_PRIVATE The barrier object it is attached to may only be accessed by threads in the same process as the one that created the object. .It Dv PTHREAD_PROCESS_SHARED The barrier object it is attached to may be accessed by threads in processes other than the one that created the object. .El .Sh RETURN VALUES If successful, all these functions will return zero. Otherwise, an error number will be returned to indicate the error. .Pp None of these functions will return .Er EINTR . .Sh ERRORS The .Fn pthread_barrierattr_destroy , .Fn pthread_barrierattr_getpshared and .Fn pthread_barrierattr_setpshared functions may fail if: .Bl -tag -width Er .It Bq Er EINVAL The value specified by .Fa attr is invalid. .El .Pp The .Fn pthread_barrierattr_init function will fail if: .Bl -tag -width Er .It Bq Er ENOMEM Insufficient memory to initialize the barrier attribute object .Fa attr . .El .Pp The .Fn pthread_barrierattr_setpshared function will fail if: .Bl -tag -width Er .It Bq Er EINVAL The value specified in .Fa pshared is not one of the allowed values. .El .Sh SEE ALSO .Xr pthread_barrier_destroy 3 , .Xr pthread_barrier_init 3 , .Xr pthread_barrier_wait 3 .Sh HISTORY The .Fn pthread_barrierattr_* functions first appeared in .Lb libkse in .Fx 5.2 , and in .Lb libthr in .Fx 5.3 . Support for process-shared barriers appeared in .Fx 11.0 . Index: head/share/man/man3/pthread_cond_init.3 =================================================================== --- head/share/man/man3/pthread_cond_init.3 (revision 337991) +++ head/share/man/man3/pthread_cond_init.3 (revision 337992) @@ -1,83 +1,83 @@ .\" 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$ .\" -.Dd November 4, 2006 +.Dd August 17, 2018 .Dt PTHREAD_COND_INIT 3 .Os .Sh NAME .Nm pthread_cond_init .Nd create a condition variable .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_cond_init "pthread_cond_t *cond" "const pthread_condattr_t *attr" +.Fn pthread_cond_init "pthread_cond_t *restrict cond" "const pthread_condattr_t *restrict attr" .Sh DESCRIPTION The .Fn pthread_cond_init function creates a new condition variable, with attributes specified with .Fa attr . If .Fa attr is NULL the default attributes are used. .Sh RETURN VALUES If successful, the .Fn pthread_cond_init function will return zero and put the new condition variable id into .Fa cond , otherwise an error number will be returned to indicate the error. .Sh ERRORS The .Fn pthread_cond_init function will fail if: .Bl -tag -width Er .It Bq Er EINVAL The value specified by .Fa attr is invalid. .It Bq Er ENOMEM The process cannot allocate enough memory to create another condition variable. .It Bq Er EAGAIN The system temporarily lacks the resources to create another condition variable. .El .Sh SEE ALSO .Xr pthread_cond_broadcast 3 , .Xr pthread_cond_destroy 3 , .Xr pthread_cond_signal 3 , .Xr pthread_cond_timedwait 3 , .Xr pthread_cond_wait 3 , .Xr pthread_condattr 3 .Sh STANDARDS The .Fn pthread_cond_init function conforms to .St -p1003.1-96 . Index: head/share/man/man3/pthread_cond_wait.3 =================================================================== --- head/share/man/man3/pthread_cond_wait.3 (revision 337991) +++ head/share/man/man3/pthread_cond_wait.3 (revision 337992) @@ -1,101 +1,101 @@ .\" 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$ .\" -.Dd April 29, 2016 +.Dd August 17, 2018 .Dt PTHREAD_COND_WAIT 3 .Os .Sh NAME .Nm pthread_cond_wait .Nd wait on a condition variable .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_cond_wait "pthread_cond_t *cond" "pthread_mutex_t *mutex" +.Fn pthread_cond_wait "pthread_cond_t *restrict cond" "pthread_mutex_t *restrict mutex" .Sh DESCRIPTION The .Fn pthread_cond_wait function atomically blocks the current thread waiting on the condition variable specified by .Fa cond , and releases the mutex specified by .Fa mutex . The waiting thread unblocks only after another thread calls .Xr pthread_cond_signal 3 , or .Xr pthread_cond_broadcast 3 with the same condition variable, and the current thread reacquires the lock on .Fa mutex . .Sh RETURN VALUES If successful, the .Fn pthread_cond_wait function will return zero. Otherwise an error number will be returned to indicate the error. .Sh ERRORS The .Fn pthread_cond_wait function will 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 specified .Fa mutex was not locked by the calling thread. .It Bq Er EOWNERDEAD The argument .Fa mutex points to a robust mutex and the previous owning thread terminated while holding the mutex lock. The lock was granted to the caller and it is up to the new owner to make the state consistent. .It Bq Er ENOTRECOVERABLE The state protected by the .Fa mutex is not recoverable. .El .Sh SEE ALSO .Xr pthread_cond_broadcast 3 , .Xr pthread_cond_destroy 3 , .Xr pthread_cond_init 3 , .Xr pthread_cond_signal 3 , .Xr pthread_cond_timedwait 3 , .Xr pthread_mutex_consistent 3 .Sh STANDARDS The .Fn pthread_cond_wait function conforms to .St -p1003.1-96 . Index: head/share/man/man3/pthread_create.3 =================================================================== --- head/share/man/man3/pthread_create.3 (revision 337991) +++ head/share/man/man3/pthread_create.3 (revision 337992) @@ -1,149 +1,149 @@ .\" 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$ .\" -.Dd June 2, 2016 +.Dd August 17, 2018 .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 *thread" "const pthread_attr_t *attr" "void *(*start_routine)(void *)" "void *arg" +.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. If the attributes specified by .Fa attr are modified later, the thread's attributes are not affected. Upon successful completion .Fn pthread_create will store the ID of the created thread in the location specified by .Fa thread . .Pp The thread is created executing .Fa start_routine with .Fa arg as its sole argument. 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 The .Fn pthread_create function can return any of the following errors: .Bl -tag -width Er .It Bq Er ENOMEM The system lacked the necessary resources to create another thread. .It Bq Er EAGAIN The system-imposed limit on the total number of threads in a process .Dv [PTHREAD_THREADS_MAX] would be exceeded. .It Bq Er EAGAIN The .Dv RACCT_NTHR limit would be exceeded; see .Xr racct 2 . .It Bq Er EPERM The caller does not have permission to set the scheduling parameters or scheduling policy. .It Bq Er EINVAL A value specified by .Fa attr is invalid. .It Bq Er EDEADLK The CPU set specified by .Fa attr would prevent the thread from running on any CPU. .It Bq Er EFAULT The stack base specified by .Fa attr is invalid, or the kernel was unable to put required initial data on the stack. .El .Sh SEE ALSO .Xr cpuset_setaffinity 2 , .Xr fork 2 , .Xr racct 2 , .Xr thr_new 2 , .Xr pthread_attr 3 , .Xr pthread_cancel 3 , .Xr pthread_cleanup_pop 3 , .Xr pthread_cleanup_push 3 , .Xr pthread_exit 3 , .Xr pthread_join 3 .Sh STANDARDS The .Fn pthread_create function conforms to .St -p1003.1-96 . Index: head/share/man/man3/pthread_mutex_init.3 =================================================================== --- head/share/man/man3/pthread_mutex_init.3 (revision 337991) +++ head/share/man/man3/pthread_mutex_init.3 (revision 337992) @@ -1,78 +1,78 @@ .\" 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$ .\" -.Dd November 4, 2006 +.Dd August 17, 2018 .Dt PTHREAD_MUTEX_INIT 3 .Os .Sh NAME .Nm pthread_mutex_init .Nd create a mutex .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_mutex_init "pthread_mutex_t *mutex" "const pthread_mutexattr_t *attr" +.Fn pthread_mutex_init "pthread_mutex_t *restrict mutex" "const pthread_mutexattr_t *restrict attr" .Sh DESCRIPTION The .Fn pthread_mutex_init function creates a new mutex, with attributes specified with .Fa attr . If .Fa attr is NULL the default attributes are used. .Sh RETURN VALUES If successful, .Fn pthread_mutex_init will return zero and put the new mutex id into .Fa mutex , otherwise an error number will be returned to indicate the error. .Sh ERRORS The .Fn pthread_mutex_init function will fail if: .Bl -tag -width Er .It Bq Er EINVAL The value specified by .Fa attr is invalid. .It Bq Er ENOMEM The process cannot allocate enough memory to create another mutex. .El .Sh SEE ALSO .Xr pthread_mutex_destroy 3 , .Xr pthread_mutex_lock 3 , .Xr pthread_mutex_trylock 3 , .Xr pthread_mutex_unlock 3 , .Xr pthread_mutexattr 3 .Sh STANDARDS The .Fn pthread_mutex_init function conforms to .St -p1003.1-96 . Index: head/share/man/man3/pthread_mutex_timedlock.3 =================================================================== --- head/share/man/man3/pthread_mutex_timedlock.3 (revision 337991) +++ head/share/man/man3/pthread_mutex_timedlock.3 (revision 337992) @@ -1,115 +1,115 @@ .\" Copyright (c) 2003 Michael Telahun Makonnen .\" 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$ .\" -.Dd April 29, 2016 +.Dd August 17, 2018 .Dt PTHREAD_MUTEX_TIMEDLOCK 3 .Os .Sh NAME .Nm pthread_mutex_timedlock .Nd lock a mutex without blocking indefinitely .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .In time.h .Ft int -.Fn pthread_mutex_timedlock "pthread_mutex_t *mutex" "const struct timespec *abs_timeout" +.Fn pthread_mutex_timedlock "pthread_mutex_t *restrict mutex" "const struct timespec *restrict abs_timeout" .Sh DESCRIPTION The .Fn pthread_mutex_timedlock function will lock .Fa mutex . If it is already locked the calling thread will block until the mutex becomes available or the timeout, specified by abs_timeout, expires. The time of the timeout is an absolute time and is not relative to the current time. .Sh RETURN VALUES If successful, .Fn pthread_mutex_timedlock will return zero, otherwise an error number will be returned to indicate the error. .Sh ERRORS The .Fn pthread_mutex_timedlock function will fail if: .Bl -tag -width Er .It Bq "Er ENOTRECOVERABLE" The .Fa mutex was created with the protocol attribute having the value PTHREAD_PRIO_PROTECT and the calling thread's priority is higher than the mutex's current priority ceiling. .It Bq Er EINVAL The process or thread would have blocked, and .Fa abs_timeout specified a nanosecond value less than zero or greater than or equal to 1 billion. .It Bq Er EINVAL The .Fa mutex parameter is invalid. .It Bq Er ETIMEDOUT The .Fa mutex could not be locked before the timeout expired. .It Bq Er EAGAIN The .Fa mutex could not be acquired because the maximum number of recursive locks for the .Fa mutex has been exceeded. .It Bq Er EDEADLK The current thread already owns the .Fa mutex . .It Bq Er EOWNERDEAD The argument .Fa mutex points to a robust mutex and the previous owning thread terminated while holding the mutex lock. The lock was granted to the caller and it is up to the new owner to make the state consistent. .It Bq Er ENOTRECOVERABLE The state protected by the .Fa mutex is not recoverable. .El .Sh SEE ALSO .Xr pthread_mutex_consistent 3 , .Xr pthread_mutex_destroy 3 , .Xr pthread_mutex_init 3 , .Xr pthread_mutex_lock 3 , .Xr pthread_mutex_trylock 3 , .Xr pthread_mutex_unlock 3 .Sh STANDARDS The .Fn pthread_mutex_timedlock function is expected to conform to .St -p1003.1-96 . Index: head/share/man/man3/pthread_mutexattr.3 =================================================================== --- head/share/man/man3/pthread_mutexattr.3 (revision 337991) +++ head/share/man/man3/pthread_mutexattr.3 (revision 337992) @@ -1,219 +1,219 @@ .\" 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$ -.Dd April 29, 2016 +.Dd August 17, 2018 .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_setrobust , .Nm pthread_mutexattr_getrobust , .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" +.Fn pthread_mutexattr_getprioceiling "const 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" +.Fn pthread_mutexattr_getprotocol "const pthread_mutexattr_t *restrict attr" "int *restrict protocol" .Ft int .Fn pthread_mutexattr_setrobust "pthread_mutexattr_t *attr" "int robust" .Ft int .Fn pthread_mutexattr_getrobust "pthread_mutexattr_t *attr" "int *robust" .Ft int .Fn pthread_mutexattr_settype "pthread_mutexattr_t *attr" "int type" .Ft int -.Fn pthread_mutexattr_gettype "pthread_mutexattr_t *attr" "int *type" +.Fn pthread_mutexattr_gettype "const pthread_mutexattr_t *restrict attr" "int *restrict type" .Sh DESCRIPTION Mutex attributes are used to specify parameters to .Fn pthread_mutex_init . One attribute object can be used in multiple calls to .Fn pthread_mutex_init , 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_set* functions set the attribute that corresponds to each function name. .Pp The .Fn pthread_mutexattr_get* functions copy the value of the attribute that corresponds to each function name to the location pointed to by the second function 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 will fail if: .Bl -tag -width Er .It Bq Er ENOMEM Out of memory. .El .Pp The .Fn pthread_mutexattr_destroy function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Pp The .Fn pthread_mutexattr_setprioceiling function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr , or invalid value for .Fa prioceiling . .El .Pp The .Fn pthread_mutexattr_getprioceiling function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Pp The .Fn pthread_mutexattr_setprotocol function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr , or invalid value for .Fa protocol . .El .Pp The .Fn pthread_mutexattr_getprotocol function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Pp The .Fn pthread_mutexattr_settype function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr , or invalid value for .Fa type . .El .Pp The .Fn pthread_mutexattr_gettype function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Pp The .Fn pthread_mutexattr_setrobust function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr , or invalid value for .Fa robust . .El .Pp The .Fn pthread_mutexattr_getrobust function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa attr . .El .Sh SEE ALSO .Xr pthread_mutex_init 3 .Sh STANDARDS The .Fn pthread_mutexattr_init and .Fn pthread_mutexattr_destroy functions conform to .St -p1003.1-96 .Pp The .Fn pthread_mutexattr_setprioceiling , .Fn pthread_mutexattr_getprioceiling , .Fn pthread_mutexattr_setprotocol , .Fn pthread_mutexattr_getprotocol , .Fn pthread_mutexattr_settype , and .Fn pthread_mutexattr_gettype functions conform to .St -susv2 . The .Fn pthread_mutexattr_setrobust and .Fn pthread_mutexattr_getrobust functions conform to .St -susv4 . Index: head/share/man/man3/pthread_rwlock_init.3 =================================================================== --- head/share/man/man3/pthread_rwlock_init.3 (revision 337991) +++ head/share/man/man3/pthread_rwlock_init.3 (revision 337992) @@ -1,100 +1,100 @@ .\" 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$ .\" -.Dd May 31, 2016 +.Dd August 17, 2018 .Dt PTHREAD_RWLOCK_INIT 3 .Os .Sh NAME .Nm pthread_rwlock_init .Nd initialize a read/write lock .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_rwlock_init "pthread_rwlock_t *lock" "const pthread_rwlockattr_t *attr" +.Fn pthread_rwlock_init "pthread_rwlock_t *restrict lock" "const pthread_rwlockattr_t *restrict attr" .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 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. .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. .Sh ERRORS The .Fn pthread_rwlock_init function will fail if: .Bl -tag -width Er .It Bq Er EAGAIN The system lacked the necessary resources (other than memory) to initialize the lock. .It Bq Er ENOMEM Insufficient memory exists to initialize the lock. .It Bq Er EPERM The caller does not have sufficient privilege to perform the operation. .El .Pp The .Fn pthread_rwlock_init function may fail if: .Bl -tag -width Er .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. .El .Sh SEE ALSO .Xr pthread_rwlock_destroy 3 , .Xr pthread_rwlockattr_init 3 , .Xr pthread_rwlockattr_setpshared 3 .Sh STANDARDS The .Fn pthread_rwlock_init function is expected to conform to .St -susv2 . .Sh HISTORY The .Fn pthread_rwlock_init function first appeared in .Fx 3.0 . Index: head/share/man/man3/pthread_rwlock_timedrdlock.3 =================================================================== --- head/share/man/man3/pthread_rwlock_timedrdlock.3 (revision 337991) +++ head/share/man/man3/pthread_rwlock_timedrdlock.3 (revision 337992) @@ -1,118 +1,118 @@ .\" Copyright (c) 2004 Michael Telahun Makonnen .\" 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$ .\" -.Dd January 16, 2004 +.Dd August 17, 2018 .Dt PTHREAD_RWLOCK_TIMEDRDLOCK 3 .Os .Sh NAME .Nm pthread_rwlock_timedrdlock .Nd "acquire a read-write lock for reading or give up after a specified period" .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_rwlock_timedrdlock "pthread_rwlock_t *rwlock" "const struct timespec *abs_timeout" +.Fn pthread_rwlock_timedrdlock "pthread_rwlock_t *restrict rwlock" "const struct timespec *restrict abs_timeout" .Sh DESCRIPTION This function acquires a read lock on the read-write lock .Fa rwlock . However, if the lock cannot be acquired without waiting for another thread to unlock the lock, this wait shall be terminated when .Fa abs_timeout expires. .Pp A thread may hold multiple concurrent read locks. The .Xr pthread_rwlock_unlock 3 function must be called once for each lock acquired. .Pp If the thread should be interrupted by a signal, the .Fn pthread_rwlock_timedrdlock function will be automatically restarted after the thread returns from the signal handler. .Pp The calling thread may deadlock if at the time the call is made it holds a write lock on .Fa rwlock . The results are undefined if this function is called with an uninitialized read-write lock. .Sh IMPLEMENTATION NOTES To prevent writer starvation, writers are favored over readers. .Sh RETURN VALUES If successful, the .Fn pthread_rwlock_timedrdlock function will return zero. Otherwise, an error number will be returned to indicate the error. .Pp This function shall not return an error code of .Er EINTR . .Sh ERRORS The .Fn pthread_rwlock_timedrdlock function will fail if: .Bl -tag -width Er .It Bq Er ETIMEDOUT The lock could not be acquired before the specified timeout expired. .El .Pp The .Fn pthread_rwlock_timedrdlock function may fail if: .Bl -tag -width Er .It Bq Er EAGAIN The read lock could not be acquired because the maximum number of read locks for .Fa rwlock would be exceeded. .It Bq Er EDEADLK The calling thread already holds a write lock on .Fa rwlock . .It Bq Er EINVAL The value specified by .Fa rwlock does not refer to an initialized read-write lock object, or the .Fa abs_timeout nanosecond value is less than zero or greater than or equal to 1 billion. .El .Sh SEE ALSO .Xr pthread_rwlock_init 3 , .Xr pthread_rwlock_timedwrlock 3 , .Xr pthread_rwlock_unlock 3 .Sh STANDARDS The .Fn pthread_rwlock_timedrdlock function is expected to conform to .St -p1003.1-96 . .Sh HISTORY The .Fn pthread_rwlock_timedrdlock function first appeared in .Fx 5.2 . Index: head/share/man/man3/pthread_rwlock_timedwrlock.3 =================================================================== --- head/share/man/man3/pthread_rwlock_timedwrlock.3 (revision 337991) +++ head/share/man/man3/pthread_rwlock_timedwrlock.3 (revision 337992) @@ -1,108 +1,108 @@ .\" Copyright (c) 2004 Michael Telahun Makonnen .\" 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$ .\" -.Dd January 16, 2004 +.Dd August 17, 2018 .Dt PTHREAD_RWLOCK_TIMEDWRLOCK 3 .Os .Sh NAME .Nm pthread_rwlock_timedwrlock .Nd "acquire a read-write lock for writing or give up after a specified period" .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_rwlock_timedwrlock "pthread_rwlock_t *rwlock" "const struct timespec *abs_timeout" +.Fn pthread_rwlock_timedwrlock "pthread_rwlock_t *restrict rwlock" "const struct timespec *restrict abs_timeout" .Sh DESCRIPTION This function acquires a write lock on the read-write lock .Fa rwlock . However, if the lock cannot be acquired without waiting for another thread to unlock the lock, this wait shall be terminated when .Fa abs_timeout expires. .Pp If the thread should be interrupted by a signal, the .Fn pthread_rwlock_timedwrlock function will be automatically restarted after the thread returns from the signal handler. .Pp The calling thread may deadlock if at the time the call is made it holds .Fa rwlock . The results are undefined if this function is called with an uninitialized read-write lock. .Sh IMPLEMENTATION NOTES To prevent writer starvation, writers are favored over readers. .Sh RETURN VALUES If successful, the .Fn pthread_rwlock_timedwrlock function will return zero. Otherwise, an error number will be returned to indicate the error. .Pp This function shall not return an error code of .Er EINTR . .Sh ERRORS The .Fn pthread_rwlock_timedwrlock function shall fail if: .Bl -tag -width Er .It Bq Er ETIMEDOUT The lock could not be acquired before the specified timeout expired. .El .Pp The .Fn pthread_rwlock_timedwrlock function may fail if: .Bl -tag -width Er .It Bq Er EDEADLK The calling thread already holds .Fa rwlock . .It Bq Er EINVAL The value specified by .Fa rwlock does not refer to an initialized read-write lock object, or the .Fa abs_timeout nanosecond value is less than zero or greater than or equal to 1 billion. .El .Sh SEE ALSO .Xr pthread_rwlock_init 3 , .Xr pthread_rwlock_timedrdlock 3 , .Xr pthread_rwlock_unlock 3 .Sh STANDARDS The .Fn pthread_rwlock_timedwrlock function is expected to conform to .St -p1003.1-96 . .Sh HISTORY The .Fn pthread_rwlock_timedwrlock function first appeared in .Fx 5.2 . Index: head/share/man/man3/pthread_rwlockattr_getpshared.3 =================================================================== --- head/share/man/man3/pthread_rwlockattr_getpshared.3 (revision 337991) +++ head/share/man/man3/pthread_rwlockattr_getpshared.3 (revision 337992) @@ -1,86 +1,86 @@ .\" 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$ .\" -.Dd March 22, 1999 +.Dd August 17, 2018 .Dt PTHREAD_RWLOCKATTR_GETPSHARED 3 .Os .Sh NAME .Nm pthread_rwlockattr_getpshared .Nd get the process shared attribute .Sh LIBRARY .Lb libpthread .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_rwlockattr_getpshared "const pthread_rwlockattr_t *attr" "int *pshared" +.Fn pthread_rwlockattr_getpshared "const pthread_rwlockattr_t *restrict attr" "int *restrict pshared" .Sh DESCRIPTION The .Fn pthread_rwlockattr_getpshared function is used to get the process shared setting of a read/write lock attribute object. The setting is returned via .Fa pshared , and may be one of two values: .Bl -tag -width PTHREAD_PROCESS_PRIVATE .It Dv PTHREAD_PROCESS_SHARED Any thread of any process that has access to the memory where the read/write lock resides can manipulate the lock. .It Dv PTHREAD_PROCESS_PRIVATE Only threads created within the same process as the thread that initialized the read/write lock can manipulate the lock. This is the default value. .El .Sh RETURN VALUES If successful, the .Fn pthread_rwlockattr_getpshared function will return zero. Otherwise an error number will be returned to indicate the error. .Sh ERRORS The .Fn pthread_rwlockattr_getpshared 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_rwlock_init 3 , .Xr pthread_rwlockattr_init 3 , .Xr pthread_rwlockattr_setpshared 3 .Sh STANDARDS The .Fn pthread_rwlockattr_getpshared function is expected to conform to .St -susv2 . .Sh HISTORY The .Fn pthread_rwlockattr_getpshared function first appeared in .Fx 3.0 . Index: head/share/man/man3/pthread_schedparam.3 =================================================================== --- head/share/man/man3/pthread_schedparam.3 (revision 337991) +++ head/share/man/man3/pthread_schedparam.3 (revision 337992) @@ -1,100 +1,100 @@ .\" 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$ .\" -.Dd October 16, 2006 +.Dd August 17, 2018 .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 *policy" "struct sched_param *param" +.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 either be .Dv SCHED_FIFO (first in, first out), .Dv SCHED_RR (round-robin), or .Dv SCHED_OTHER (timesharing). Valid thread priorities (accessed via .Va param->sched_priority ) must be within the range returned by the .Xr sched_get_priority_min 2 and .Xr sched_get_priority_max 2 system calls. .Sh RETURN VALUES If successful, these functions return 0. Otherwise, an error number is returned to indicate the error. .Sh ERRORS The .Fn pthread_setschedparam function will fail if: .Bl -tag -width Er .It Bq Er EINVAL Invalid value for .Fa policy . .It Bq Er ENOTSUP Invalid value for scheduling parameters. .It Bq Er ESRCH Non-existent thread .Fa thread . .El .Pp The .Fn pthread_getschedparam function will fail if: .Bl -tag -width Er .It Bq Er ESRCH Non-existent thread .Fa thread . .El .Sh SEE ALSO .Xr sched_get_priority_max 2 , .Xr sched_get_priority_min 2 .Sh STANDARDS The .Fn pthread_setschedparam and .Fn pthread_getschedparam functions conform to .St -susv2 .