Browse Source

sync with glibc

Mike Frysinger 20 years ago
parent
commit
7d342c378c
1 changed files with 282 additions and 83 deletions
  1. 282 83
      libpthread/linuxthreads/linuxthreads.texi

+ 282 - 83
libpthread/linuxthreads/linuxthreads.texi

@@ -19,7 +19,7 @@ use @var{errno}.
 * Thread Attributes::           Tuning thread scheduling.
 * Thread Attributes::           Tuning thread scheduling.
 * Cancellation::                Stopping a thread before it's done.
 * Cancellation::                Stopping a thread before it's done.
 * Cleanup Handlers::            Deallocating resources when a thread is
 * Cleanup Handlers::            Deallocating resources when a thread is
-                                  cancelled.
+                                  canceled.
 * Mutexes::                     One way to synchronize threads.
 * Mutexes::                     One way to synchronize threads.
 * Condition Variables::         Another way.
 * Condition Variables::         Another way.
 * POSIX Semaphores::            And a third way.
 * POSIX Semaphores::            And a third way.
@@ -27,6 +27,10 @@ use @var{errno}.
                                   different threads.
                                   different threads.
 * Threads and Signal Handling:: Why you should avoid mixing the two, and
 * Threads and Signal Handling:: Why you should avoid mixing the two, and
                                   how to do it if you must.
                                   how to do it if you must.
+* Threads and Fork::            Interactions between threads and the
+                                  @code{fork} function.
+* Streams and Fork::            Interactions between stdio streams and
+                                  @code{fork}.
 * Miscellaneous Thread Functions:: A grab bag of utility routines.
 * Miscellaneous Thread Functions:: A grab bag of utility routines.
 @end menu
 @end menu
 
 
@@ -98,12 +102,12 @@ returns 0. @xref{Cancellation}, for details.
 @deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return})
 @deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return})
 @code{pthread_join} suspends the execution of the calling thread until
 @code{pthread_join} suspends the execution of the calling thread until
 the thread identified by @var{th} terminates, either by calling
 the thread identified by @var{th} terminates, either by calling
-@code{pthread_exit} or by being cancelled.
+@code{pthread_exit} or by being canceled.
 
 
 If @var{thread_return} is not @code{NULL}, the return value of @var{th}
 If @var{thread_return} is not @code{NULL}, the return value of @var{th}
 is stored in the location pointed to by @var{thread_return}.  The return
 is stored in the location pointed to by @var{thread_return}.  The return
 value of @var{th} is either the argument it gave to @code{pthread_exit},
 value of @var{th} is either the argument it gave to @code{pthread_exit},
-or @code{PTHREAD_CANCELED} if @var{th} was cancelled.
+or @code{PTHREAD_CANCELED} if @var{th} was canceled.
 
 
 The joined thread @code{th} must be in the joinable state: it must not
 The joined thread @code{th} must be in the joinable state: it must not
 have been detached using @code{pthread_detach} or the
 have been detached using @code{pthread_detach} or the
@@ -177,13 +181,18 @@ left in an undefined state, and you must not use it again in a call to
 any pthreads function until it has been reinitialized.
 any pthreads function until it has been reinitialized.
 @end deftypefun
 @end deftypefun
 
 
+@findex pthread_attr_setdetachstate
+@findex pthread_attr_setguardsize
 @findex pthread_attr_setinheritsched
 @findex pthread_attr_setinheritsched
 @findex pthread_attr_setschedparam
 @findex pthread_attr_setschedparam
 @findex pthread_attr_setschedpolicy
 @findex pthread_attr_setschedpolicy
 @findex pthread_attr_setscope
 @findex pthread_attr_setscope
+@findex pthread_attr_setstack
+@findex pthread_attr_setstackaddr
+@findex pthread_attr_setstacksize
 @comment pthread.h
 @comment pthread.h
 @comment POSIX
 @comment POSIX
