From patchwork Fri Feb 2 17:04:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 126759 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp819722ljc; Fri, 2 Feb 2018 09:06:18 -0800 (PST) X-Google-Smtp-Source: AH8x227S77EE5IU6c/rrQvkMPzVcUz20YQz6+wopM5bfdWM8rBYuCj+5tT1f9jNJCyrTOf36KZf1 X-Received: by 10.98.102.135 with SMTP id s7mr40207740pfj.209.1517591178192; Fri, 02 Feb 2018 09:06:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517591178; cv=none; d=google.com; s=arc-20160816; b=VEvqt+aGB/m9puptql5BkscyowhpWF9217n3K3oL21Q6+o1NE6r/DAwcA78IBIpzRC 7Op81SCmX79ZYFMqkDhlaqQ+PegyusZU4TWzrmFVHqXZedEEl2V8nqMfmjvra+g8Dhl8 BvHr6C7Sfab5GoL5xSyJ0b/Ci3zAvkUElymMiSKDNRqbrioZZbq5g8BtvzZY+hMGOLCO +G0JOVYaH15QETHBDMxgBFQ3mI78ZlbqUT2EnX5EH5D1nuYq9ayWaYCAUMtHHZFmoU5t hVb1Bm9V4MJXoPEQ1gonpuFHGRRFSryr2ImYxAdELRu42LLFe0OeSI017+MIEJmYqUgz 7D/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :delivered-to:sender:list-help:list-post:list-archive:list-subscribe :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature:arc-authentication-results; bh=UqU2WYVs8kwNgeeYof6gRLbqE6Qq9WdWbqlAKeF9tJM=; b=b47FYI81+8xTimGKCCuGovZ8ufYTovvQ7UkuxTWlW2najZFEmX6ikeSgENgo9+zqcm JKyugluQhNp6ZSczBl6C0Nlxow/HGJJpV//KJ//DF9JGefczYwxmAS6h6zcwO8Y+L9Xk gay1Rb+vLcQdlfFxSEkma/NWypC3+45LH449EQuoHciY604/neFdj2AMChRAWxcFDikZ K8o7U4p5v1W1N7RQiNUb3GrgwPEgVdLaRbX7DVh3Kf+rc5zCGdyg+T4TaBG1sKnTwr+0 xbjkfeTFj0jsvb0ulH+5KGI24nHiuIsMgpvB/yhBhQ0WGoIOvhFhIHJJT7w2nA+0XYaD ighg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=W36hYduP; spf=pass (google.com: domain of libc-alpha-return-89927-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-89927-patch=linaro.org@sourceware.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id e27si2154881pfk.172.2018.02.02.09.06.17 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Feb 2018 09:06:18 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-89927-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=W36hYduP; spf=pass (google.com: domain of libc-alpha-return-89927-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-89927-patch=linaro.org@sourceware.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=msUJvCmNXG88eR07EIivgqNqZZ10EYw eWURA6fqYcr98z4+mWJmZAoyD1i4zLdAddZpdWd9K0sauKqrSqzrVYPIE428tqCM tarohyRePUK9OULTERV/uakjOZv3eMhWTteR35Reof0m2AWNQ5/w9XlET3AAjkQr s44SiB0P9QkY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; s=default; bh=mb4pIbVpM6dH7+diunHo0ZZEv/o=; b=W36hY duPOmtYR3P4Uw0l97mfc/+GBxulXhSm7Q6e+6WH65PMxIJnNrn7s5orW7NzwZ6WJ XgO1baR/5gcseKLnIp6UUCXALqPM2YytRKXckjmdIKpcXdaRX4AUqQiyJ9yTXALJ eNAvUlcRpdrDw5c1tmgfwOHh0KLd/MvxATx2qM= Received: (qmail 130420 invoked by alias); 2 Feb 2018 17:05:13 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 130299 invoked by uid 89); 2 Feb 2018 17:05:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Juan, mutual, acquiring, threadspecific X-HELO: mail-qt0-f175.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UqU2WYVs8kwNgeeYof6gRLbqE6Qq9WdWbqlAKeF9tJM=; b=F4c46jchc3afApZ2L8gH9v4lpX1jPFQO1LCDY28bdJsm69BdeF1ulKDE4cpNjTLBy7 xjG2E0LYIfBdN8OZqBe4aMnqAdXD4vG9ALB8epOpJEWOica5f36sfz9s1u8+qhi7nLqd WyP4cOeldIwI8U2fmND/44x6bCw7TidVOcpI1c9mvu9VmKxHK4nH3RxYCcvxK1D/i6Ro eID6dMigAgzQFInLsFi54B3mg4FYimzBDKhEe0iVKRHHe0lFjWIooelClZuQ343QRWcT jXDe0pcbn5YTv0PP9igaaMoVsOnof/IBVek9P/gysGd4ApZOAv+myOn2RHJz0yx1wOAC q7Ug== X-Gm-Message-State: APf1xPAHq2s4a7xyEnbfU7zIv/selbv1suZ+dhJHY8viy13cCZRSeLAY y0/BXYDpyD68Bkicevdf6J/fOvHasw4= X-Received: by 10.200.4.148 with SMTP id s20mr459111qtg.144.1517591105148; Fri, 02 Feb 2018 09:05:05 -0800 (PST) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Juan Manuel Torres Palma Subject: [PATCH v8 8/8] Add manual documentation for threads.h Date: Fri, 2 Feb 2018 15:04:44 -0200 Message-Id: <1517591084-11347-9-git-send-email-adhemerval.zanella@linaro.org> In-Reply-To: <1517591084-11347-1-git-send-email-adhemerval.zanella@linaro.org> References: <1517591084-11347-1-git-send-email-adhemerval.zanella@linaro.org> From: Juan Manuel Torres Palma 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. * manual/Makefile (chapters): Add isothreads.texi. * manual/isothreads.texi: New file. Add new chapter for ISO C11 threads documentation. --- ChangeLog | 4 + manual/Makefile | 2 +- manual/isothreads.texi | 355 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+), 1 deletion(-) create mode 100644 manual/isothreads.texi -- 2.7.4 diff --git a/manual/Makefile b/manual/Makefile index c275664..7fb64d7 100644 --- a/manual/Makefile +++ b/manual/Makefile @@ -39,7 +39,7 @@ chapters = $(addsuffix .texi, \ pipe socket terminal syslog math arith time \ resource setjmp signal startup process ipc job \ nss users sysinfo conf crypt debug threads \ - probes tunables) + probes tunables isothreads) appendices = lang.texi header.texi install.texi maint.texi platform.texi \ contrib.texi licenses = freemanuals.texi lgpl-2.1.texi fdl-1.3.texi diff --git a/manual/isothreads.texi b/manual/isothreads.texi new file mode 100644 index 0000000..bcdf127 --- /dev/null +++ b/manual/isothreads.texi @@ -0,0 +1,355 @@ +@node ISO Threads, , , Top +@chapter ISO C11 threads + +This chapter describes @theglibc{} ISO C11 threads implementation. +To have a deeper understanding of this API, is strongly recomended +to read ISO/IEC 9899:2011, section 7.26 where ISO C11 threads +are specified. +All types and function prototypes are declared in +@file{threads.h} header. +@pindex threads.h + +@menu +* Thread Creation and Control:: Support for basic threading. +* Call Once:: Single call macros and functions. +* Mutex:: Low level mechanism for mutual exclusion. +* Condition variable:: High level objects for thread synchronization. +* Thread-local storage:: Functions to support thread-local storage. +* C11 error types:: Symbolic constants that represent functions return value. +@end menu + +@node Thread Creation and Control, Call Once, , ISO Threads +@section Thread Creation and Control + +@Theglibc{} implements a set of functions that allow 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 object that identifies a thread unequivocally. +@end deftp + +@deftp {Data Type} {thrd_start_t} +It is a (@code{int (*)(void *)}) typedef 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 set 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 wall-clock +time point 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. + +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}. +If this function is called from a single thread process, the call to this +function is equivalent to @code{exit(0)}. Returning from a thread-start +function is equivalent to calling @code{thrd_exit}. +@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 control thread. +The resources held by the thread will be freed automatically once the thread +exits. The parent thread will never be notified by any @var{thr} signal. +@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 Call Once, Mutex, Thread Creation and Control, ISO Threads +@section Call Once + +In order to guarantee single access to a function, @theglibc implements a call +once function to allow unique access in case a function is required to be +called only once in presence of several threads. + +@deftp {Data Type} {once_flag} +Complete object type capable of holding a flag used by @code{call_once} +@end deftp + +@deftypevr Macro {} ONCE_FLAG_INIT +Value established to initialize an object of type @code{once_flag}. +@end deftypevr + +@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 + +@node Mutex, Condition variable, Call Once, 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. + +@deftp {Data Type} {mtx_t} +Mutex object identifier. +@end deftp + +@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{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} 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{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} +Blocks the current thread until the mutex pointed to by @var{mutex} is locked +or until the wall-clock time pointed to by @var{time_point} has been reached. +This function takes an absolute time, so if a duration is required, must be +calculated manually and passed to this function. + +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{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} +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 + +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 conditional variables, that allow +the user to think in a higher level to solve complex synchronization problems. +They are used to synchronize threads waiting on a certain condition to happen. + +@deftp {Data Type} {cnd_t} +Condition variable object identifier. +@end deftp + +@deftypefun int cnd_init (cnd_t *@var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Initializes new conditional variable. The object pointed to by @var{cond} +will be set to value that identifies the conditional variable. +@end deftypefun + +@deftypefun int cnd_signal (cnd_t *@var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Unblocks one thread that currently waits on conditional 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 conditional 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{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} +Atomically unlocks the mutex pointed to by @var{mutex} and blocks on the +conditional 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{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}} +Atomically unlocks the mutex pointed to by @var{mutex} and blocks on the +conditional variable pointed to by @var{cond} until the thread is signalled +by @code{cnd_signal} or @code{cnd_broadcast}, or until the wall-clock time +pointed to by @var{time_point} has been reached. The mutex is locked again +before the function returns. +As for @code{mtx_timedlock}, this function also takes an absolute time +rather than a duration. +@end deftypefun + +@deftypefun void cnd_destroy (cnd_t *@var{cond}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +Destroys the conditional 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: + +@deftp {Data Type} {tss_t} +Thread-specific storage object. Even if shared, every thread will have +its own instance of that variable with different values. +@end deftp + +@deftp {Data Type} {tss_dtor_t} +Function pointer of type @code{void(*)(void*)}, used for TSS destructor. +This function will be called when the current thread calls @code{thrd_exit}, +but never when calling @code{tss_delete} or @code{exit} +@end deftp + +@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 {} 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. + +If @var{destructor} is different to NULL, a destructor function will be set, +and called when the thread finishes its execution by calling @code{thrd_exit}. +@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 conditional +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