This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v8 0/8] Add support for ISO C threads.h


On 07/20/2018 08:26 PM, Rical Jasan wrote:
> On 07/19/2018 12:58 PM, Adhemerval Zanella wrote:
>> If you could send a patch based on my personal branch [1] and can merge
>> it.
> I've attached the refactored/rewritten version.  It isn't a very long
> section, so shouldn't take long to review (IANAE, so somebody should).
> 
> Aside from the refactoring to make the Threads chapter generic, I
> reviewed the grammar, converted all references to "ISO C11" to "ISO C",
> added @standards to everything, made sure all the relevant functions
> mentioned their return values, and added cross-references where I felt
> they would be useful.  I also reviewed the output in PDF, Info, and HTML
> form.
> 
> I didn't mean to take so long, but I had to build make due a minimum
> version requirement before I could review the output, and it took a lot
> longer than building a single package like that usually does...
> 
> I didn't bother with the ChangeLog since I wasn't sure how you wanted to
> handle that, and it changes all the time anyway.

Great work here! Thank you for this help Rical!

OK for 2.28 with the follwing changes:

- Two spelling fixes.
- Consider suggestion for removing "unequivocally"
- Use "owning thread"
- Consider suggestion to expand thread type |'ing.
- Tighten up TLS language.
- You "use" a keyword.
- Broaden explanation of TSS_DTOR_ITERATIONS

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> commit 52d5f975656c61903d6a2fbb47a9ea460dd8db28
> Author: Rical Jasan <ricaljasan@pacific.net>
> Date:   Fri Jul 20 17:04:02 2018 -0700
> 
>     manual: Add documentation for ISO C Threads.
>     
>     The POSIX Threads chapter is renamed to Threads, making POSIX Threads
>     a section, and a new section is added on the topic of ISO C Threads.
>     
>             * manual/debug.texi: Update adjacent chapter name.
>             * manual/probes.texi: Likewise.
>             * manual/threads.texi (ISO C Threads): New section.
>             (POSIX Threads): Convert to a section.
> 
> diff --git a/manual/debug.texi b/manual/debug.texi
> index f4157e525e..712a42f75c 100644
> --- a/manual/debug.texi
> +++ b/manual/debug.texi
> @@ -1,5 +1,5 @@
>  @node Debugging Support
> -@c @node Debugging Support, POSIX Threads, Cryptographic Functions, Top
> +@c @node Debugging Support, Threads, Cryptographic Functions, Top

OK.

>  @c %MENU% Functions to help debugging applications
>  @chapter Debugging support
>  
> diff --git a/manual/probes.texi b/manual/probes.texi
> index fa6e38f785..ab2a3102bb 100644
> --- a/manual/probes.texi
> +++ b/manual/probes.texi
> @@ -1,5 +1,5 @@
>  @node Internal Probes
> -@c @node Internal Probes, Tunables, POSIX Threads, Top
> +@c @node Internal Probes, Tunables, Threads, Top

OK.

>  @c %MENU% Probes to monitor libc internal behavior
>  @chapter Internal probes
>  
> diff --git a/manual/threads.texi b/manual/threads.texi
> index 769d974d50..01217e1c85 100644
> --- a/manual/threads.texi
> +++ b/manual/threads.texi
> @@ -1,10 +1,538 @@
> +@node Threads
> +@c @node Threads, Internal Probes, Debugging Support, Top
> +@c %MENU% Functions, constants, and data types for working with threads

OK.

> +@chapter Threads
> +@cindex threads
> +
> +This chapter describes functions used for managing threads.
> +@Theglibc{} provides two threading implementations: ISO C threads and
> +POSIX threads.

OK.

> +
> +@menu
> +* ISO C Threads::	Threads based on the ISO C specification.
> +* POSIX Threads::	Threads based on the POSIX specification.

OK. Yay!

> +@end menu
> +
> +
> +@node ISO C Threads
> +@section ISO C Threads
> +@cindex ISO C threads
> +@cindex C threads
> +@pindex threads.h
> +
> +This section describes the @glibcadj{} ISO C threads implementation.
> +To have a deeper understanding of this API, it is strongly recomended

s/recomended/recommended/g