-@deftypefun int pthread_attr_set@var{attr} (pthread_attr_t *@var{obj}, int @var{value})
+@deftypefun int pthread_attr_setattr (pthread_attr_t *@var{obj}, int @var{value})
 Set attribute @var{attr} to @var{value} in the attribute object pointed
 Set attribute @var{attr} to @var{value} in the attribute object pointed
 to by @var{obj}.  See below for a list of possible attributes and the
 to by @var{obj}.  See below for a list of possible attributes and the
 values they can take.
 values they can take.
@@ -194,13 +203,18 @@ for the @var{attr} being modified, they will return the error code
 below.
 below.
 @end deftypefun
 @end deftypefun
 
 
+@findex pthread_attr_getdetachstate
+@findex pthread_attr_getguardsize
 @findex pthread_attr_getinheritsched
 @findex pthread_attr_getinheritsched
 @findex pthread_attr_getschedparam
 @findex pthread_attr_getschedparam
 @findex pthread_attr_getschedpolicy
 @findex pthread_attr_getschedpolicy
 @findex pthread_attr_getscope
 @findex pthread_attr_getscope
+@findex pthread_attr_getstack
+@findex pthread_attr_getstackaddr
+@findex pthread_attr_getstacksize
 @comment pthread.h
 @comment pthread.h
 @comment POSIX
 @comment POSIX
-@deftypefun int pthread_attr_get@var{attr} (const pthread_attr_t *@var{obj}, int *@var{value})
+@deftypefun int pthread_attr_getattr (const pthread_attr_t *@var{obj}, int *@var{value})
 Store the current setting of @var{attr} in @var{obj} into the variable
 Store the current setting of @var{attr} in @var{obj} into the variable
 pointed to by @var{value}.
 pointed to by @var{value}.
 
 
@@ -275,8 +289,45 @@ interpreted relative to the priorities of the other threads of the
 process, regardless of the priorities of other processes.
 process, regardless of the priorities of other processes.
 
 
 @code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads.  If you
 @code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads.  If you
-try to set the scope to this value @code{pthread_attr_setscope} will
+try to set the scope to this value, @code{pthread_attr_setscope} will
 fail and return @code{ENOTSUP}.
 fail and return @code{ENOTSUP}.
+
+@item stackaddr
+Provide an address for an application managed stack.  The size of the
+stack must be at least @code{PTHREAD_STACK_MIN}.
+
+@item stacksize
+Change the size of the stack created for the thread.  The value defines
+the minimum stack size, in bytes.
+
+If the value exceeds the system's maximum stack size, or is smaller
+than @code{PTHREAD_STACK_MIN}, @code{pthread_attr_setstacksize} will
+fail and return @code{EINVAL}.
+
+@item stack
+Provide both the address and size of an application managed stack to
+use for the new thread.  The base of the memory area is @var{stackaddr}
+with the size of the memory area, @var{stacksize}, measured in bytes.
+
+If the value of @var{stacksize} is less than @code{PTHREAD_STACK_MIN},
+or greater than the system's maximum stack size, or if the value of
+@var{stackaddr} lacks the proper alignment, @code{pthread_attr_setstack}
+will fail and return @code{EINVAL}.
+
+@item guardsize
+Change the minimum size in bytes of the guard area for the thread's
+stack.  The default size is a single page.  If this value is set, it
+will be rounded up to the nearest page size.  If the value is set to 0,
+a guard area will not be created for this thread.  The space allocated
+for the guard area is used to catch stack overflow.  Therefore, when
+allocating large structures on the stack, a larger guard area may be
+required to catch a stack overflow.
+
+If the caller is managing their own stacks (if the @code{stackaddr}
+attribute has been set), then the @code{guardsize} attribute is ignored.
+
+If the value exceeds the @code{stacksize}, @code{pthread_atrr_setguardsize}
+will fail and return @code{EINVAL}.
 @end table
 @end table
 
 
 @node Cancellation
 @node Cancellation
