1.\" Copyright (c) 2005 Robert N. M. Watson 2.\" Copyright (c) 2014,2015,2021 The FreeBSD Foundation 3.\" All rights reserved. 4.\" 5.\" Part of this documentation was written by 6.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship 7.\" from the FreeBSD Foundation. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28.\" SUCH DAMAGE. 29.\" 30.Dd October 1, 2021 31.Dt LIBTHR 3 32.Os 33.Sh NAME 34.Nm libthr 35.Nd "1:1 POSIX threads library" 36.Sh LIBRARY 37.Lb libthr 38.Sh SYNOPSIS 39.In pthread.h 40.Sh DESCRIPTION 41The 42.Nm 43library provides a 1:1 implementation of the 44.Xr pthread 3 45library interfaces for application threading. 46It 47has been optimized for use by applications expecting system scope thread 48semantics. 49.Pp 50The library is tightly integrated with the run-time link editor 51.Xr ld-elf.so.1 1 52and 53.Lb libc ; 54all three components must be built from the same source tree. 55Together, they constitute the base C runtime environment of 56.Fx , 57running on top of the 58.Fx 59kernel. 60.Pp 61Mixing 62.Li libc 63and 64.Nm 65libraries from different versions of 66.Fx 67is not supported. 68The run-time linker 69.Xr ld-elf.so.1 1 70has some code to ensure backward-compatibility with older versions of 71.Nm . 72.Pp 73The man page documents the quirks and tunables of the 74.Nm . 75When linking with 76.Li -lpthread , 77the run-time dependency 78.Li libthr.so.3 79is recorded in the produced object. 80.Sh MUTEX ACQUISITION 81A locked mutex (see 82.Xr pthread_mutex_lock 3 ) 83is represented by a volatile variable of type 84.Dv lwpid_t , 85which records the global system identifier of the thread 86owning the lock. 87.Nm 88performs a contested mutex acquisition in three stages, each of which 89is more resource-consuming than the previous. 90The first two stages are only applied for a mutex of 91.Dv PTHREAD_MUTEX_ADAPTIVE_NP 92type and 93.Dv PTHREAD_PRIO_NONE 94protocol (see 95.Xr pthread_mutexattr 3 ) . 96.Pp 97First, on SMP systems, a spin loop 98is performed, where the library attempts to acquire the lock by 99.Xr atomic 9 100operations. 101The loop count is controlled by the 102.Ev LIBPTHREAD_SPINLOOPS 103environment variable, with a default value of 2000. 104.Pp 105If the spin loop 106was unable to acquire the mutex, a yield loop 107is executed, performing the same 108.Xr atomic 9 109acquisition attempts as the spin loop, 110but each attempt is followed by a yield of the CPU time 111of the thread using the 112.Xr sched_yield 2 113syscall. 114By default, the yield loop 115is not executed. 116This is controlled by the 117.Ev LIBPTHREAD_YIELDLOOPS 118environment variable. 119.Pp 120If both the spin and yield loops 121failed to acquire the lock, the thread is taken off the CPU and 122put to sleep in the kernel with the 123.Xr _umtx_op 2 124syscall. 125The kernel wakes up a thread and hands the ownership of the lock to 126the woken thread when the lock becomes available. 127.Sh THREAD STACKS 128Each thread is provided with a private user-mode stack area 129used by the C runtime. 130The size of the main (initial) thread stack is set by the kernel, and is 131controlled by the 132.Dv RLIMIT_STACK 133process resource limit (see 134.Xr getrlimit 2 ) . 135.Pp 136By default, the main thread's stack size is equal to the value of 137.Dv RLIMIT_STACK 138for the process. 139If the 140.Ev LIBPTHREAD_SPLITSTACK_MAIN 141environment variable is present in the process environment 142(its value does not matter), 143the main thread's stack is reduced to 4MB on 64bit architectures, and to 1442MB on 32bit architectures, when the threading library is initialized. 145The rest of the address space area which has been reserved by the 146kernel for the initial process stack is used for non-initial thread stacks 147in this case. 148The presence of the 149.Ev LIBPTHREAD_BIGSTACK_MAIN 150environment variable overrides 151.Ev LIBPTHREAD_SPLITSTACK_MAIN ; 152it is kept for backward-compatibility. 153.Pp 154The size of stacks for threads created by the process at run-time 155with the 156.Xr pthread_create 3 157call is controlled by thread attributes: see 158.Xr pthread_attr 3 , 159in particular, the 160.Xr pthread_attr_setstacksize 3 , 161.Xr pthread_attr_setguardsize 3 162and 163.Xr pthread_attr_setstackaddr 3 164functions. 165If no attributes for the thread stack size are specified, the default 166non-initial thread stack size is 2MB for 64bit architectures, and 1MB 167for 32bit architectures. 168.Sh RUN-TIME SETTINGS 169The following environment variables are recognized by 170.Nm 171and adjust the operation of the library at run-time: 172.Bl -tag -width "Ev LIBPTHREAD_SPLITSTACK_MAIN" 173.It Ev LIBPTHREAD_BIGSTACK_MAIN 174Disables the reduction of the initial thread stack enabled by 175.Ev LIBPTHREAD_SPLITSTACK_MAIN . 176.It Ev LIBPTHREAD_SPLITSTACK_MAIN 177Causes a reduction of the initial thread stack, as described in the 178section 179.Sx THREAD STACKS . 180This was the default behaviour of 181.Nm 182before 183.Fx 11.0 . 184.It Ev LIBPTHREAD_SPINLOOPS 185The integer value of the variable overrides the default count of 186iterations in the 187.Li spin loop 188of the mutex acquisition. 189The default count is 2000, set by the 190.Dv MUTEX_ADAPTIVE_SPINS 191constant in the 192.Nm 193sources. 194.It Ev LIBPTHREAD_YIELDLOOPS 195A non-zero integer value enables the yield loop 196in the process of the mutex acquisition. 197The value is the count of loop operations. 198.It Ev LIBPTHREAD_QUEUE_FIFO 199The integer value of the variable specifies how often blocked 200threads are inserted at the head of the sleep queue, instead of its tail. 201Bigger values reduce the frequency of the FIFO discipline. 202The value must be between 0 and 255. 203.It Dv LIBPTHREAD_UMTX_MIN_TIMEOUT 204The minimal amount of time, in nanoseconds, the thread is required to sleep 205for pthread operations specifying a timeout. 206If the operation requests a timeout less than the value provided, 207it is silently increased to the value. 208The value of zero means no minimum (default). 209.Pp 210.El 211The following 212.Dv sysctl 213MIBs affect the operation of the library: 214.Bl -tag -width "Dv debug.umtx.robust_faults_verbose" 215.It Dv kern.ipc.umtx_vnode_persistent 216By default, a shared lock backed by a mapped file in memory is 217automatically destroyed on the last unmap of the corresponding file's page, 218which is allowed by POSIX. 219Setting the sysctl to 1 makes such a shared lock object persist until 220the vnode is recycled by the Virtual File System. 221Note that in case file is not opened and not mapped, the kernel might 222recycle it at any moment, making this sysctl less useful than it sounds. 223.It Dv kern.ipc.umtx_max_robust 224The maximal number of robust mutexes allowed for one thread. 225The kernel will not unlock more mutexes than specified, see 226.Xr _umtx_op 2 227for more details. 228The default value is large enough for most useful applications. 229.It Dv debug.umtx.robust_faults_verbose 230A non zero value makes kernel emit some diagnostic when the robust 231mutexes unlock was prematurely aborted after detecting some inconsistency, 232as a measure to prevent memory corruption. 233.El 234.Pp 235The 236.Dv RLIMIT_UMTXP 237limit (see 238.Xr getrlimit 2 ) 239defines how many shared locks a given user may create simultaneously. 240.Sh INTERACTION WITH RUN-TIME LINKER 241On load, 242.Nm 243installs interposing handlers into the hooks exported by 244.Li libc . 245The interposers provide real locking implementation instead of the 246stubs for single-threaded processes in 247.Li libc , 248cancellation support and some modifications to the signal operations. 249.Pp 250.Nm 251cannot be unloaded; the 252.Xr dlclose 3 253function does not perform any action when called with a handle for 254.Nm . 255One of the reasons is that the internal interposing of 256.Li libc 257functions cannot be undone. 258.Sh SIGNALS 259The implementation interposes the user-installed 260.Xr signal 3 261handlers. 262This interposing is done to postpone signal delivery to threads which 263entered (libthr-internal) critical sections, where the calling 264of the user-provided signal handler is unsafe. 265An example of such a situation is owning the internal library lock. 266When a signal is delivered while the signal handler cannot be safely 267called, the call is postponed and performed until after the exit from 268the critical section. 269This should be taken into account when interpreting 270.Xr ktrace 1 271logs. 272.Pp 273The 274.Nm 275library uses the 276.Va SIGTHR 277signal for internal operations, in particular, 278for cancellation requests. 279This signal's masking and disposition is controlled by the library, 280and user programs should not try to modify them. 281The library interposes functions controlling signals to prevent 282inadvertent modifications and to guard portable code against 283exposure to 284.Va SIGTHR . 285.Pp 286Note: similarly, the 287.Va SIGLIBRT 288signal is reserved for use by 289.Lb librt , 290and should be not modified by users. 291.Sh PROCESS-SHARED SYNCHRONIZATION OBJECTS 292In the 293.Li libthr 294implementation, 295user-visible types for all synchronization objects (e.g. pthread_mutex_t) 296are pointers to internal structures, allocated either by the corresponding 297.Fn pthread_<objtype>_init 298method call, or implicitly on first use when a static initializer 299was specified. 300The initial implementation of process-private locking object used this 301model with internal allocation, and the addition of process-shared objects 302was done in a way that did not break the application binary interface. 303.Pp 304For process-private objects, the internal structure is allocated using 305either 306.Xr malloc 3 307or, for 308.Xr pthread_mutex_init 3 , 309an internal memory allocator implemented in 310.Nm . 311The internal allocator for mutexes is used to avoid bootstrap issues 312with many 313.Xr malloc 3 314implementations which need working mutexes to function. 315The same allocator is used for thread-specific data, see 316.Xr pthread_setspecific 3 , 317for the same reason. 318.Pp 319For process-shared objects, the internal structure is created by first 320allocating a shared memory segment using 321.Xr _umtx_op 2 322operation 323.Dv UMTX_OP_SHM , 324and then mapping it into process address space with 325.Xr mmap 2 326with the 327.Dv MAP_SHARED 328flag. 329The POSIX standard requires that: 330.Bd -literal 331only the process-shared synchronization object itself can be used for 332performing synchronization. It need not be referenced at the address 333used to initialize it (that is, another mapping of the same object can 334be used). 335.Ed 336.Pp 337With the 338.Fx 339implementation, process-shared objects require initialization 340in each process that use them. 341In particular, if you map the shared memory containing the user portion of 342a process-shared object already initialized in different process, locking 343functions do not work on it. 344.Pp 345Another broken case is a forked child creating the object in memory shared 346with the parent, which cannot be used from parent. 347Note that processes should not use non-async-signal safe functions after 348.Xr fork 2 349anyway. 350.Sh SEE ALSO 351.Xr ktrace 1 , 352.Xr ld-elf.so.1 1 , 353.Xr _umtx_op 2 , 354.Xr errno 2 , 355.Xr getrlimit 2 , 356.Xr thr_exit 2 , 357.Xr thr_kill 2 , 358.Xr thr_kill2 2 , 359.Xr thr_new 2 , 360.Xr thr_self 2 , 361.Xr thr_set_name 2 , 362.Xr dlclose 3 , 363.Xr dlopen 3 , 364.Xr getenv 3 , 365.Xr pthread_attr 3 , 366.Xr pthread_attr_setstacksize 3 , 367.Xr pthread_create 3 , 368.Xr signal 3 , 369.Xr atomic 9 370.Sh HISTORY 371The 372.Nm 373library first appeared in 374.Fx 5.2 . 375.Sh AUTHORS 376.An -nosplit 377The 378.Nm 379library 380was originally created by 381.An Jeff Roberson Aq Mt jeff@FreeBSD.org , 382and enhanced by 383.An Jonathan Mini Aq Mt mini@FreeBSD.org 384and 385.An Mike Makonnen Aq Mt mtm@FreeBSD.org . 386It has been substantially rewritten and optimized by 387.An David Xu Aq Mt davidxu@FreeBSD.org . 388