> +to read ISO/IEC 9899:2011, section 7.26, in which ISO C threads were
> +originally specified.  All types and function prototypes are declared
> +in the header file @file{threads.h}.
> +
> +@menu
> +* ISO C Threads Return Values:: Symbolic constants that represent a
> +				function's return value.
> +* ISO C Thread Management::	Support for basic threading.
> +* Call Once::			Single-call functions and macros.
> +* ISO C Mutexes::		A low-level mechanism for mutual exclusion.
> +* ISO C Condition Variables::	High-level objects for thread synchronization.
> +* ISO C Thread-local Storage::	Functions to support thread-local storage.
> +@end menu

OK.

> +
> +
> +@node ISO C Threads Return Values
> +@subsection Return Values
> +
> +The ISO C thread specification provides the following enumeration
> +constants for return values from functions in the API:
> +
> +@vtable @code
> +@item thrd_timedout
> +@standards{C11, threads.h}
> +A specified time was reached without acquiring the requested resource,
> +usually a mutex or condition variable.
> +
> +@item thrd_success
> +@standards{C11, threads.h}
> +The requested operation succeeded.
> +
> +@item thrd_busy
> +@standards{C11, threads.h}
> +The requested operation failed because a requested resource is already
> +in use.
> +
> +@item thrd_error
> +@standards{C11, threads.h}
> +The requested operation failed.
> +
> +@item thrd_nomem
> +@standards{C11, threads.h}
> +The requested operation failed because it was unable to allocate
> +enough memory.
> +@end vtable

OK.

> +
> +
> +@node ISO C Thread Management
> +@subsection Creation and Control
> +@cindex thread creation
> +@cindex thread control
> +@cindex thread management
> +
> +@Theglibc{} implements a set of functions that allow the user to easily
> +create and use threads.  Additional functionality is provided to control
> +the behavior of threads.
> +
> +The following data types are defined for managing threads:
> +
> +@deftp {Data Type} thrd_t
> +@standards{C11, threads.h}
> +A unique object that identifies a thread unequivocally.

Suggest:
A unique object that identifies one thread.

Do more with less.

> +@end deftp
> +
> +@deftp {Data Type} thrd_start_t
> +@standards{C11, threads.h}
> +This data type is an @code{int (*) (void *)} typedef that is passed to
> +@code{thrd_create} when creating a new thread.  It should point to the
> +first function that thread will run.
> +@end deftp
> +
> +The following functions are used for working with threads:
> +
> +@deftypefun int thrd_create (thrd_t *@var{thr}, thrd_start_t @var{func}, void *@var{arg})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_create} creates a new thread that will execute the function
> +@var{func}.  The object pointed to by @var{arg} will be used as the
> +argument to @var{func}.  If successful, @var{thr} is set to the new
> +thread identifier.

OK.

> +
> +This function may return @code{thrd_success}, @code{thrd_nomem}, or
> +@code{thrd_error}.

OK.

> +@end deftypefun
> +
> +@deftypefun thrd_t thrd_current (void)
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +This function returns the identifier of the calling thread.
> +@end deftypefun
> +
> +@deftypefun int thrd_equal (thrd_t @var{lhs}, thrd_t @var{rhs})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_equal} checks whether @var{lhs} and @var{rhs} refer to the
> +same thread.  If @var{lhs} and @var{rhs} are different threads, this
> +function returns @math{0}; otherwise, the return value is non-zero.
> +@end deftypefun

OK.

> +
> +@deftypefun int thrd_sleep (const struct timespec *@var{time_point}, struct timespec *@var{remaining})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_sleep} blocks the execution of the current thread for at
> +least until the elapsed time pointed to by @var{time_point} has been
> +reached.  This function does not take an absolute time, but a duration
> +that the thread is required to be blocked.  @xref{Time Basics}, and
> +@ref{Elapsed Time}.
> +

OK.

> +The thread may wake early if a signal that is not ignored is received.
> +In such a case, if @code{remaining} is not NULL, the remaining time
> +duration is stored in the object pointed to by
> +@var{remaining}.

OK.

> +
> +@code{thrd_sleep} returns @math{0} if it blocked for at least the
> +amount of time in @code{time_point}, @math{-1} if it was interrupted
> +by a signal, or a negative number on failure.
> +@end deftypefun

OK.

> +
> +@deftypefun void thrd_yield (void)
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_yield} provides a hint to the implementation to reschedule
> +the execution of the current thread, allowing other threads to run.
> +@end deftypefun