@@ -294,7 +345,7 @@ When a thread eventually honors a cancellation request, it behaves as if
 @code{pthread_exit(PTHREAD_CANCELED)} was called.  All cleanup handlers
 @code{pthread_exit(PTHREAD_CANCELED)} was called.  All cleanup handlers
 are executed in reverse order, finalization functions for
 are executed in reverse order, finalization functions for
 thread-specific data are called, and finally the thread stops executing.
 thread-specific data are called, and finally the thread stops executing.
-If the cancelled thread was joinable, the return value
+If the canceled thread was joinable, the return value
 @code{PTHREAD_CANCELED} is provided to whichever thread calls
 @code{PTHREAD_CANCELED} is provided to whichever thread calls
 @var{pthread_join} on it. See @code{pthread_exit} for more information.
 @var{pthread_join} on it. See @code{pthread_exit} for more information.
 
 
@@ -377,7 +428,7 @@ stack-like discipline.
 
 
 The purpose of cleanup handlers is to free the resources that a thread
 The purpose of cleanup handlers is to free the resources that a thread
 may hold at the time it terminates. In particular, if a thread exits or
 may hold at the time it terminates. In particular, if a thread exits or
-is cancelled while it owns a locked mutex, the mutex will remain locked
+is canceled while it owns a locked mutex, the mutex will remain locked
 forever and prevent other threads from executing normally. The best way
 forever and prevent other threads from executing normally. The best way
 to avoid this is, just before locking the mutex, to install a cleanup
 to avoid this is, just before locking the mutex, to install a cleanup
 handler whose effect is to unlock the mutex. Cleanup handlers can be
 handler whose effect is to unlock the mutex. Cleanup handlers can be
@@ -493,7 +544,7 @@ The sequence
 @smallexample
 @smallexample
 pthread_cleanup_push_defer_np(routine, arg);
 pthread_cleanup_push_defer_np(routine, arg);
 ...
 ...
-pthread_cleanup_pop_defer_np(execute);
+pthread_cleanup_pop_restore_np(execute);
 @end smallexample
 @end smallexample
 
 
 @noindent
 @noindent
@@ -546,15 +597,16 @@ calling thread.
 If @var{mutexattr} is @code{NULL}, default attributes are used instead.
 If @var{mutexattr} is @code{NULL}, default attributes are used instead.
 
 
 The LinuxThreads implementation supports only one mutex attribute,
 The LinuxThreads implementation supports only one mutex attribute,
-the @var{mutex kind}, which is either ``fast'', ``recursive'', or
-``error checking''. The kind of a mutex determines whether
+the @var{mutex type}, which is either ``fast'', ``recursive'', or
+``error checking''. The type of a mutex determines whether
 it can be locked again by a thread that already owns it.
 it can be locked again by a thread that already owns it.
-The default kind is ``fast''.
+The default type is ``fast''.
 
 
 Variables of type @code{pthread_mutex_t} can also be initialized
 Variables of type @code{pthread_mutex_t} can also be initialized
 statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for
 statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for
