xref: /freebsd/lib/libthr/libthr.3 (revision 8a7df6c58d549bd2eaa5cad30b2ef93c3eca3c18)
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.It Ev LIBPTHREAD_PSHARED_LOCK_DESTROY_IMMEDIATE_GC
210The implementation of the process shared lock scans
211the mapped shared off-pages to detect locks destroyed by other processes,
212when the current process destroys a shared lock.
213This is done not more often than 25msec.
214Setting the environment variable causes the scan to run on each destroy.
215.El
216.Pp
217The following
218.Dv sysctl
219MIBs affect the operation of the library:
220.Bl -tag -width "Dv debug.umtx.robust_faults_verbose"
221.It Dv kern.ipc.umtx_vnode_persistent
222By default, a shared lock backed by a mapped file in memory is
223automatically destroyed on the last unmap of the corresponding file's page,
224which is allowed by POSIX.
225Setting the sysctl to 1 makes such a shared lock object persist until
226the vnode is recycled by the Virtual File System.
227Note that in case file is not opened and not mapped, the kernel might
228recycle it at any moment, making this sysctl less useful than it sounds.
229.It Dv kern.ipc.umtx_max_robust
230The maximal number of robust mutexes allowed for one thread.
231The kernel will not unlock more mutexes than specified, see
232.Xr _umtx_op 2
233for more details.
234The default value is large enough for most useful applications.
235.It Dv debug.umtx.robust_faults_verbose
236A non zero value makes kernel emit some diagnostic when the robust
237mutexes unlock was prematurely aborted after detecting some inconsistency,
238as a measure to prevent memory corruption.
239.El
240.Pp
241The
242.Dv RLIMIT_UMTXP
243limit (see
244.Xr getrlimit 2 )
245defines how many shared locks a given user may create simultaneously.
246.Sh INTERACTION WITH RUN-TIME LINKER
247On load,
248.Nm
249installs interposing handlers into the hooks exported by
250.Li libc .
251The interposers provide real locking implementation instead of the
252stubs for single-threaded processes in
253.Li libc ,
254cancellation support and some modifications to the signal operations.
255.Pp
256.Nm
257cannot be unloaded; the
258.Xr dlclose 3
259function does not perform any action when called with a handle for
260.Nm .
261One of the reasons is that the internal interposing of
262.Li libc
263functions cannot be undone.
264.Sh SIGNALS
265The implementation interposes the user-installed
266.Xr signal 3
267handlers.
268This interposing is done to postpone signal delivery to threads which
269entered (libthr-internal) critical sections, where the calling
270of the user-provided signal handler is unsafe.
271An example of such a situation is owning the internal library lock.
272When a signal is delivered while the signal handler cannot be safely
273called, the call is postponed and performed until after the exit from
274the critical section.
275This should be taken into account when interpreting
276.Xr ktrace 1
277logs.
278.Pp
279The
280.Nm
281library uses the
282.Va SIGTHR
283signal for internal operations, in particular,
284for cancellation requests.
285This signal's masking and disposition is controlled by the library,
286and user programs should not try to modify them.
287The library interposes functions controlling signals to prevent
288inadvertent modifications and to guard portable code against
289exposure to
290.Va SIGTHR .
291.Pp
292Note: similarly, the
293.Va SIGLIBRT
294signal is reserved for use by
295.Lb librt ,
296and should be not modified by users.
297.Sh PROCESS-SHARED SYNCHRONIZATION OBJECTS
298In the
299.Li libthr
300implementation,
301user-visible types for all synchronization objects (e.g. pthread_mutex_t)
302are pointers to internal structures, allocated either by the corresponding
303.Fn pthread_<objtype>_init
304method call, or implicitly on first use when a static initializer
305was specified.
306The initial implementation of process-private locking object used this
307model with internal allocation, and the addition of process-shared objects
308was done in a way that did not break the application binary interface.
309.Pp
310For process-private objects, the internal structure is allocated using
311either
312.Xr malloc 3
313or, for
314.Xr pthread_mutex_init 3 ,
315an internal memory allocator implemented in
316.Nm .
317The internal allocator for mutexes is used to avoid bootstrap issues
318with many
319.Xr malloc 3
320implementations which need working mutexes to function.
321The same allocator is used for thread-specific data, see
322.Xr pthread_setspecific 3 ,
323for the same reason.
324.Pp
325For process-shared objects, the internal structure is created by first
326allocating a shared memory segment using
327.Xr _umtx_op 2
328operation
329.Dv UMTX_OP_SHM ,
330and then mapping it into process address space with
331.Xr mmap 2
332with the
333.Dv MAP_SHARED
334flag.
335The POSIX standard requires that:
336.Bd -literal
337only the process-shared synchronization object itself can be used for
338performing synchronization.  It need not be referenced at the address
339used to initialize it (that is, another mapping of the same object can
340be used).
341.Ed
342.Pp
343With the
344.Fx
345implementation, process-shared objects require initialization
346in each process that use them.
347In particular, if you map the shared memory containing the user portion of
348a process-shared object already initialized in different process, locking
349functions do not work on it.
350.Pp
351Another broken case is a forked child creating the object in memory shared
352with the parent, which cannot be used from parent.
353Note that processes should not use non-async-signal safe functions after
354.Xr fork 2
355anyway.
356.Sh SEE ALSO
357.Xr ktrace 1 ,
358.Xr ld-elf.so.1 1 ,
359.Xr _umtx_op 2 ,
360.Xr errno 2 ,
361.Xr getrlimit 2 ,
362.Xr thr_exit 2 ,
363.Xr thr_kill 2 ,
364.Xr thr_kill2 2 ,
365.Xr thr_new 2 ,
366.Xr thr_self 2 ,
367.Xr thr_set_name 2 ,
368.Xr dlclose 3 ,
369.Xr dlopen 3 ,
370.Xr getenv 3 ,
371.Xr pthread_attr 3 ,
372.Xr pthread_attr_setstacksize 3 ,
373.Xr pthread_create 3 ,
374.Xr signal 3 ,
375.Xr atomic 9
376.Sh HISTORY
377The
378.Nm
379library first appeared in
380.Fx 5.2 .
381.Sh AUTHORS
382.An -nosplit
383The
384.Nm
385library
386was originally created by
387.An Jeff Roberson Aq Mt jeff@FreeBSD.org ,
388and enhanced by
389.An Jonathan Mini Aq Mt mini@FreeBSD.org
390and
391.An Mike Makonnen Aq Mt mtm@FreeBSD.org .
392It has been substantially rewritten and optimized by
393.An David Xu Aq Mt davidxu@FreeBSD.org .
394