OK.

> +
> +@deftypefun {_Noreturn void} thrd_exit (int @var{res})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_exit} terminates execution of the calling thread and sets
> +its result code to @var{res}.
> +
> +If this function is called from a single-threaded process, the call is
> +equivalent to calling @code{exit} with @code{EXIT_SUCCESS}
> +(@pxref{Normal Termination}).  Also note that returning from a
> +function that started a thread is equivalent to calling
> +@code{thrd_exit}.

This is the text you worried about.

On the one hand the standard says "last thread," but what does that mean?
It implies a total ordering of exiting threads, when that might not be true,
but both texts appear to assume it. Therefore it's fine for a first kick at
the can to describe what is happening.

In essence you had a multi-threaded program, and the threads start exiting,
and eventually you are left with just one thread whose thrd_exit is equivalent
to exit. It's a fine cognitive model, but assumes the implementation imposes
that total exit ordering in order for there to be a "last" thread, rather than
all threads exiting simultaneously and all of them being the "last" thread.

This looks good to me.

> +@end deftypefun
> +
> +@deftypefun int thrd_detach (thrd_t @var{thr})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_detach} detaches the thread identified by @code{thr} from
> +the current control thread.  The resources held by the detached thread
> +will be freed automatically once the thread exits.  The parent thread
> +will never be notified by any @var{thr} signal.
> +
> +Calling @code{thrd_detach} on a thread that was previously detached or
> +joined by another thread results in undefined behavior.
> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun int thrd_join (thrd_t @var{thr}, int *@var{res})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{thrd_join} blocks the current thread until the thread identified
> +by @code{thr} finishes execution.  If @code{res} is not NULL, the
> +result code of the thread is put into the location pointed to by
> +@var{res}.  The termination of the thread @dfn{synchronizes-with} the
> +completion of this function, meaning both threads have arrived at a
> +common point in their execution.
> +
> +Calling @code{thrd_join} on a thread that was previously detached or
> +joined by another thread results in undefined behavior.
> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +
> +@node Call Once
> +@subsection Call Once
> +@cindex call once
> +@cindex single-call functions
> +
> +In order to guarantee single access to a function, @theglibc{}
> +implements a @dfn{call once function} to ensure a function is only
> +called once in the presence of multiple, potentially calling threads.
> +
> +@deftp {Data Type} once_flag
> +@standards{C11, threads.h}
> +A complete object type capable of holding a flag used by @code{call_once}.
> +@end deftp
> +
> +@defvr Macro ONCE_FLAG_INIT
> +@standards{C11, threads.h}
> +This value is used to initialize an object of type @code{once_flag}.
> +@end defvr
> +
> +@deftypefun void call_once (once_flag *@var{flag}, void (*@var{func}) (void))
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{call_once} calls function @var{func} exactly once, even if
> +invoked from several threads.  The completion of the function
> +@var{func} synchronizes-with all previous or subsequent calls to
> +@code{call_once} with the same @code{flag} variable.
> +@end deftypefun

OK.

> +
> +
> +@node ISO C Mutexes
> +@subsection Mutexes
> +@cindex mutex
> +@cindex mutual exclusion
> +
> +To have better control of resources and how threads access them,
> +@theglibc{} implements a @dfn{mutex} object, which can help avoid race
> +conditions and other concurrency issues.  The term ``mutex'' refers to

OK.

> +mutual exclusion.
> +

OK.

> +The fundamental data type for a mutex is the @code{mtx_t}:
> +
> +@deftp {Data Type} mtx_t
> +@standards{C11, threads.h}
> +The @code{mtx_t} data type uniquely identifies a mutex object.
> +@end deftp
> +
> +The ISO C standard defines several types of mutexes.  They are
> +represented by the following symbolic constants:
> +
> +@vtable @code
> +@item mtx_plain
> +@standards{C11, threads.h}
> +A mutex that does not support timeout, or test and return.
> +
> +@item mtx_recursive
> +@standards{C11, threads.h}
> +A mutex that supports recursive locking, which means that the owner
> +thread can lock it more than once without causing deadlock.

Traditional technical language is "owning thread"

s/owner thread/owning thread/g