-fast mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for
-recursive mutexes), and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP}
+timed mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for
+recursive mutexes), @code{PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP}
+(for fast mutexes(, and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP}
 (for error checking mutexes).
 (for error checking mutexes).
 
 
 @code{pthread_mutex_init} always returns 0.
 @code{pthread_mutex_init} always returns 0.
@@ -570,16 +622,17 @@ already locked by another thread, @code{pthread_mutex_lock} suspends the
 calling thread until the mutex is unlocked.
 calling thread until the mutex is unlocked.
 
 
 If the mutex is already locked by the calling thread, the behavior of
 If the mutex is already locked by the calling thread, the behavior of
-@code{pthread_mutex_lock} depends on the kind of the mutex. If the mutex
-is of the ``fast'' kind, the calling thread is suspended.  It will
+@code{pthread_mutex_lock} depends on the type of the mutex. If the mutex
+is of the ``fast'' type, the calling thread is suspended.  It will
 remain suspended forever, because no other thread can unlock the mutex.
 remain suspended forever, because no other thread can unlock the mutex.
-If  the mutex is of the ``error checking'' kind, @code{pthread_mutex_lock}
+If  the mutex is of the ``error checking'' type, @code{pthread_mutex_lock}
 returns immediately with the error code @code{EDEADLK}.  If the mutex is
 returns immediately with the error code @code{EDEADLK}.  If the mutex is
-of the ``recursive'' kind, @code{pthread_mutex_lock} succeeds and
+of the ``recursive'' type, @code{pthread_mutex_lock} succeeds and
 returns immediately, recording the number of times the calling thread
 returns immediately, recording the number of times the calling thread
 has locked the mutex. An equal number of @code{pthread_mutex_unlock}
 has locked the mutex. An equal number of @code{pthread_mutex_unlock}
 operations must be performed before the mutex returns to the unlocked
 operations must be performed before the mutex returns to the unlocked
 state.
 state.
+@c This doesn't discuss PTHREAD_MUTEX_TIMED_NP mutex attributes. FIXME
 @end deftypefun
 @end deftypefun
 
 
 @comment pthread.h
 @comment pthread.h
@@ -593,14 +646,33 @@ calling thread in the case of a ``fast'' mutex). Instead,
 @code{EBUSY}.
 @code{EBUSY}.
 @end deftypefun
 @end deftypefun
 
 
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_mutex_timedlock (pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime})
+The @code{pthread_mutex_timedlock} is similar to the
+@code{pthread_mutex_lock} function but instead of blocking for in
+indefinite time if the mutex is locked by another thread, it returns
+when the time specified in @var{abstime} is reached.
+
+This function can only be used on standard (``timed'') and ``error
+checking'' mutexes.  It behaves just like @code{pthread_mutex_lock} for
+all other types.
+
+If the mutex is successfully locked, the function returns zero.  If the
+time specified in @var{abstime} is reached without the mutex being locked,
+@code{ETIMEDOUT} is returned.
+
+This function was introduced in the POSIX.1d revision of the POSIX standard.
+@end deftypefun
+
 @comment pthread.h
 @comment pthread.h
 @comment POSIX
 @comment POSIX
 @deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex})
 @deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex})
 @code{pthread_mutex_unlock} unlocks the given mutex. The mutex is
 @code{pthread_mutex_unlock} unlocks the given mutex. The mutex is
 assumed to be locked and owned by the calling thread on entrance to
 assumed to be locked and owned by the calling thread on entrance to
-@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' kind,
+@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' type,
 @code{pthread_mutex_unlock} always returns it to the unlocked state. If
 @code{pthread_mutex_unlock} always returns it to the unlocked state. If
-it is of the ``recursive'' kind, it decrements the locking count of the
+it is of the ``recursive'' type, it decrements the locking count of the
 mutex (number of @code{pthread_mutex_lock} operations performed on it by
 mutex (number of @code{pthread_mutex_lock} operations performed on it by
 the calling thread), and only when this count reaches zero is the mutex
 the calling thread), and only when this count reaches zero is the mutex
 actually unlocked.
 actually unlocked.
@@ -673,45 +745,52 @@ LinuxThreads implementation.
 This function always returns 0.
 This function always returns 0.
 @end deftypefun
 @end deftypefun
 
 
-LinuxThreads supports only one mutex attribute: the mutex kind, which is
-either @code{PTHREAD_MUTEX_FAST_NP} for ``fast'' mutexes,
-@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes, or
+LinuxThreads supports only one mutex attribute: the mutex type, which is
+either @code{PTHREAD_MUTEX_ADAPTIVE_NP} for ``fast'' mutexes,
+@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes,
+@code{PTHREAD_MUTEX_TIMED_NP} for ``timed'' mutexes, or
 @code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes.  As
 @code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes.  As
 the @code{NP} suffix indicates, this is a non-portable extension to the
 the @code{NP} suffix indicates, this is a non-portable extension to the
 POSIX standard and should not be employed in portable programs.
 POSIX standard and should not be employed in portable programs.
 
 
