diff --git a/lib/libthr/libthr.3 b/lib/libthr/libthr.3 --- a/lib/libthr/libthr.3 +++ b/lib/libthr/libthr.3 @@ -1,5 +1,5 @@ .\" Copyright (c) 2005 Robert N. M. Watson -.\" Copyright (c) 2014,2015 The FreeBSD Foundation, Inc. +.\" Copyright (c) 2014,2015,2021 The FreeBSD Foundation, Inc. .\" All rights reserved. .\" .\" Part of this documentation was written by @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 5, 2020 +.Dd October 1, 2021 .Dt LIBTHR 3 .Os .Sh NAME @@ -259,6 +259,63 @@ This should be taken into account when interpreting .Xr ktrace 1 logs. +.Sh PROCESS-SHARED SYNCHRONIZATION OBJECTS +In the +.Li libthr +implementation, +user-visible types for all synchronization objects are pointers to the +internal structures, allocated either at the corresponding +.Fn pthread__init +method call, or implicitly on first use, when a static initializer +was specified. +Initial implementation of the process-private locking object used this +model with internal allocation, and addition of the process-shared objects +was done in a way that did not break application binary interface. +.Pp +For process-private objects, the internal structure is allocated using +either +.Xr malloc 3 +or, for +.Xr pthread_mutex_init 3 , +an internal memory allocator implemented in +.Nm . +The internal allocator for mutexes is used to avoid bootstrap issues +with many +.Xr malloc 3 +implementations which need working mutexes to function. +Same allocator is used for thread-specific data, see +.Xr pthread_setspecific 3 , +for the same reason. +.Pp +For process-shared objects, the internal structure is created by first +allocating shared memory segment using +.Xr _umtx_op 2 +operation +.Dv UMTX_OP_SHM , +and then mapping it into process address space with +.Xr mmap 2 +with +.Dv MAP_SHARED +flag. +The POSIX standard requires that: +.Bd -literal +only the process-shared synchronization object itself can be used for +performing synchronization. It need not be referenced at the address +used to initalize it (that is, another mapping of the same object can +be used). +.Ed +.Pp +With this implementation, the process-shared objects require initialization +in each process that use them. +In particular, if you map the shared memory containing the user portion of +the process-shared object already initialized in different process, locking +functions do not work on it. +.Pp +Another broken case is a forked child creating the object in memory shared +with the parent, which cannot be used from parent. +Note that processes should not use non-async-signal safe functions after +.Xr fork 2 +anyway. .Sh SEE ALSO .Xr ktrace 1 , .Xr ld-elf.so.1 1 , diff --git a/share/man/man3/Makefile b/share/man/man3/Makefile --- a/share/man/man3/Makefile +++ b/share/man/man3/Makefile @@ -481,11 +481,13 @@ PTHREAD_MLINKS+=pthread_mutexattr.3 pthread_mutexattr_destroy.3 \ pthread_mutexattr.3 pthread_mutexattr_getprioceiling.3 \ pthread_mutexattr.3 pthread_mutexattr_getprotocol.3 \ + pthread_mutexattr.3 pthread_mutexattr_getpshared.3 \ pthread_mutexattr.3 pthread_mutexattr_getrobust.3 \ pthread_mutexattr.3 pthread_mutexattr_gettype.3 \ pthread_mutexattr.3 pthread_mutexattr_init.3 \ pthread_mutexattr.3 pthread_mutexattr_setprioceiling.3 \ pthread_mutexattr.3 pthread_mutexattr_setprotocol.3 \ + pthread_mutexattr.3 pthread_mutexattr_setpshared.3 \ pthread_mutexattr.3 pthread_mutexattr_setrobust.3 \ pthread_mutexattr.3 pthread_mutexattr_settype.3 PTHREAD_MLINKS+=pthread_mutexattr_getkind_np.3 pthread_mutexattr_setkind_np.3 diff --git a/share/man/man3/pthread_barrierattr.3 b/share/man/man3/pthread_barrierattr.3 --- a/share/man/man3/pthread_barrierattr.3 +++ b/share/man/man3/pthread_barrierattr.3 @@ -38,11 +38,15 @@ .Ft int .Fn pthread_barrierattr_destroy "pthread_barrierattr_t *attr" .Ft int -.Fn pthread_barrierattr_getpshared "const pthread_barrierattr_t *restrict attr" "int *restrict pshared" +.Fo pthread_barrierattr_getpshared +.Fa "const pthread_barrierattr_t *restrict attr" "int *restrict pshared" +.Fc .Ft int .Fn pthread_barrierattr_init "pthread_barrierattr_t *attr" .Ft int -.Fn pthread_barrierattr_setpshared "pthread_barrierattr_t *attr" "int pshared" +.Fo pthread_barrierattr_setpshared +.Fa "pthread_barrierattr_t *attr" "int pshared" +.Fc .Sh DESCRIPTION The .Fn pthread_barrierattr_init diff --git a/share/man/man3/pthread_condattr.3 b/share/man/man3/pthread_condattr.3 --- a/share/man/man3/pthread_condattr.3 +++ b/share/man/man3/pthread_condattr.3 @@ -46,11 +46,15 @@ .Ft int .Fn pthread_condattr_destroy "pthread_condattr_t *attr" .Ft int -.Fn pthread_condattr_getclock "pthread_condattr_t * restrict attr" "clockid_t * restrict clock_id" +.Fo pthread_condattr_getclock +.Fa "pthread_condattr_t * restrict attr" "clockid_t * restrict clock_id" +.Fc .Ft int .Fn pthread_condattr_setclock "pthread_condattr_t *attr" "clockid_t clock_id" .Ft int -.Fn pthread_condattr_getpshared "pthread_condattr_t * restrict attr" "int * restrict pshared" +.Fo pthread_condattr_getpshared +.Fa "pthread_condattr_t * restrict attr" "int * restrict pshared" +.Fc .Ft int .Fn pthread_condattr_setpshared "pthread_condattr_t *attr" "int pshared" .Sh DESCRIPTION diff --git a/share/man/man3/pthread_mutexattr.3 b/share/man/man3/pthread_mutexattr.3 --- a/share/man/man3/pthread_mutexattr.3 +++ b/share/man/man3/pthread_mutexattr.3 @@ -1,6 +1,11 @@ .\" Copyright (C) 2000 Jason Evans . +.\" Copyright (c) 2021 The FreeBSD Foundation, Inc. .\" All rights reserved. .\" +.\" Part of this documentation was written 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: @@ -26,7 +31,7 @@ .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd August 17, 2018 +.Dd October 1, 2021 .Dt PTHREAD_MUTEXATTR 3 .Os .Sh NAME @@ -36,6 +41,8 @@ .Nm pthread_mutexattr_getprioceiling , .Nm pthread_mutexattr_setprotocol , .Nm pthread_mutexattr_getprotocol , +.Nm pthread_mutexattr_setpshared , +.Nm pthread_mutexattr_getpshared , .Nm pthread_mutexattr_setrobust , .Nm pthread_mutexattr_getrobust , .Nm pthread_mutexattr_settype , @@ -50,13 +57,27 @@ .Ft int .Fn pthread_mutexattr_destroy "pthread_mutexattr_t *attr" .Ft int -.Fn pthread_mutexattr_setprioceiling "pthread_mutexattr_t *attr" "int prioceiling" +.Fo pthread_mutexattr_setprioceiling +.Fa "pthread_mutexattr_t *attr" "int prioceiling" +.Fc .Ft int -.Fn pthread_mutexattr_getprioceiling "const pthread_mutexattr_t *attr" "int *prioceiling" +.Fo pthread_mutexattr_getprioceiling +.Fa "const pthread_mutexattr_t *attr" "int *prioceiling" +.Fc .Ft int .Fn pthread_mutexattr_setprotocol "pthread_mutexattr_t *attr" "int protocol" .Ft int -.Fn pthread_mutexattr_getprotocol "const pthread_mutexattr_t *restrict attr" "int *restrict protocol" +.Fo pthread_mutexattr_getprotocol +.Fa "const pthread_mutexattr_t *restrict attr" "int *restrict protocol" +.Fc +.Ft int +.Fo pthread_mutexattr_setpshared +.Fa "pthread_mutexattr_t *attr" "int shared" +.Fc +.Ft int +.Fo pthread_mutexattr_getpshared +.Fa "const pthread_mutexattr_t *attr" "int *shared" +.Fc .Ft int .Fn pthread_mutexattr_setrobust "pthread_mutexattr_t *attr" "int robust" .Ft int @@ -64,7 +85,9 @@ .Ft int .Fn pthread_mutexattr_settype "pthread_mutexattr_t *attr" "int type" .Ft int -.Fn pthread_mutexattr_gettype "const pthread_mutexattr_t *restrict attr" "int *restrict type" +.Fo pthread_mutexattr_gettype +.Fa "const pthread_mutexattr_t *restrict attr" "int *restrict type" +.Fc .Sh DESCRIPTION Mutex attributes are used to specify parameters to .Fn pthread_mutex_init . @@ -84,8 +107,89 @@ .Fa attr . .Pp The -.Fn pthread_mutexattr_set* -functions set the attribute that corresponds to each function name. +.Fn pthread_mutexattr_setprioceiling +function set the priority ceiling for the mutex, used +by threads executed under +.Dv PTHREAD_PRIO_PROTECT +protocol. +.Pp +The +.Fn pthread_mutexattr_setprotocol +function specifies the protocol to be followed in utilizing mutexes. +The +.Fa protocol +argument can take one of the following values: +.Bl -tag -width PTHREAD_PRIO_PROTECT +.It PTHREAD_PRIO_NONE +Priority and scheduling of the thread owning this mutex is not +affected by its mutex ownership. +.It PTHREAD_PRIO_INHERIT +Request priority-inheritance protocol, where the thread owning the mutex +is executed at highest priority among priorities of all threads waiting +on any mutex owned by this thread. +.It PTHREAD_PRIO_PROTECT +Request priority-inheritance protocol, where the thread owning the mutex +is executed at highest priority among priorities or priority ceilings of +all threads waiting on any mutex owned by this thread. +.El +.Pp +The +.Fn pthread_mutexattr_setrobust +function specifies robust attribute of the mutex. +Possible values for the +.Fa robust +argument are +.Bl -tag -width PTHREAD_MUTEX_STALLED +.It PTHREAD_MUTEX_STALLED +No special actions are taken if the thread owning the mutex is terminated +while holding the mutex lock. +This can lead to deadlocks if no other thread can unlock the mutex. +This is the default value. +.It PTHREAD_MUTEX_ROBUST +If the process containing the owning thread of a robust mutex, or owning +thread, terminates while holding the mutex lock, the next thread that +acquires the mutex is notified about the termination +by the return value +.Ev EOWNERDEAD +from the locking function. +Then, either +.Xr pthread_mutex_consistent 3 +can be used to repair the mutex lock state, or +.Xr pthread_mutex_unlock 3 +can unlock the mutex lock but also put it unreparaible state, +where all further attempts to acquire it result in the +.Ev ENOTRECOVERABLE +error. +.El +.Pp +The +.Fn pthread_mutexattr_settype +sets the type of the mutex. +Type affects the behavior of calls which lock and unlock the mutex. +The possible values for the +.Fa type +argument are +.Bl -tag -width PTHREAD_MUTEX_ERRORCHECK +.It PTHREAD_MUTEX_NORMAL +Both recursive locking and unlock when the lock is not owned by the current +thread cause an error returned from the corresponding functions. +This matches +.Dv PTHREAD_MUTEX_ERRORCHECK +but somewhat contradicts to the behavior mandated by POSIX. +.It PTHREAD_MUTEX_ERRORCHECK +Both recursive locking and unlock when the lock is not owned by the current +thread cause an error returned from the corresponding functions. +.It PTHREAD_MUTEX_RECURSIVE +Recursive locking is allowed. +Attempt to unlock when current thread is not an owner of the lock results +in an error returned. +.It PTHREAD_MUTEX_DEFAULT +The +.Fx +implementation maps this type to +.Dv PTHREAD_MUTEX_ERRORCHECK +type. +.El .Pp The .Fn pthread_mutexattr_get* @@ -153,6 +257,26 @@ .El .Pp The +.Fn pthread_mutexattr_setpshared +function will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +Invalid value for +.Fa attr , +or invalid value for +.Fa shared . +.El +.Pp +The +.Fn pthread_mutexattr_getpshared +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 @@ -206,6 +330,8 @@ .Fn pthread_mutexattr_getprioceiling , .Fn pthread_mutexattr_setprotocol , .Fn pthread_mutexattr_getprotocol , +.Fn pthread_mutexattr_setpshared , +.Fn pthread_mutexattr_getpshared , .Fn pthread_mutexattr_settype , and .Fn pthread_mutexattr_gettype diff --git a/share/man/man3/pthread_rwlockattr_getpshared.3 b/share/man/man3/pthread_rwlockattr_getpshared.3 --- a/share/man/man3/pthread_rwlockattr_getpshared.3 +++ b/share/man/man3/pthread_rwlockattr_getpshared.3 @@ -35,7 +35,9 @@ .Sh SYNOPSIS .In pthread.h .Ft int -.Fn pthread_rwlockattr_getpshared "const pthread_rwlockattr_t *restrict attr" "int *restrict pshared" +.Fo pthread_rwlockattr_getpshared +.Fa "const pthread_rwlockattr_t *restrict attr" "int *restrict pshared" +.Fc .Sh DESCRIPTION The .Fn pthread_rwlockattr_getpshared