|
NAMElibthr —
1:1 POSIX threads library
LIBRARY1:1 Threading Library (libthr, -lthr)SYNOPSIS#include <pthread.h>
DESCRIPTIONThelibthr library provides a 1:1 implementation of the
pthread(3)
library interfaces for application threading. It has been optimized for use by
applications expecting system scope thread semantics.
The library is tightly integrated with the run-time link editor
ld-elf.so.1(1)
and Standard C Library (libc, -lc); all three
components must be built from the same source tree. Mixing
The man page documents the quirks and tunables of the
MUTEX ACQUISITIONA locked mutex (see pthread_mutex_lock(3)) is represented by a volatile variable of typelwpid_t ,
which records the global system identifier of the thread owning the lock.
libthr performs a contested mutex acquisition in three
stages, each of which is more resource-consuming than the previous. The first
two stages are only applied for a mutex of
PTHREAD_MUTEX_ADAPTIVE_NP type and
PTHREAD_PRIO_NONE protocol (see
pthread_mutexattr(3)).
First, on SMP systems, a spin loop is performed, where the library
attempts to acquire the lock by
atomic(9)
operations. The loop count is controlled by the
If the spin loop was unable to acquire the mutex, a yield loop is
executed, performing the same
atomic(9)
acquisition attempts as the spin loop, but each attempt is followed by a
yield of the CPU time of the thread using the
sched_yield(2)
syscall. By default, the yield loop is not executed. This is controlled by
the If both the spin and yield loops failed to acquire the lock, the thread is taken off the CPU and put to sleep in the kernel with the _umtx_op(2) syscall. The kernel wakes up a thread and hands the ownership of the lock to the woken thread when the lock becomes available. THREAD STACKSEach thread is provided with a private user-mode stack area used by the C runtime. The size of the main (initial) thread stack is set by the kernel, and is controlled by theRLIMIT_STACK process resource
limit (see
getrlimit(2)).
By default, the main thread's stack size is equal to the value of
The size of stacks for threads created by the process at run-time with the pthread_create(3) call is controlled by thread attributes: see pthread_attr(3), in particular, the pthread_attr_setstacksize(3), pthread_attr_setguardsize(3) and pthread_attr_setstackaddr(3) functions. If no attributes for the thread stack size are specified, the default non-initial thread stack size is 2MB for 64bit architectures, and 1MB for 32bit architectures. RUN-TIME SETTINGSThe following environment variables are recognized bylibthr and adjust the operation of the library at
run-time:
The following
The INTERACTION WITH RUN-TIME LINKEROn load,libthr installs interposing handlers into the
hooks exported by libc . The interposers provide real
locking implementation instead of the stubs for single-threaded processes in
libc , cancellation support and some modifications to
the signal operations.
SIGNALSThe implementation interposes the user-installed signal(3) handlers. This interposing is done to postpone signal delivery to threads which entered (libthr-internal) critical sections, where the calling of the user-provided signal handler is unsafe. An example of such a situation is owning the internal library lock. When a signal is delivered while the signal handler cannot be safely called, the call is postponed and performed until after the exit from the critical section. This should be taken into account when interpreting ktrace(1) logs.PROCESS-SHARED SYNCHRONIZATION OBJECTSIn thelibthr implementation, user-visible types for all
synchronization objects (e.g. pthread_mutex_t) are pointers to internal
structures, allocated either by the corresponding
pthread_<objtype>_init () method call, or
implicitly on first use when a static initializer was specified. The initial
implementation of process-private locking object used this model with internal
allocation, and the addition of process-shared objects was done in a way that
did not break the application binary interface.
For process-private objects, the internal structure is allocated
using either
malloc(3)
or, for
pthread_mutex_init(3),
an internal memory allocator implemented in For process-shared objects, the internal structure is created by
first allocating a shared memory segment using
_umtx_op(2)
operation only the process-shared synchronization object itself can be used for performing synchronization. It need not be referenced at the address used to initialize it (that is, another mapping of the same object can be used). With the FreeBSD implementation, process-shared objects require initialization in each process that use them. In particular, if you map the shared memory containing the user portion of a process-shared object already initialized in different process, locking functions do not work on it. 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 fork(2) anyway. SEE ALSOktrace(1), ld-elf.so.1(1), getrlimit(2), errno(2), thr_exit(2), thr_kill(2), thr_kill2(2), thr_new(2), thr_self(2), thr_set_name(2), _umtx_op(2), dlclose(3), dlopen(3), getenv(3), pthread_attr(3), pthread_attr_setstacksize(3), pthread_create(3), signal(3), atomic(9)HISTORYThelibthr library first appeared in
FreeBSD 5.2.
AUTHORSThelibthr library was originally created by
Jeff Roberson
<jeff@FreeBSD.org>, and
enhanced by Jonathan Mini
<mini@FreeBSD.org> and
Mike Makonnen
<mtm@FreeBSD.org>. It
has been substantially rewritten and optimized by David
Xu
<davidxu@FreeBSD.org>.
Visit the GSP FreeBSD Man Page Interface. |