-The mutex kind determines what happens if a thread attempts to lock a
+The mutex type determines what happens if a thread attempts to lock a
 mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of
 mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of
-the ``fast'' kind, @code{pthread_mutex_lock} simply suspends the calling
-thread forever.  If the mutex is of the ``error checking'' kind,
+the ``fast'' type, @code{pthread_mutex_lock} simply suspends the calling
+thread forever.  If the mutex is of the ``error checking'' type,
 @code{pthread_mutex_lock} returns immediately with the error code
 @code{pthread_mutex_lock} returns immediately with the error code
-@code{EDEADLK}.  If the mutex is of the ``recursive'' kind, the call to
+@code{EDEADLK}.  If the mutex is of the ``recursive'' type, the call to
 @code{pthread_mutex_lock} returns immediately with a success return
 @code{pthread_mutex_lock} returns immediately with a success return
 code. The number of times the thread owning the mutex has locked it is
 code. The number of times the thread owning the mutex has locked it is
 recorded in the mutex. The owning thread must call
 recorded in the mutex. The owning thread must call
 @code{pthread_mutex_unlock} the same number of times before the mutex
 @code{pthread_mutex_unlock} the same number of times before the mutex
 returns to the unlocked state.
 returns to the unlocked state.
 
 
-The default mutex kind is ``fast'', that is, @code{PTHREAD_MUTEX_FAST_NP}.
+The default mutex type is ``timed'', that is, @code{PTHREAD_MUTEX_TIMED_NP}.
+@c This doesn't describe how a ``timed'' mutex behaves. FIXME
 
 
 @comment pthread.h
 @comment pthread.h
-@comment GNU
-@deftypefun int pthread_mutexattr_setkind_np (pthread_mutexattr_t *@var{attr}, int @var{kind})
-@code{pthread_mutexattr_setkind_np} sets the mutex kind attribute in
-@var{attr} to the value specified by @var{kind}.
+@comment POSIX
+@deftypefun int pthread_mutexattr_settype (pthread_mutexattr_t *@var{attr}, int @var{type})
+@code{pthread_mutexattr_settype} sets the mutex type attribute in
+@var{attr} to the value specified by @var{type}.
 
 
-If @var{kind} is not @code{PTHREAD_MUTEX_FAST_NP},
-@code{PTHREAD_MUTEX_RECURSIVE_NP}, or
+If @var{type} is not @code{PTHREAD_MUTEX_ADAPTIVE_NP},
+@code{PTHREAD_MUTEX_RECURSIVE_NP}, @code{PTHREAD_MUTEX_TIMED_NP}, or
 @code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return
 @code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return
 @code{EINVAL} and leave @var{attr} unchanged.
 @code{EINVAL} and leave @var{attr} unchanged.
+
+The standard Unix98 identifiers @code{PTHREAD_MUTEX_DEFAULT},
+@code{PTHREAD_MUTEX_NORMAL}, @code{PTHREAD_MUTEX_RECURSIVE},
+and @code{PTHREAD_MUTEX_ERRORCHECK} are also permitted.
+
 @end deftypefun
 @end deftypefun
 
 
 @comment pthread.h
 @comment pthread.h
-@comment GNU
-@deftypefun int pthread_mutexattr_getkind_np (const pthread_mutexattr_t *@var{attr}, int *@var{kind})
-@code{pthread_mutexattr_getkind_np} retrieves the current value of the
-mutex kind attribute in @var{attr} and stores it in the location pointed
-to by @var{kind}.
+@comment POSIX
+@deftypefun int pthread_mutexattr_gettype (const pthread_mutexattr_t *@var{attr}, int *@var{type})
+@code{pthread_mutexattr_gettype} retrieves the current value of the
+mutex type attribute in @var{attr} and stores it in the location pointed
+to by @var{type}.
 
 
 This function always returns 0.
 This function always returns 0.
 @end deftypefun
 @end deftypefun
