summaryrefslogtreecommitdiffstats
path: root/man/man7/pthreads.7
diff options
context:
space:
mode:
Diffstat (limited to 'man/man7/pthreads.7')
-rw-r--r--man/man7/pthreads.7937
1 files changed, 937 insertions, 0 deletions
diff --git a/man/man7/pthreads.7 b/man/man7/pthreads.7
new file mode 100644
index 0000000..7079847
--- /dev/null
+++ b/man/man7/pthreads.7
@@ -0,0 +1,937 @@
+.\" Copyright (c) 2005 by Michael Kerrisk <mtk.manpages@gmail.com>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH pthreads 7 2024-05-02 "Linux man-pages (unreleased)"
+.SH NAME
+pthreads \- POSIX threads
+.SH DESCRIPTION
+POSIX.1 specifies a set of interfaces (functions, header files) for
+threaded programming commonly known as POSIX threads, or Pthreads.
+A single process can contain multiple threads,
+all of which are executing the same program.
+These threads share the same global memory (data and heap segments),
+but each thread has its own stack (automatic variables).
+.P
+POSIX.1 also requires that threads share a range of other attributes
+(i.e., these attributes are process-wide rather than per-thread):
+.IP \[bu] 3
+process ID
+.IP \[bu]
+parent process ID
+.IP \[bu]
+process group ID and session ID
+.IP \[bu]
+controlling terminal
+.IP \[bu]
+user and group IDs
+.IP \[bu]
+open file descriptors
+.IP \[bu]
+record locks (see
+.BR fcntl (2))
+.IP \[bu]
+signal dispositions
+.IP \[bu]
+file mode creation mask
+.RB ( umask (2))
+.IP \[bu]
+current directory
+.RB ( chdir (2))
+and
+root directory
+.RB ( chroot (2))
+.IP \[bu]
+interval timers
+.RB ( setitimer (2))
+and POSIX timers
+.RB ( timer_create (2))
+.IP \[bu]
+nice value
+.RB ( setpriority (2))
+.IP \[bu]
+resource limits
+.RB ( setrlimit (2))
+.IP \[bu]
+measurements of the consumption of CPU time
+.RB ( times (2))
+and resources
+.RB ( getrusage (2))
+.P
+As well as the stack, POSIX.1 specifies that various other
+attributes are distinct for each thread, including:
+.IP \[bu] 3
+thread ID (the
+.I pthread_t
+data type)
+.IP \[bu]
+signal mask
+.RB ( pthread_sigmask (3))
+.IP \[bu]
+the
+.I errno
+variable
+.IP \[bu]
+alternate signal stack
+.RB ( sigaltstack (2))
+.IP \[bu]
+real-time scheduling policy and priority
+.RB ( sched (7))
+.P
+The following Linux-specific features are also per-thread:
+.IP \[bu] 3
+capabilities (see
+.BR capabilities (7))
+.IP \[bu]
+CPU affinity
+.RB ( sched_setaffinity (2))
+.SS Pthreads function return values
+Most pthreads functions return 0 on success, and an error number on failure.
+The error numbers that can be returned have the same meaning as
+the error numbers returned in
+.I errno
+by conventional system calls and C library functions.
+Note that the pthreads functions do not set
+.IR errno .
+For each of the pthreads functions that can return an error,
+POSIX.1-2001 specifies that the function can never fail with the error
+.BR EINTR .
+.SS Thread IDs
+Each of the threads in a process has a unique thread identifier
+(stored in the type
+.IR pthread_t ).
+This identifier is returned to the caller of
+.BR pthread_create (3),
+and a thread can obtain its own thread identifier using
+.BR pthread_self (3).
+.P
+Thread IDs are guaranteed to be unique only within a process.
+(In all pthreads functions that accept a thread ID as an argument,
+that ID by definition refers to a thread in
+the same process as the caller.)
+.P
+The system may reuse a thread ID after a terminated thread has been joined,
+or a detached thread has terminated.
+POSIX says: "If an application attempts to use a thread ID whose
+lifetime has ended, the behavior is undefined."
+.SS Thread-safe functions
+A thread-safe function is one that can be safely
+(i.e., it will deliver the same results regardless of whether it is)
+called from multiple threads at the same time.
+.P
+POSIX.1-2001 and POSIX.1-2008 require that all functions specified
+in the standard shall be thread-safe,
+except for the following functions:
+.P
+.in +4n
+.EX
+asctime()
+basename()
+catgets()
+crypt()
+ctermid() if passed a non-NULL argument
+ctime()
+dbm_clearerr()
+dbm_close()
+dbm_delete()
+dbm_error()
+dbm_fetch()
+dbm_firstkey()
+dbm_nextkey()
+dbm_open()
+dbm_store()
+dirname()
+dlerror()
+drand48()
+ecvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
+encrypt()
+endgrent()
+endpwent()
+endutxent()
+fcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
+ftw()
+gcvt() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
+getc_unlocked()
+getchar_unlocked()
+getdate()
+getenv()
+getgrent()
+getgrgid()
+getgrnam()
+gethostbyaddr() [POSIX.1-2001 only (function removed in
+ POSIX.1-2008)]
+gethostbyname() [POSIX.1-2001 only (function removed in
+ POSIX.1-2008)]
+gethostent()
+getlogin()
+getnetbyaddr()
+getnetbyname()
+getnetent()
+getopt()
+getprotobyname()
+getprotobynumber()
+getprotoent()
+getpwent()
+getpwnam()
+getpwuid()
+getservbyname()
+getservbyport()
+getservent()
+getutxent()
+getutxid()
+getutxline()
+gmtime()
+hcreate()
+hdestroy()
+hsearch()
+inet_ntoa()
+l64a()
+lgamma()
+lgammaf()
+lgammal()
+localeconv()
+localtime()
+lrand48()
+mrand48()
+nftw()
+nl_langinfo()
+ptsname()
+putc_unlocked()
+putchar_unlocked()
+putenv()
+pututxline()
+rand()
+readdir()
+setenv()
+setgrent()
+setkey()
+setpwent()
+setutxent()
+strerror()
+strsignal() [Added in POSIX.1-2008]
+strtok()
+system() [Added in POSIX.1-2008]
+tmpnam() if passed a non-NULL argument
+ttyname()
+unsetenv()
+wcrtomb() if its final argument is NULL
+wcsrtombs() if its final argument is NULL
+wcstombs()
+wctomb()
+.EE
+.in
+.SS Async-cancel-safe functions
+An async-cancel-safe function is one that can be safely called
+in an application where asynchronous cancelability is enabled (see
+.BR pthread_setcancelstate (3)).
+.P
+Only the following functions are required to be async-cancel-safe by
+POSIX.1-2001 and POSIX.1-2008:
+.P
+.in +4n
+.EX
+pthread_cancel()
+pthread_setcancelstate()
+pthread_setcanceltype()
+.EE
+.in
+.SS Cancelation points
+POSIX.1 specifies that certain functions must,
+and certain other functions may, be cancelation points.
+If a thread is cancelable, its cancelability type is deferred,
+and a cancelation request is pending for the thread,
+then the thread is canceled when it calls a function
+that is a cancelation point.
+.P
+The following functions are required to be cancelation points by
+POSIX.1-2001 and/or POSIX.1-2008:
+.P
+.\" FIXME
+.\" Document the list of all functions that are cancelation points in glibc
+.in +4n
+.EX
+accept()
+aio_suspend()
+clock_nanosleep()
+close()
+connect()
+creat()
+fcntl() F_SETLKW
+fdatasync()
+fsync()
+getmsg()
+getpmsg()
+lockf() F_LOCK
+mq_receive()
+mq_send()
+mq_timedreceive()
+mq_timedsend()
+msgrcv()
+msgsnd()
+msync()
+nanosleep()
+open()
+openat() [Added in POSIX.1-2008]
+pause()
+poll()
+pread()
+pselect()
+pthread_cond_timedwait()
+pthread_cond_wait()
+pthread_join()
+pthread_testcancel()
+putmsg()
+putpmsg()
+pwrite()
+read()
+readv()
+recv()
+recvfrom()
+recvmsg()
+select()
+sem_timedwait()
+sem_wait()
+send()
+sendmsg()
+sendto()
+sigpause() [POSIX.1-2001 only (moves to "may" list in POSIX.1-2008)]
+sigsuspend()
+sigtimedwait()
+sigwait()
+sigwaitinfo()
+sleep()
+system()
+tcdrain()
+usleep() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
+wait()
+waitid()
+waitpid()
+write()
+writev()
+.EE
+.in
+.P
+The following functions may be cancelation points according to
+POSIX.1-2001 and/or POSIX.1-2008:
+.P
+.in +4n
+.EX
+access()
+asctime()
+asctime_r()
+catclose()
+catgets()
+catopen()
+chmod() [Added in POSIX.1-2008]
+chown() [Added in POSIX.1-2008]
+closedir()
+closelog()
+ctermid()
+ctime()
+ctime_r()
+dbm_close()
+dbm_delete()
+dbm_fetch()
+dbm_nextkey()
+dbm_open()
+dbm_store()
+dlclose()
+dlopen()
+dprintf() [Added in POSIX.1-2008]
+endgrent()
+endhostent()
+endnetent()
+endprotoent()
+endpwent()
+endservent()
+endutxent()
+faccessat() [Added in POSIX.1-2008]
+fchmod() [Added in POSIX.1-2008]
+fchmodat() [Added in POSIX.1-2008]
+fchown() [Added in POSIX.1-2008]
+fchownat() [Added in POSIX.1-2008]
+fclose()
+fcntl() (for any value of cmd argument)
+fflush()
+fgetc()
+fgetpos()
+fgets()
+fgetwc()
+fgetws()
+fmtmsg()
+fopen()
+fpathconf()
+fprintf()
+fputc()
+fputs()
+fputwc()
+fputws()
+fread()
+freopen()
+fscanf()
+fseek()
+fseeko()
+fsetpos()
+fstat()
+fstatat() [Added in POSIX.1-2008]
+ftell()
+ftello()
+ftw()
+futimens() [Added in POSIX.1-2008]
+fwprintf()
+fwrite()
+fwscanf()
+getaddrinfo()
+getc()
+getc_unlocked()
+getchar()
+getchar_unlocked()
+getcwd()
+getdate()
+getdelim() [Added in POSIX.1-2008]
+getgrent()
+getgrgid()
+getgrgid_r()
+getgrnam()
+getgrnam_r()
+gethostbyaddr() [POSIX.1-2001 only (function removed in
+ POSIX.1-2008)]
+gethostbyname() [POSIX.1-2001 only (function removed in
+ POSIX.1-2008)]
+gethostent()
+gethostid()
+gethostname()
+getline() [Added in POSIX.1-2008]
+getlogin()
+getlogin_r()
+getnameinfo()
+getnetbyaddr()
+getnetbyname()
+getnetent()
+getopt() (if opterr is nonzero)
+getprotobyname()
+getprotobynumber()
+getprotoent()
+getpwent()
+getpwnam()
+getpwnam_r()
+getpwuid()
+getpwuid_r()
+gets()
+getservbyname()
+getservbyport()
+getservent()
+getutxent()
+getutxid()
+getutxline()
+getwc()
+getwchar()
+getwd() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
+glob()
+iconv_close()
+iconv_open()
+ioctl()
+link()
+linkat() [Added in POSIX.1-2008]
+lio_listio() [Added in POSIX.1-2008]
+localtime()
+localtime_r()
+lockf() [Added in POSIX.1-2008]
+lseek()
+lstat()
+mkdir() [Added in POSIX.1-2008]
+mkdirat() [Added in POSIX.1-2008]
+mkdtemp() [Added in POSIX.1-2008]
+mkfifo() [Added in POSIX.1-2008]
+mkfifoat() [Added in POSIX.1-2008]
+mknod() [Added in POSIX.1-2008]
+mknodat() [Added in POSIX.1-2008]
+mkstemp()
+mktime()
+nftw()
+opendir()
+openlog()
+pathconf()
+pclose()
+perror()
+popen()
+posix_fadvise()
+posix_fallocate()
+posix_madvise()
+posix_openpt()
+posix_spawn()
+posix_spawnp()
+posix_trace_clear()
+posix_trace_close()
+posix_trace_create()
+posix_trace_create_withlog()
+posix_trace_eventtypelist_getnext_id()
+posix_trace_eventtypelist_rewind()
+posix_trace_flush()
+posix_trace_get_attr()
+posix_trace_get_filter()
+posix_trace_get_status()
+posix_trace_getnext_event()
+posix_trace_open()
+posix_trace_rewind()
+posix_trace_set_filter()
+posix_trace_shutdown()
+posix_trace_timedgetnext_event()
+posix_typed_mem_open()
+printf()
+psiginfo() [Added in POSIX.1-2008]
+psignal() [Added in POSIX.1-2008]
+pthread_rwlock_rdlock()
+pthread_rwlock_timedrdlock()
+pthread_rwlock_timedwrlock()
+pthread_rwlock_wrlock()
+putc()
+putc_unlocked()
+putchar()
+putchar_unlocked()
+puts()
+pututxline()
+putwc()
+putwchar()
+readdir()
+readdir_r()
+readlink() [Added in POSIX.1-2008]
+readlinkat() [Added in POSIX.1-2008]
+remove()
+rename()
+renameat() [Added in POSIX.1-2008]
+rewind()
+rewinddir()
+scandir() [Added in POSIX.1-2008]
+scanf()
+seekdir()
+semop()
+setgrent()
+sethostent()
+setnetent()
+setprotoent()
+setpwent()
+setservent()
+setutxent()
+sigpause() [Added in POSIX.1-2008]
+stat()
+strerror()
+strerror_r()
+strftime()
+symlink()
+symlinkat() [Added in POSIX.1-2008]
+sync()
+syslog()
+tmpfile()
+tmpnam()
+ttyname()
+ttyname_r()
+tzset()
+ungetc()
+ungetwc()
+unlink()
+unlinkat() [Added in POSIX.1-2008]
+utime() [Added in POSIX.1-2008]
+utimensat() [Added in POSIX.1-2008]
+utimes() [Added in POSIX.1-2008]
+vdprintf() [Added in POSIX.1-2008]
+vfprintf()
+vfwprintf()
+vprintf()
+vwprintf()
+wcsftime()
+wordexp()
+wprintf()
+wscanf()
+.EE
+.in
+.P
+An implementation may also mark other functions
+not specified in the standard as cancelation points.
+In particular, an implementation is likely to mark
+any nonstandard function that may block as a cancelation point.
+(This includes most functions that can touch files.)
+.P
+It should be noted that even if an application is not using
+asynchronous cancelation, that calling a function from the above list
+from an asynchronous signal handler may cause the equivalent of
+asynchronous cancelation.
+The underlying user code may not expect
+asynchronous cancelation and the state of the user data may become
+inconsistent.
+Therefore signals should be used with caution when
+entering a region of deferred cancelation.
+.\" So, scanning "cancelation point" comments in the glibc 2.8 header
+.\" files, it looks as though at least the following nonstandard
+.\" functions are cancelation points:
+.\" endnetgrent
+.\" endspent
+.\" epoll_pwait
+.\" epoll_wait
+.\" fcloseall
+.\" fdopendir
+.\" fflush_unlocked
+.\" fgetc_unlocked
+.\" fgetgrent
+.\" fgetgrent_r
+.\" fgetpwent
+.\" fgetpwent_r
+.\" fgets_unlocked
+.\" fgetspent
+.\" fgetspent_r
+.\" fgetwc_unlocked
+.\" fgetws_unlocked
+.\" fputc_unlocked
+.\" fputs_unlocked
+.\" fputwc_unlocked
+.\" fputws_unlocked
+.\" fread_unlocked
+.\" fwrite_unlocked
+.\" gai_suspend
+.\" getaddrinfo_a
+.\" getdate_r
+.\" getgrent_r
+.\" getgrouplist
+.\" gethostbyaddr_r
+.\" gethostbyname2
+.\" gethostbyname2_r
+.\" gethostbyname_r
+.\" gethostent_r
+.\" getnetbyaddr_r
+.\" getnetbyname_r
+.\" getnetent_r
+.\" getnetgrent
+.\" getnetgrent_r
+.\" getprotobyname_r
+.\" getprotobynumber_r
+.\" getprotoent_r
+.\" getpw
+.\" getpwent_r
+.\" getservbyname_r
+.\" getservbyport_r
+.\" getservent_r
+.\" getspent
+.\" getspent_r
+.\" getspnam
+.\" getspnam_r
+.\" getutmp
+.\" getutmpx
+.\" getw
+.\" getwc_unlocked
+.\" getwchar_unlocked
+.\" initgroups
+.\" innetgr
+.\" mkostemp
+.\" mkostemp64
+.\" mkstemp64
+.\" ppoll
+.\" pthread_timedjoin_np
+.\" putgrent
+.\" putpwent
+.\" putspent
+.\" putw
+.\" putwc_unlocked
+.\" putwchar_unlocked
+.\" rcmd
+.\" rcmd_af
+.\" rexec
+.\" rexec_af
+.\" rresvport
+.\" rresvport_af
+.\" ruserok
+.\" ruserok_af
+.\" setnetgrent
+.\" setspent
+.\" sgetspent
+.\" sgetspent_r
+.\" updwtmpx
+.\" utmpxname
+.\" vfscanf
+.\" vfwscanf
+.\" vscanf
+.\" vsyslog
+.\" vwscanf
+.SS Compiling on Linux
+On Linux, programs that use the Pthreads API should be compiled using
+.IR "cc \-pthread" .
+.SS Linux implementations of POSIX threads
+Over time, two threading implementations have been provided by
+the GNU C library on Linux:
+.TP
+.B LinuxThreads
+This is the original Pthreads implementation.
+Since glibc 2.4, this implementation is no longer supported.
+.TP
+.BR NPTL " (Native POSIX Threads Library)"
+This is the modern Pthreads implementation.
+By comparison with LinuxThreads, NPTL provides closer conformance to
+the requirements of the POSIX.1 specification and better performance
+when creating large numbers of threads.
+NPTL is available since glibc 2.3.2,
+and requires features that are present in the Linux 2.6 kernel.
+.P
+Both of these are so-called 1:1 implementations, meaning that each
+thread maps to a kernel scheduling entity.
+Both threading implementations employ the Linux
+.BR clone (2)
+system call.
+In NPTL, thread synchronization primitives (mutexes,
+thread joining, and so on) are implemented using the Linux
+.BR futex (2)
+system call.
+.SS LinuxThreads
+The notable features of this implementation are the following:
+.IP \[bu] 3
+In addition to the main (initial) thread,
+and the threads that the program creates using
+.BR pthread_create (3),
+the implementation creates a "manager" thread.
+This thread handles thread creation and termination.
+(Problems can result if this thread is inadvertently killed.)
+.IP \[bu]
+Signals are used internally by the implementation.
+On Linux 2.2 and later, the first three real-time signals are used
+(see also
+.BR signal (7)).
+On older Linux kernels,
+.B SIGUSR1
+and
+.B SIGUSR2
+are used.
+Applications must avoid the use of whichever set of signals is
+employed by the implementation.
+.IP \[bu]
+Threads do not share process IDs.
+(In effect, LinuxThreads threads are implemented as processes which share
+more information than usual, but which do not share a common process ID.)
+LinuxThreads threads (including the manager thread)
+are visible as separate processes using
+.BR ps (1).
+.P
+The LinuxThreads implementation deviates from the POSIX.1
+specification in a number of ways, including the following:
+.IP \[bu] 3
+Calls to
+.BR getpid (2)
+return a different value in each thread.
+.IP \[bu]
+Calls to
+.BR getppid (2)
+in threads other than the main thread return the process ID of the
+manager thread; instead
+.BR getppid (2)
+in these threads should return the same value as
+.BR getppid (2)
+in the main thread.
+.IP \[bu]
+When one thread creates a new child process using
+.BR fork (2),
+any thread should be able to
+.BR wait (2)
+on the child.
+However, the implementation allows only the thread that
+created the child to
+.BR wait (2)
+on it.
+.IP \[bu]
+When a thread calls
+.BR execve (2),
+all other threads are terminated (as required by POSIX.1).
+However, the resulting process has the same PID as the thread that called
+.BR execve (2):
+it should have the same PID as the main thread.
+.IP \[bu]
+Threads do not share user and group IDs.
+This can cause complications with set-user-ID programs and
+can cause failures in Pthreads functions if an application
+changes its credentials using
+.BR seteuid (2)
+or similar.
+.IP \[bu]
+Threads do not share a common session ID and process group ID.
+.IP \[bu]
+Threads do not share record locks created using
+.BR fcntl (2).
+.IP \[bu]
+The information returned by
+.BR times (2)
+and
+.BR getrusage (2)
+is per-thread rather than process-wide.
+.IP \[bu]
+Threads do not share semaphore undo values (see
+.BR semop (2)).
+.IP \[bu]
+Threads do not share interval timers.
+.IP \[bu]
+Threads do not share a common nice value.
+.IP \[bu]
+POSIX.1 distinguishes the notions of signals that are directed
+to the process as a whole and signals that are directed to individual
+threads.
+According to POSIX.1, a process-directed signal (sent using
+.BR kill (2),
+for example) should be handled by a single,
+arbitrarily selected thread within the process.
+LinuxThreads does not support the notion of process-directed signals:
+signals may be sent only to specific threads.
+.IP \[bu]
+Threads have distinct alternate signal stack settings.
+However, a new thread's alternate signal stack settings
+are copied from the thread that created it, so that
+the threads initially share an alternate signal stack.
+(A new thread should start with no alternate signal stack defined.
+If two threads handle signals on their shared alternate signal
+stack at the same time, unpredictable program failures are
+likely to occur.)
+.SS NPTL
+With NPTL, all of the threads in a process are placed
+in the same thread group;
+all members of a thread group share the same PID.
+NPTL does not employ a manager thread.
+.P
+NPTL makes internal use of the first two real-time signals;
+these signals cannot be used in applications.
+See
+.BR nptl (7)
+for further details.
+.P
+NPTL still has at least one nonconformance with POSIX.1:
+.IP \[bu] 3
+Threads do not share a common nice value.
+.\" FIXME . bug report filed for NPTL nice nonconformance
+.\" http://bugzilla.kernel.org/show_bug.cgi?id=6258
+.\" Sep 08: there is a patch by Denys Vlasenko to address this
+.\" "make setpriority POSIX compliant; introduce PRIO_THREAD extension"
+.\" Monitor this to see if it makes it into mainline.
+.P
+Some NPTL nonconformances occur only with older kernels:
+.IP \[bu] 3
+The information returned by
+.BR times (2)
+and
+.BR getrusage (2)
+is per-thread rather than process-wide (fixed in Linux 2.6.9).
+.IP \[bu]
+Threads do not share resource limits (fixed in Linux 2.6.10).
+.IP \[bu]
+Threads do not share interval timers (fixed in Linux 2.6.12).
+.IP \[bu]
+Only the main thread is permitted to start a new session using
+.BR setsid (2)
+(fixed in Linux 2.6.16).
+.IP \[bu]
+Only the main thread is permitted to make the process into a
+process group leader using
+.BR setpgid (2)
+(fixed in Linux 2.6.16).
+.IP \[bu]
+Threads have distinct alternate signal stack settings.
+However, a new thread's alternate signal stack settings
+are copied from the thread that created it, so that
+the threads initially share an alternate signal stack
+(fixed in Linux 2.6.16).
+.P
+Note the following further points about the NPTL implementation:
+.IP \[bu] 3
+If the stack size soft resource limit (see the description of
+.B RLIMIT_STACK
+in
+.BR setrlimit (2))
+is set to a value other than
+.IR unlimited ,
+then this value defines the default stack size for new threads.
+To be effective, this limit must be set before the program
+is executed, perhaps using the
+.I ulimit \-s
+shell built-in command
+.RI ( "limit stacksize"
+in the C shell).
+.SS Determining the threading implementation
+Since glibc 2.3.2, the
+.BR getconf (1)
+command can be used to determine
+the system's threading implementation, for example:
+.P
+.in +4n
+.EX
+bash$ getconf GNU_LIBPTHREAD_VERSION
+NPTL 2.3.4
+.EE
+.in
+.P
+With older glibc versions, a command such as the following should
+be sufficient to determine the default threading implementation:
+.P
+.in +4n
+.EX
+bash$ $( ldd /bin/ls | grep libc.so | awk \[aq]{print $3}\[aq] ) | \e
+ egrep \-i \[aq]threads|nptl\[aq]
+ Native POSIX Threads Library by Ulrich Drepper et al
+.EE
+.in
+.SS Selecting the threading implementation: LD_ASSUME_KERNEL
+On systems with a glibc that supports both LinuxThreads and NPTL
+(i.e., glibc 2.3.\fIx\fP), the
+.B LD_ASSUME_KERNEL
+environment variable can be used to override
+the dynamic linker's default choice of threading implementation.
+This variable tells the dynamic linker to assume that it is
+running on top of a particular kernel version.
+By specifying a kernel version that does not
+provide the support required by NPTL, we can force the use
+of LinuxThreads.
+(The most likely reason for doing this is to run a
+(broken) application that depends on some nonconformant behavior
+in LinuxThreads.)
+For example:
+.P
+.in +4n
+.EX
+bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \e
+ awk \[aq]{print $3}\[aq] ) | egrep \-i \[aq]threads|nptl\[aq]
+ linuxthreads\-0.10 by Xavier Leroy
+.EE
+.in
+.SH SEE ALSO
+.ad l
+.nh
+.BR clone (2),
+.BR fork (2),
+.BR futex (2),
+.BR gettid (2),
+.BR proc (5),
+.BR attributes (7),
+.BR futex (7),
+.BR nptl (7),
+.BR sigevent (3type),
+.BR signal (7)
+.P
+Various Pthreads manual pages, for example:
+.BR pthread_atfork (3),
+.BR pthread_attr_init (3),
+.BR pthread_cancel (3),
+.BR pthread_cleanup_push (3),
+.BR pthread_cond_signal (3),
+.BR pthread_cond_wait (3),
+.BR pthread_create (3),
+.BR pthread_detach (3),
+.BR pthread_equal (3),
+.BR pthread_exit (3),
+.BR pthread_key_create (3),
+.BR pthread_kill (3),
+.BR pthread_mutex_lock (3),
+.BR pthread_mutex_unlock (3),
+.BR pthread_mutexattr_destroy (3),
+.BR pthread_mutexattr_init (3),
+.BR pthread_once (3),
+.BR pthread_spin_init (3),
+.BR pthread_spin_lock (3),
+.BR pthread_rwlockattr_setkind_np (3),
+.BR pthread_setcancelstate (3),
+.BR pthread_setcanceltype (3),
+.BR pthread_setspecific (3),
+.BR pthread_sigmask (3),
+.BR pthread_sigqueue (3),
+and
+.BR pthread_testcancel (3)