> +
> +@item mtx_timed
> +@standards{C11, threads.h}
> +A mutex that supports timeout.
> +@end vtable
> +
> +The following functions are used for working with mutexes:
> +
> +@deftypefun int mtx_init (mtx_t *@var{mutex}, int @var{type})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{mtx_init} creates a new mutex object with type @var{type}.  The
> +object pointed to by @var{mutex} is set to the identifier of the newly
> +created mutex.
> +
> +The @code{type} argument may be either @code{mtx_plain} or
> +@code{mtx_timed}, optionally combined with @code{mtx_recursive}.

This should be expanded to ensure clarity.

Suggest:
~~~
The @code{type} argument may be either @code{mtx_plain},
@code{mtx_timed}, @code{mtx_plain | mtx_recursive}, or 
@code{mtx_timed | mtx_recursive}.
~~~

> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun int mtx_lock (mtx_t *@var{mutex})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +@code{mtx_lock} blocks the current thread until the mutex pointed to
> +by @var{mutex} is locked.  The behavior is undefined if the current
> +thread has already locked the mutex and the mutex is not recursive.
> +
> +Prior calls to @code{mtx_unlock} on the same mutex synchronize-with
> +this operation (if this operation succeeds), and all lock/unlock
> +operations on any given mutex form a single total order (similar to
> +the modification order of an atomic).
> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun int mtx_timedlock (mtx_t *restrict @var{mutex}, const struct timespec *restrict @var{time_point})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +@code{mtx_timedlock} blocks the current thread until the mutex pointed
> +to by @var{mutex} is locked or until the calendar time pointed to by
> +@var{time_point} has been reached.  Since this function takes an
> +absolute time, if a duration is required, the calendar time must be
> +calculated manually.  @xref{Time Basics}, and @ref{Calendar Time}.

OK.

> +
> +If the current thread has already locked the mutex and the mutex is
> +not recursive, or if the mutex does not support timeout, the behavior
> +of this function is undefined.
> +
> +Prior calls to @code{mtx_unlock} on the same mutex synchronize-with
> +this operation (if this operation succeeds), and all lock/unlock
> +operations on any given mutex form a single total order (similar to
> +the modification order of an atomic).
> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun

OK.

> +
> +@deftypefun int mtx_trylock (mtx_t *@var{mutex})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +@code{mtx_trylock} tries to lock the mutex pointed to by @var{mutex}
> +without blocking.  It returns immediately if the mutex is already
> +locked.
> +
> +Prior calls to @code{mtx_unlock} on the same mutex synchronize-with
> +this operation (if this operation succeeds), and all lock/unlock
> +operations on any given mutex form a single total order (similar to
> +the modification order of an atomic).
> +
> +This function returns @code{thrd_success} if the lock was obtained,
> +@code{thrd_busy} if the mutex is already locked, and @code{thrd_error}
> +on failure.
> +@end deftypefun
> +
> +@deftypefun int mtx_unlock (mtx_t *@var{mutex})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{mtx_unlock} unlocks the mutex pointed to by @var{mutex}.  The
> +behavior is undefined if the mutex is not locked by the calling
> +thread.

OK. What about unlocking a lock you already unlocked?

> +
> +This function synchronizes-with subsequent @code{mtx_lock},
> +@code{mtx_trylock}, and @code{mtx_timedlock} calls on the same mutex.
> +All lock/unlock operations on any given mutex form a single total
> +order (similar to the modification order of an atomic).
> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun void mtx_destroy (mtx_t *@var{mutex})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{mtx_destroy} destroys the mutex pointed to by @var{mutex}.  If
> +there are any threads waiting on the mutex, the behavior is
> +undefined.

OK.

> +@end deftypefun
> +
> +
> +@node ISO C Condition Variables
> +@subsection Condition Variables
> +@cindex condvar
> +@cindex condition variables
> +
> +Mutexes are not the only synchronization mechanisms available.  For
> +some more complex tasks, @theglibc{} also implements @dfn{condition
> +variables}, which allow the programmer to think at a higher level when
> +solving complex synchronization problems.  They are used to
> +synchronize threads waiting on a certain condition to happen.