@@ -820,7 +899,7 @@ nothing.
 @end deftypefun
 @end deftypefun
 
 
 @code{pthread_cond_wait} and @code{pthread_cond_timedwait} are
 @code{pthread_cond_wait} and @code{pthread_cond_timedwait} are
-cancellation points. If a thread is cancelled while suspended in one of
+cancellation points. If a thread is canceled while suspended in one of
 these functions, the thread immediately resumes execution, relocks the
 these functions, the thread immediately resumes execution, relocks the
 mutex specified by  @var{mutex}, and finally executes the cancellation.
 mutex specified by  @var{mutex}, and finally executes the cancellation.
 Consequently, cleanup handlers are assured that @var{mutex} is locked
 Consequently, cleanup handlers are assured that @var{mutex} is locked
@@ -1237,6 +1316,141 @@ threads must not attach their own signal handlers to these signals, or
 alternatively they should all block these signals (which is recommended
 alternatively they should all block these signals (which is recommended
 anyway).
 anyway).
 
 
+@node Threads and Fork
+@section Threads and Fork
+
+It's not intuitively obvious what should happen when a multi-threaded POSIX
+process calls @code{fork}. Not only are the semantics tricky, but you may
+need to write code that does the right thing at fork time even if that code
+doesn't use the @code{fork} function. Moreover, you need to be aware of
+interaction between @code{fork} and some library features like
+@code{pthread_once} and stdio streams.
+
+When @code{fork} is called by one of the threads of a process, it creates a new
+process which is copy of the  calling process. Effectively, in addition to
+copying certain system objects, the function takes a snapshot of the memory
+areas of the parent process, and creates identical areas in the child.
+To make matters more complicated, with threads it's possible for two or more
+threads to concurrently call fork to create two or more child processes.
+
+The child process has a copy of the address space of the parent, but it does
+not inherit any of its threads. Execution of the child process is carried out
+by a new thread which returns from @code{fork} function with a return value of
+zero; it is the only thread in the child process.  Because threads are not
+inherited across fork, issues arise. At the time of the call to @code{fork},
+threads in the parent process other than the one calling @code{fork} may have
+been executing critical regions of code.  As a result, the child process may
+get a copy of objects that are not in a well-defined state.  This potential
+problem affects all components of the program.
+
+Any program component which will continue being used in a child process must
+correctly handle its state during @code{fork}. For this purpose, the POSIX
+interface provides the special function @code{pthread_atfork} for installing
+pointers to handler functions which are called from within @code{fork}.
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void))
+
+@code{pthread_atfork} registers handler functions to be called just
+before and just after a new process is created with @code{fork}. The
+@var{prepare} handler will be called from the parent process, just
+before the new process is created. The @var{parent} handler will be
+called from the parent process, just before @code{fork} returns. The
+@var{child} handler will be called from the child process, just before
+@code{fork} returns.
+
+@code{pthread_atfork} returns 0 on success and a non-zero error code on
+error.
+
+One or more of the three handlers @var{prepare}, @var{parent} and
+@var{child} can be given as @code{NULL}, meaning that no handler needs
+to be called at the corresponding point.
+
+@code{pthread_atfork} can be called several times to install several
+sets of handlers. At @code{fork} time, the @var{prepare} handlers are
+called in LIFO order (last added with @code{pthread_atfork}, first
+called before @code{fork}), while the @var{parent} and @var{child}
+handlers are called in FIFO order (first added, first called).
+
+If there is insufficient memory available to register the handlers,
+@code{pthread_atfork} fails and returns @code{ENOMEM}.  Otherwise it
+returns 0.
+
+The functions @code{fork} and @code{pthread_atfork} must not be regarded as
+reentrant from the context of the handlers.  That is to say, if a
+@code{pthread_atfork} handler invoked from within @code{fork} calls
+@code{pthread_atfork} or @code{fork}, the behavior is undefined.
+
+Registering a triplet of handlers is an atomic operation with respect to fork.
+If new handlers are registered at about the same time as a fork occurs, either
+all three handlers will be called, or none of them will be called.
+
+The handlers are inherited by the child process, and there is no
+way to remove them, short of using @code{exec} to load a new
+pocess image.
+
+@end deftypefun
+
+To understand the purpose of @code{pthread_atfork}, recall that
+@code{fork} duplicates the whole memory space, including mutexes in
+their current locking state, but only the calling thread: other threads
+are not running in the child process.  The mutexes are not usable after
+the @code{fork} and must be initialized with @code{pthread_mutex_init}
+in the child process.  This is a limitation of the current
+implementation and might or might not be present in future versions.
+
+To avoid this, install handlers with @code{pthread_atfork} as follows: have the
+@var{prepare} handler lock the mutexes (in locking order), and the
+@var{parent} handler unlock the mutexes. The @var{child} handler should reset
+the mutexes using @code{pthread_mutex_init}, as well as any other
+synchronization objects such as condition variables.
+
+Locking the global mutexes before the fork ensures that all other threads are
+locked out of the critical regions of code protected by those mutexes.  Thus
+when @code{fork} takes a snapshot of the parent's address space, that snapshot
+will copy valid, stable data.  Resetting the synchronization objects in the
+child process will ensure they are properly cleansed of any artifacts from the
+threading subsystem of the parent process. For example, a mutex may inherit
+a wait queue of threads waiting for the lock; this wait queue makes no sense
+in the child process. Initializing the mutex takes care of this.
+
+@node Streams and Fork
+@section Streams and Fork
+
+The GNU standard I/O library has an internal mutex which guards the internal
+linked list of all standard C FILE objects. This mutex is properly taken care
+of during @code{fork} so that the child receives an intact copy of the list.
+This allows the @code{fopen} function, and related stream-creating functions,
+to work correctly in the child process, since these functions need to insert
+into the list.
+
+However, the individual stream locks are not completely taken care of.  Thus
+unless the multithreaded application takes special precautions in its use of
+@code{fork}, the child process might not be able to safely use the streams that
+it inherited from the parent.   In general, for any given open stream in the
+parent that is to be used by the child process, the application must ensure
+that that stream is not in use by another thread when @code{fork} is called.
+Otherwise an inconsistent copy of the stream object be produced. An easy way to
+ensure this is to use @code{flockfile} to lock the stream prior to calling
+@code{fork} and then unlock it with @code{funlockfile} inside the parent
+process, provided that the parent's threads properly honor these locks.
+Nothing special needs to be done in the child process, since the library
+internally resets all stream locks.
+
+Note that the stream locks are not shared between the parent and child.
+For example, even if you ensure that, say, the stream @code{stdout} is properly
+treated and can be safely used in the child, the stream locks do not provide
+an exclusion mechanism between the parent and child. If both processes write
+to @code{stdout}, strangely interleaved output may result regardless of
+the explicit use of @code{flockfile} or implicit locks.
+
+Also note that these provisions are a GNU extension; other systems might not
+provide any way for streams to be used in the child of a multithreaded process.
+POSIX requires that such a child process confines itself to calling only
+asynchronous safe functions, which excludes much of the library, including
+standard I/O.
+
 @node Miscellaneous Thread Functions
 @node Miscellaneous Thread Functions
 @section Miscellaneous Thread Functions
 @section Miscellaneous Thread Functions
 
 
