Message ID | 1439299988-30771-2-git-send-email-j.m.torrespalma@gmail.com |
---|---|
State | New |
Headers | show |
On 08/11/2015 09:33 AM, Juan Manuel Torres Palma wrote: > This patch updates the manual and adds a new chapter to the manual, > explaining types macros, constants and functions defined by ISO C11 > threads.h standard. This has some substantive issues and some organizational problems. Let me first outline a better organization, and then I'll run through the whole thing pointing out the substantive issues as they pop up. It's very important to minimize forward references in documentation. That is, if someone starts reading at the beginning of a chapter, by the time they get to 'foo' they should already have encountered all the new concepts from that chapter that are necessary to understand 'foo'. In this case, what that mostly means is the result codes need to come first. I also strongly recommend separating 'call_once' and its associated constants and types to its own section -- right now it's smeared over the mutex section and the thread-local storage section, which is just weird. So it should be something like this: ISO C11 Threading Threading Result codes (current "C11 error types") thrd_success thrd_error thrd_timedout thrd_busy thrd_nomem Thread Creation and Control (current "Thread") thrd_t thrd_start_t thrd_current thrd_equal thrd_create thrd_exit thrd_join thrd_detach thrd_sleep thrd_yield Call Once (new) once_flag ONCE_FLAG_INIT call_once [an example] Thread-Local Storage thread_local tss_t tss_dtor_t TSS_DTOR_ITERATIONS tss_create tss_delete tss_get tss_set Mutexes mtx_t mtx_init mtx_plain (* move the explanation of these constants inside mtx_timed the @deftypefun for mtx_init *) mtx_recursive mtx_lock mtx_timedlock mtx_trylock mtx_unlock Condition Variables cnd_t cnd_init cnd_destroy cnd_wait cnd_timedwait cnd_signal cnd_broadcast General editorial comments: We do not appear to have any documentation of C11 atomics right now, and that means you need to avoid *talking* about C11 atomics or anything that you need to know C11 atomic terminology to understand. All the "synchronizes-with" stuff -- just delete it. (I would be making a different recommendation if I were asking you to write a full guide to threads, but since we don't even have complete reference documentation on POSIX threads right now, that seems like too much extra work to put on you.) Make sure everything appears in the appropriate index. Widespread substantive issues: You need to explain what the return value means for *every single function* even if you think it's obvious. (Having moved the result codes up front, "This function returns a threading result code" will often, but not always, be sufficient -- e.g. that would not be enough for mtx_trylock and mtx_timedlock.) The @safety{} annotations appear to be wrong across the board. Most of these functions probably are indeed multithread-safe (or they'd be useless!), but they probably *aren't* either async-signal or async-cancel safe. Please recheck every single one. I'm cross-checking your work with C11 (N1570) and there are a bunch of places where the standard doesn't specify the behavior as precisely as I would like, which is really quite unfortunate; we should think about the extent to which we want to pin down unspecified cases. @deftp clauses for cnd_t, mtx_t, tss_t, tss_dtor_t, and once_flag are missing. Specific substantive issues: > +@deftp {Data Type} {thrd_t} > +Unique number that identifies a thread > +unequivocally. > +@end deftp This should be described as an "opaque object", not a "number". > +@deftp {Data Type} {thrd_start_t} > +It is a function pointer that is passed to @code{thrd_create} when > +creating a new thread. Should point to the first function that thread > +will run. > +@end deftp This, you need to specify the exact definition of, (int (*)(void *)), so people know how to write their thread-start procedures. > +@deftypefun int thrd_equal (thrd_t @var{lhs}, thrd_t @var{rhs}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Checks whether @var{lhs} and @var{rhs} refer to the same thread. > +@end deftypefun This makes a nice example of how specific you need to be, everywhere, about the return value: "Returns a nonzero value if @var{lhs} and @var{rhs} refer to the same thread, or zero if they don't." > +@deftypefun int thrd_sleep (const struct timespec* @var{time_point}, struct timespec* @var{remaining}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Blocks the execution of the current thread for at least until > +the TIME_UTC based time point pointed to by @var{time_point} has been > +reached. C11 says this function takes a *duration*, not an absolute time point. What did you actually implement? Need to explicitly point out that this is not the same as mtx_timedlock or cnd_timedwait. TIME_UTC is not documented, say "wall-clock time" instead. > +@deftypefun _Noreturn void thrd_exit (int @var{res}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Terminates execution of the calling thread and sets its result code > +to @var{res}. > +@end deftypefun This needs to mention that returning from a thread-start procedure is equivalent to calling thrd_exit, and that thrd_exit calls exit(0), *regardless of the value of @var{res}*, if the calling thread is the only thread in the process. > +@deftypefun int thrd_detach (thrd_t @var{thr}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Detaches the thread identified by @var{thr} from the current > +environment. > +The resources held by the thread will be freed automatically once > +the thread exits. > +@end deftypefun I know this is what the C standard says this does, but it's not actually a helpful thing to say. It would be better to say something like "Informs the implementation that the program does not need any sort of notification when @var{thr} exits." > +@deftypefun int mtx_init (mtx_t* @var{mutex},int @var{type}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Creates a new mutex object with type @var{type}. The object pointed > +to by @var{mutex} is set to an identifier of the newly created mutex. > +@end deftypefun As mentioned above, explain the various values @var{type} can take *here*, not at the bottom of the section. > +@deftypefun int mtx_timedlock (mtx_t *restrict @var{mutex}, const struct timespec *restrict @var{time_point}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Blocks the current thread until the mutex pointed to by @var{mutex} > +is locked or until the TIME_UTC based time point pointed to > +by @var{time_point} has been reached. Again, TIME_UTC is not documented, so just say "wall-clock time". Point out specifically that this function differs from thr_sleep, in that it takes an absolute time point rather than a duration. > +@deftypefun int mtx_trylock (mtx_t *@var{mutex}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Tries to lock the mutex pointed to by @var{mutex} without blocking. > +Returns immediately if the mutex is already locked. "Returns thrd_success if it locked the mutex, or if this thread has already locked the mutex. (This does not count as a recursive lock.) Returns thrd_busy if another thread holds the lock." (Does the case where the lock is already held indeed not count as a recursive lock? That could be extremely bad.) > +@deftypefun int mtx_unlock (mtx_t *@var{mutex}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +Unlocks the mutex pointed to by @var{mutex}. The behavior is undefined > +if the mutex is not locked by the calling thread. This function > +synchronizes-with subsequent @code{mtx_lock}, @code{mtx_trylock}, > +or @code{mtx_timedlock} 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). > +@end deftypefun If you have recursively locked a mutex N times, do you need to unlock it N times also? (I see that C11 does not say.) > +Mutexes are not the only synchronization mechanisms available. For some > +more complex tasks, @theglibc{} also implements condition variables, > +that allow the user to think in a higher level to solve possible > +mutual exclusion issues. This paragraph doesn't make any sense. > +@deftypefun int cnd_timedwait (cnd_t* restrict @var{cond}, mtx_t* restrict @var{mutex}, const struct timespec* restrict @var{time_point}) > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +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}, or until the TIME_UTC based > +time point pointed to by @var{time_point} has been reached. The mutex > +is locked again before the function returns. > +@end deftypefun Same deal with TIME_UTC and being clear that this function, unlike thrd_sleep, *does* take an absolute time. > +@deftypevr Macro {} TSS_DTOR_ITERATIONS > +Integer constant expression representing the maximum number of > +times that destructors will be called when a thread terminates. > +@end deftypevr This also doesn't make any sense. I see that this text was copied verbatim from C11, but that isn't an excuse :) Ideally there would be something in here about when you should use thread_local versus tss_*. > +@deftypefun int tss_create (tss_t* @var{tss_key}, tss_dtor_t @var{destructor}) When would the destructor be called? > +The ISO C11 specification also provides new error types that belong > +specifically to @code{threads.h}. @Theglibc{} has also implemented > +this feature and every function in this API always returns one of the > +following error codes: Does that mean none of them ever set errno? > +@item thrd_error > +Value returned by a function to indicate that the requested operation > +failed. Gosh, that's vague. zw
Disclaimer: I haven't had time to look through the actual documentation, but want to comment nonetheless early so that we agree on the general direction. On Tue, 2015-08-11 at 14:06 -0400, Zack Weinberg wrote: > It's very important to minimize forward references in documentation. > That is, if someone starts reading at the beginning of a chapter, by > the time they get to 'foo' they should already have encountered all > the new concepts from that chapter that are necessary to understand > 'foo'. Agreed that this makes it easier, but understanding a concept does not mean that one knows about all possible instances of it. Specifically, it's perfectly fine to introduce the concept of a Threading Result Code without actually enumerating all the specific codes. Putting the enumeration further down in the manual can even be easier because the codes aren't central to the understanding, I'd claim -- users would be interested in the functions first, and then care about error conditions. > General editorial comments: > > We do not appear to have any documentation of C11 atomics right now, > and that means you need to avoid *talking* about C11 atomics or > anything that you need to know C11 atomic terminology to understand. > All the "synchronizes-with" stuff -- just delete it. I disagree. First, synchronizes-with is not tied C11 atomics, but to the C11 memory model. The semantics of atomics are described based on the memory model. If we try to document the semantics of the thread functions at all, we need to assume the reader is familiar with the memory model. Otherwise, we just shouldn't document any of the synchronization semantics (at which point we can just omit the docs completely I'd say). More generally, I'm also wondering why we even try to document semantics that are (supposed to be) documented perfectly by C11. I agree that the C11 specs aren't as precise as we'd want them to be, but then we need to make it clear that whatever we're documenting is just illustrative and not the authorative spec (which is C11), or covers implementation-defined behavior, or covers our interpretation of C11. > I'm cross-checking your work with C11 (N1570) and there are a bunch of > places where the standard doesn't specify the behavior as precisely as > I would like, which is really quite unfortunate; we should think about > the extent to which we want to pin down unspecified cases. If we do so, we should also look at C++14. It specifies the synchronization stuff more thoroughly, and arguably C++ and C should be aligned where possible. > > +@deftypefun int mtx_trylock (mtx_t *@var{mutex}) > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > > +Tries to lock the mutex pointed to by @var{mutex} without blocking. > > +Returns immediately if the mutex is already locked. > > "Returns thrd_success if it locked the mutex, or if this thread has > already locked the mutex. (This does not count as a recursive lock.) > Returns thrd_busy if another thread holds the lock." > > (Does the case where the lock is already held indeed not count as a > recursive lock? That could be extremely bad.) I believe calling mtx_trylock on a nonrecursive mutex is undefined behavior. It's not specifically called out in C (but is in C++), but mtx_lock makes that requirement. > > +@deftypefun int mtx_unlock (mtx_t *@var{mutex}) > > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > > +Unlocks the mutex pointed to by @var{mutex}. The behavior is undefined > > +if the mutex is not locked by the calling thread. This function > > +synchronizes-with subsequent @code{mtx_lock}, @code{mtx_trylock}, > > +or @code{mtx_timedlock} 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). The sc relation for sequential consistency is a better similarity. But we really should just point to C11 here instead of inventing our own wording. > > +@end deftypefun > > If you have recursively locked a mutex N times, do you need to unlock > it N times also? (I see that C11 does not say.) Yes, you have to. If C11 should say that, this should be treated as a C11 defect. > > +Mutexes are not the only synchronization mechanisms available. For some > > +more complex tasks, @theglibc{} also implements condition variables, > > +that allow the user to think in a higher level to solve possible > > +mutual exclusion issues. > > This paragraph doesn't make any sense. Agreed, it's incorrect. condvars are not a mutual exclusion mechanism. > > +@deftypevr Macro {} TSS_DTOR_ITERATIONS > > +Integer constant expression representing the maximum number of > > +times that destructors will be called when a thread terminates. > > +@end deftypevr > > This also doesn't make any sense. I see that this text was copied > verbatim from C11, but that isn't an excuse :) Well, copying C11 is better than inventing our own semantics that might diverge from C11. Thus, the way forward is to clarify this upstream first, and then specify what upstream does -- and upstream is ISO C in this case. > Ideally there would be something in here about when you should use > thread_local versus tss_*. > > > +@deftypefun int tss_create (tss_t* @var{tss_key}, tss_dtor_t > @var{destructor}) > > When would the destructor be called? > > > +The ISO C11 specification also provides new error types that belong > > +specifically to @code{threads.h}. @Theglibc{} has also implemented > > +this feature and every function in this API always returns one of the > > +following error codes: > > Does that mean none of them ever set errno? > > > +@item thrd_error > > +Value returned by a function to indicate that the requested operation > > +failed. > > Gosh, that's vague. But that may be the right description, given that it's a catch-all code.
diff --git a/manual/Makefile b/manual/Makefile index 5382208..04c9154 100644 --- a/manual/Makefile +++ b/manual/Makefile @@ -38,7 +38,8 @@ chapters = $(addsuffix .texi, \ message search pattern io stdio llio filesys \ pipe socket terminal syslog math arith time \ resource setjmp signal startup process ipc job \ - nss users sysinfo conf crypt debug threads probes) + nss users sysinfo conf crypt debug threads probes \ + isothreads) add-chapters = $(wildcard $(foreach d, $(add-ons), ../$d/$d.texi)) appendices = lang.texi header.texi install.texi maint.texi platform.texi \ contrib.texi diff --git a/manual/isothreads.texi b/manual/isothreads.texi new file mode 100644 index 0000000..8a602a2 --- /dev/null +++ b/manual/isothreads.texi @@ -0,0 +1,326 @@ +@node ISO Threads, , , Top +@chapter ISO C11 threads + +This chapter describes @theglibc{} ISO C11 threads implementation. +All types and function prototypes are declared in +@file{threads.h} header. +@pindex threads.h + +@menu +* Thread:: Support for basic threading +* Mutex:: Low level mechanism for mutual exclusion +* Condition variable:: Objects required for threads synchronization +* Thread-local storage:: Functions to support thread-local storage +* C11 error types:: Symbolic constants that represent functions return value +@end menu + +@node Thread, Mutex, , ISO Threads +@section Thread + +@Theglibc{} implements a set of functions that allows the user +to easily create and use threads. Many extra functionalities are +provided to control the behaviour of threads. The following functions +and types are defined: + +@deftp {Data Type} {thrd_t} +Unique number that identifies a thread +unequivocally. +@end deftp + +@deftp {Data Type} {thrd_start_t} +It is a function pointer that is passed to @code{thrd_create} when +creating a new thread. Should point to the first function that thread +will run. +@end deftp + +@deftypefun int thrd_create (thrd_t *@var{thr}, thrd_start_t @var{func}, void *@var{arg}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Create a new thread executing the function @var{func}. The object +pointed by @var{arg} will be taken as @var{func} arguments. If successful, +@var{thr} is so to the new thread identifier. +@end deftypefun + + +@deftypefun int thrd_equal (thrd_t @var{lhs}, thrd_t @var{rhs}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Checks whether @var{lhs} and @var{rhs} refer to the same thread. +@end deftypefun + + +@deftypefun thrd_t thrd_current (void) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Returns the identifier of the calling thread. +@end deftypefun + +@deftypefun int thrd_sleep (const struct timespec* @var{time_point}, struct timespec* @var{remaining}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Blocks the execution of the current thread for at least until +the TIME_UTC based time point pointed to by @var{time_point} has been +reached. + +The sleep may resume earlier if a signal that is not ignored is +received. In such case, if remaining is not NULL, the remaining +time duration is stored into the object pointed to by @var{remaining} +@end deftypefun + +@deftypefun void thrd_yield (void) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Provides a hint to the implementation to reschedule the execution +of threads, allowing other threads to run. +@end deftypefun + +@deftypefun _Noreturn void thrd_exit (int @var{res}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Terminates execution of the calling thread and sets its result code +to @var{res}. +@end deftypefun + +@deftypefun int thrd_detach (thrd_t @var{thr}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Detaches the thread identified by @var{thr} from the current +environment. +The resources held by the thread will be freed automatically once +the thread exits. +@end deftypefun + +@deftypefun int thrd_join (thrd_t @var{thr}, int *@var{res}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Blocks the current thread until the thread identified by @var{thr} +finishes execution. If @var{res} is not a null pointer, the result +code of the thread is put to the location pointed to by @var{res}. +The termination of the thread synchronizes-with the +completion of this function. +The behavior is undefined if the thread was previously detached +or joined by another thread. +@end deftypefun + + +@node Mutex, Condition variable, Thread, ISO Threads +@section Mutex + +To have a better control of resources and how threads access them, +@theglibc{} also implements a mutex object, that allows to +avoid race conditions and some other concurrency issues. + +@deftypefun int mtx_init (mtx_t* @var{mutex},int @var{type}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Creates a new mutex object with type @var{type}. The object pointed +to by @var{mutex} is set to an identifier of the newly created mutex. +@end deftypefun + +@deftypefun int mtx_lock (mtx_t* @var{mutex}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +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, and all lock/unlock operations on any given mutex +form a single total order (similar to the modification order of +an atomic). +@end deftypefun + +@deftypefun int mtx_timedlock (mtx_t *restrict @var{mutex}, const struct timespec *restrict @var{time_point}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Blocks the current thread until the mutex pointed to by @var{mutex} +is locked or until the TIME_UTC based time point pointed to +by @var{time_point} has been reached. +The behavior is undefined if the current thread has already +locked the mutex and the mutex is not recursive. +The behavior is undefined if the mutex does not support timeout. +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). +@end deftypefun + +@deftypefun int mtx_trylock (mtx_t *@var{mutex}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Tries to lock the mutex pointed to by @var{mutex} without blocking. +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). +@end deftypefun + +@deftypefun int mtx_unlock (mtx_t *@var{mutex}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Unlocks the mutex pointed to by @var{mutex}. The behavior is undefined +if the mutex is not locked by the calling thread. This function +synchronizes-with subsequent @code{mtx_lock}, @code{mtx_trylock}, +or @code{mtx_timedlock} 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). +@end deftypefun + +@deftypefun void mtx_destroy (mtx_t *@var{mutex}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Destroys the mutex pointed to by @var{mutex}. +If there are threads waiting on mutex, the behavior is undefined. +@end deftypefun + +@deftypefun void call_once (once_flag* @var{flag}, void (*@var{func})(void)) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +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 @var{flag} variable. +@end deftypefun + +The ISO C11 standard also defines several types of mutex that are +also supported. They are represented with symbolic constants +(enumeration type values) and are the following: + +@vtable @code + +@item mtx_plain +Mutex type that does not support timeout or test and return. + +@item mtx_recursive +Mutex type that supports recursive locking, what means that owner +thread can lock it twice or more without causing deadlock. + +@item mtx_timed +Mutex type that supports timeout. + +@end vtable + +@node Condition variable, Thread-local storage, Mutex, ISO Threads +@section Condition Variable + +Mutexes are not the only synchronization mechanisms available. For some +more complex tasks, @theglibc{} also implements condition variables, +that allow the user to think in a higher level to solve possible +mutual exclusion issues. + +@deftypefun int cnd_init (cnd_t* @var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Initializes new condition variable. The object pointed to by +@var{cond} will be set to value that identifies the condition variable. +@end deftypefun + +@deftypefun int cnd_signal (cnd_t *@var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Unblocks one thread that currently waits on condition variable +pointed to by @var{cond}. If no threads are blocked, does nothing and +returns @code{thrd_success}. +@end deftypefun + +@deftypefun int cnd_broadcast (cnd_t *@var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Unblocks all threads that currently wait on condition variable +pointed to by @var{cond}. If no threads are blocked, does nothing +and returns @code{thrd_success}. +@end deftypefun + +@deftypefun int cnd_wait (cnd_t* @var{cond}, mtx_t* @var{mutex}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +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}. The +mutex is locked again before the function returns. +@end deftypefun + +@deftypefun int cnd_timedwait (cnd_t* restrict @var{cond}, mtx_t* restrict @var{mutex}, const struct timespec* restrict @var{time_point}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +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}, or until the TIME_UTC based +time point pointed to by @var{time_point} has been reached. The mutex +is locked again before the function returns. +@end deftypefun + +@deftypefun void cnd_destroy (cnd_t* @var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Destroys the condition variable pointed to by @var{cond}. +If there are threads waiting on @var{cond}, the behavior is undefined. +@end deftypefun + +@node Thread-local storage, C11 error types, Condition variable, ISO Threads +@section Thread-local Storage + +@Theglibc{} also implements different functions that adds +funtionality for thread-local storage. That means that each thread can +have their own variables and are not visible by other threads. The +functions and types provided are: + +@deftypevr Macro {} thread_local +Used to mark a variable with thread storage duration, that means created +when the thread starts, and cleaned up when the thread ends. +@end deftypevr + +@deftypevr Macro {} ONCE_FLAG_INIT +Value established to initialize an object of type @code{once_call}. +@end deftypevr + +@deftypevr Macro {} TSS_DTOR_ITERATIONS +Integer constant expression representing the maximum number of +times that destructors will be called when a thread terminates. +@end deftypevr + +@deftypefun int tss_create (tss_t* @var{tss_key}, tss_dtor_t @var{destructor}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Creates 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. +@end deftypefun + +@deftypefun void *tss_get (tss_t @var{tss_key}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Returns the value held in thread-specific storage for the current +thread identified by @var{tss_key}. Different threads +may get different values identified by the same key. +@end deftypefun + +@deftypefun int tss_set (tss_t @var{tss_id}, void *@var{val}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Sets the value of the thread-specific storage identified by +@var{tss_id} for the current thread to @var{val}. Different threads +may set different values to the same key. +The destructor, if available, is not invoked. +@end deftypefun + +@deftypefun void tss_delete (tss_t @var{tss_id}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Destroys the thread-specific storage identified by @var{tss_id}. +The destructor, if one was registered by @code{tss_create}, is not +called +@end deftypefun + +@node C11 error types, , Thread-local storage, ISO Threads +@section Error Types + +The ISO C11 specification also provides new error types that belong +specifically to @code{threads.h}. @Theglibc{} has also implemented +this feature and every function in this API always returns one of the +following error codes: + + +@vtable @code + +@item thrd_timedout +Value returned by a function to indicate that a specified time was +reached without acquiring the requested resource, usually a mutex +or condition variable. + +@item thrd_sucess +Value returned by a function to indicate that the requested operation +succeded. + +@item thrd_busy +Value returned by a function to indicate that the requested operation +failed because a resource requested is already in use. + +@item thrd_error +Value returned by a function to indicate that the requested operation +failed. + +@item thrd_nomem +Value returned by a function to indicate that the requested operation +failed because it was unable to allocate enough memory. + +@end vtable
From: Juan Manuel Torres Palma <jmtorrespalma@gmail.com> This patch updates the manual and adds a new chapter to the manual, explaining types macros, constants and functions defined by ISO C11 threads.h standard. 2015-08-11 Juan Manuel Torres Palma <jmtorrespalma@gmail.com> * manual/Makefile (chapters): Add isothreads.texi. * manual/isothreads.texi: New file. Add new chapter for ISO C11 threads documentation. --- manual/Makefile | 3 +- manual/isothreads.texi | 326 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 manual/isothreads.texi