OK.
> +
> +The fundamental data type for condition variables is the @code{cnd_t}:
> +
> +@deftp {Data Type} cnd_t
> +@standards{C11, threads.h}
> +The @code{cnd_t} uniquely identifies a condition variable object.
> +@end deftp
> +
> +The following functions are used for working with condition variables:
> +
> +@deftypefun int cnd_init (cnd_t *@var{cond})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{cnd_init} initializes a new condition variable, identified by
> +@var{cond}.
> +
> +This function may return @code{thrd_success}, @code{thrd_nomem}, or
> +@code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun int cnd_signal (cnd_t *@var{cond})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{cnd_signal} unblocks one thread that is currently waiting on the
> +condition variable pointed to by @var{cond}.  If a thread is
> +successfully unblocked, this function returns @code{thrd_success}.  If
> +no threads are blocked, this function does nothing and returns
> +@code{thrd_success}.  Otherwise, this function returns
> +@code{thrd_error}.
> +@end deftypefun

OK.

> +
> +@deftypefun int cnd_broadcast (cnd_t *@var{cond})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{cnd_broadcast} unblocks all the threads that are currently
> +waiting on the condition variable pointed to by @var{cond}.  This
> +function returns @code{thrd_success} on success.  If no threads are
> +blocked, this function does nothing and returns
> +@code{thrd_success}. Otherwise, this function returns
> +@code{thrd_error}.
> +@end deftypefun

OK.

> +
> +@deftypefun int cnd_wait (cnd_t *@var{cond}, mtx_t *@var{mutex})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +@code{cnd_wait} atomically unlocks the mutex pointed to by @var{mutex}
> +and blocks on the condition variable pointed to by @var{cond} until
> +the thread is signalled by @code{cnd_signal} or @code{cnd_broadcast}.

s/signalled/signaled/g

> +The mutex is locked again before the function returns.
> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun int cnd_timedwait (cnd_t *restrict @var{cond}, mtx_t *restrict @var{mutex}, const struct timespec *restrict @var{time_point})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
> +@code{cnd_timedwait} atomically unlocks the mutex pointed to by
> +@var{mutex} and blocks on the condition variable pointed to by
> +@var{cond} until the thread is signalled by @code{cnd_signal} or

s/signalled/signaled/g

> +@code{cnd_broadcast}, or until the calendar time pointed to by
> +@var{time_point} has been reached.  The mutex is locked again before
> +the function returns.
> +
> +As for @code{mtx_timedlock}, since this function takes an absolute
> +time, if a duration is required, the calendar time must be calculated
> +manually.  @xref{Time Basics}, and @ref{Calendar Time}.
> +

OK.

> +This function may return @code{thrd_success}, @code{thrd_nomem}, or
> +@code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun void cnd_destroy (cnd_t *@var{cond})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{cnd_destroy} destroys the condition variable pointed to by
> +@var{cond}.  If there are threads waiting on @var{cond}, the behavior
> +is undefined.
> +@end deftypefun

OK.

> +
> +
> +@node ISO C Thread-local Storage
> +@subsection Thread-local Storage
> +@cindex thread-local storage
> +
> +@Theglibc{} implements functions to provide @dfn{thread-local
> +storage}, which means each thread can have their own variables that
> +are not visible by other threads.

I would tighten this up a bit like this, since it's less about
visibility and more about storage:
~~~
@Theglibc{} implements functions to provide @dfn{thread-local
storage}. Variables can be defined to have unique storage per-thread,
lifetimes that match the thread lifetime, and destructors that cleanup
the unique per-thread storage.
~~~

> +
> +Several data types and macros exist for working with thread-local
> +storage:
> +
> +@deftp {Data Type} tss_t
> +@standards{C11, threads.h}
> +The @code{tss_t} data type identifies a thread-specific storage
> +object.  Even if shared, every thread will have its own instance of
> +the variable, with different values.
> +@end deftp

OK.

> +
> +@deftp {Data Type} tss_dtor_t
> +@standards{C11, threads.h}
> +The @code{tss_dtor_t} is a function pointer of type @code{void (*)
> +(void *)}, to be used as a thread-specific storage destructor.  The
> +function will be called when the current thread calls @code{thrd_exit}
> +(but never when calling @code{tss_delete} or @code{exit}).
> +@end deftp

OK.

> +
> +@defvr Macro thread_local
> +@standards{C11, threads.h}
> +@code{thread_local} is used to mark a variable with thread storage
> +duration, which means it is created when the thread starts and cleaned
> +up when the thread ends.