@@ -1286,49 +1500,6 @@ The thread @var{th} is already in the detached state
 @end table
 @end table
 @end deftypefun
 @end deftypefun
 
 
-@comment pthread.h
-@comment POSIX
-@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void))
-
-@code{pthread_atfork} registers handler functions to be called just
-before and just after a new process is created with @code{fork}. The
-@var{prepare} handler will be called from the parent process, just
-before the new process is created. The @var{parent} handler will be
-called from the parent process, just before @code{fork} returns. The
-@var{child} handler will be called from the child process, just before
-@code{fork} returns.
-
-@code{pthread_atfork} returns 0 on success and a non-zero error code on
-error.
-
-One or more of the three handlers @var{prepare}, @var{parent} and
-@var{child} can be given as @code{NULL}, meaning that no handler needs
-to be called at the corresponding point.
-
-@code{pthread_atfork} can be called several times to install several
-sets of handlers. At @code{fork} time, the @var{prepare} handlers are
-called in LIFO order (last added with @code{pthread_atfork}, first
-called before @code{fork}), while the @var{parent} and @var{child}
-handlers are called in FIFO order (first added, first called).
-
-If there is insufficient memory available to register the handlers,
-@code{pthread_atfork} fails and returns @code{ENOMEM}.  Otherwise it
-returns 0.
-@end deftypefun
-
-To understand the purpose of @code{pthread_atfork}, recall that
-@code{fork} duplicates the whole memory space, including mutexes in
-their current locking state, but only the calling thread: other threads
-are not running in the child process. Thus, if a mutex is locked by a
-thread other than the thread calling @code{fork}, that mutex will remain
-locked forever in the child process, possibly blocking the execution of
-the child process. To avoid this, install handlers with
-@code{pthread_atfork} as follows: the @var{prepare} handler locks the
-global mutexes (in locking order), and the @var{parent} and @var{child}
-handlers unlock them (in reverse order). Alternatively, @var{prepare}
-and @var{parent} can be set to @code{NULL} and @var{child} to a function
-that calls @code{pthread_mutex_init} on the global mutexes.
-
 @comment pthread.h
 @comment pthread.h
 @comment GNU
 @comment GNU
 @deftypefun void pthread_kill_other_threads_np (@var{void})
 @deftypefun void pthread_kill_other_threads_np (@var{void})
@@ -1368,6 +1539,15 @@ record that initialization has been performed. Subsequent calls to
 @code{pthread_once} with the same @code{once_control} argument do
 @code{pthread_once} with the same @code{once_control} argument do
 nothing.
 nothing.
 
 
+If a thread is cancelled while executing @var{init_routine}
+the state of the @var{once_control} variable is reset so that
+a future call to @code{pthread_once} will call the routine again.
+
+If the process forks while one or more threads are executing
+@code{pthread_once} initialization routines, the states of their respective
+@var{once_control} variables will appear to be reset in the child process so
+that if the child calls @code{pthread_once}, the routines will be executed.
+
 @code{pthread_once} always returns 0.
 @code{pthread_once} always returns 0.
 @end deftypefun
 @end deftypefun
 
 
@@ -1426,3 +1606,22 @@ The @var{target_thread} is invalid or has already terminated.
 
 
 @end table
 @end table
 @end deftypefun
 @end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_setconcurrency (int @var{level})
+@code{pthread_setconcurrency} is unused in LinuxThreads due to the lack
+of a mapping of user threads to kernel threads.  It exists for source
+compatibility.  It does store the value @var{level} so that it can be
+returned by a subsequent call to @code{pthread_getconcurrency}.  It takes
+no other action however.
+@end deftypefun
+
+@comment pthread.h
+@comment POSIX
+@deftypefun int pthread_getconcurrency ()
+@code{pthread_getconcurrency} is unused in LinuxThreads due to the lack
+of a mapping of user threads to kernel threads.  It exists for source
+compatibility.  However, it will return the value that was set by the
+last call to @code{pthread_setconcurrency}.
+@end deftypefun