OK.

> +
> +@emph{Note:} For C++, C++11 or later is required to get the

s/get/use/g

You "use" a keyword.

> +@code{thread_local} keyword.
> +@end defvr
> +
> +@defvr Macro TSS_DTOR_ITERATIONS
> +@standards{C11, threads.h}
> +@code{TSS_DTOR_ITERATIONS} is an integer constant expression
> +representing the maximum number of times that destructors will be
> +called when a thread terminates.

Suggest a broader explanation:

@code{TSS_DTOR_ITERATIONS} is an integer constant expression
representing the maximum number of iterations over all thread-local
destructors at the time of thread termination. This value provides
a bounded limit to the destruction of thread-local storage e.g.
consider a destructor that creates more thread-local storage.

> +@end defvr
> +
> +The following functions are used to manage thread-local storage:
> +
> +@deftypefun int tss_create (tss_t *@var{tss_key}, tss_dtor_t @var{destructor})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{tss_create} creates a new thread-specific storage key and stores
> +it in the object pointed to by @var{tss_key}.  Although the same key
> +value may be used by different threads, the values bound to the key by
> +@code{tss_set} are maintained on a per-thread basis and persist for
> +the life of the calling thread.
> +
> +If @code{destructor} is not NULL, a destructor function will be set,
> +and called when the thread finishes its execution by calling
> +@code{thrd_exit}.
> +
> +This function returns @code{thrd_success} if @code{tss_key} is
> +successfully set to a unique value for the thread; otherwise,
> +@code{thrd_error} is returned and the value of @code{tss_key} is
> +undefined.
> +@end deftypefun

OK.

> +
> +@deftypefun int tss_set (tss_t @var{tss_key}, void *@var{val})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{tss_set} sets the value of the thread-specific storage
> +identified by @var{tss_key} for the current thread to @var{val}.
> +Different threads may set different values to the same key.

OK.

> +
> +This function returns either @code{thrd_success} or @code{thrd_error}.
> +@end deftypefun
> +
> +@deftypefun {void *} tss_get (tss_t @var{tss_key})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{tss_get} returns the value identified by @var{tss_key} held in
> +thread-specific storage for the current thread.  Different threads may
> +get different values identified by the same key.  On failure,
> +@code{tss_get} returns zero.
> +@end deftypefun

OK.

> +
> +@deftypefun void tss_delete (tss_t @var{tss_key})
> +@standards{C11, threads.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +@code{tss_delete} destroys the thread-specific storage identified by
> +@var{tss_key}.
> +@end deftypefun

OK.

> +
> +
>  @node POSIX Threads
> -@c @node POSIX Threads, Internal Probes, Cryptographic Functions, Top
> -@chapter POSIX Threads
> -@c %MENU% POSIX Threads
> +@section POSIX Threads

OK.

>  @cindex pthreads
>  
> -This chapter describes the @glibcadj{} POSIX Threads implementation.
> +This section describes the @glibcadj{} POSIX Threads implementation.
>  
>  @menu
>  * Thread-specific Data::          Support for creating and
> @@ -14,7 +542,7 @@ This chapter describes the @glibcadj{} POSIX Threads implementation.
>  @end menu
>  
>  @node Thread-specific Data
> -@section Thread-specific Data
> +@subsection Thread-specific Data
>  
>  The @glibcadj{} implements functions to allow users to create and manage
>  data specific to a thread.  Such data may be destroyed at thread exit,
> @@ -71,7 +599,7 @@ Associate the thread-specific @var{value} with @var{key} in the calling thread.
>  
>  
>  @node Non-POSIX Extensions
> -@section Non-POSIX Extensions
> +@subsection Non-POSIX Extensions
>  
>  In addition to implementing the POSIX API for threads, @theglibc{} provides
>  additional functions and interfaces to provide functionality not specified in
> @@ -83,7 +611,7 @@ the standard.
>  @end menu
>  
>  @node Default Thread Attributes
> -@subsection Setting Process-wide defaults for thread attributes
> +@subsubsection Setting Process-wide defaults for thread attributes
>  

OK.

>  @Theglibc{} provides non-standard API functions to set and get the default
>  attributes used in the creation of threads in a process.


-- 
Cheers,
Carlos.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]