Message ID | 1506112024-22601-2-git-send-email-adhemerval.zanella@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Add support for ISO C threads.h | expand |
On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: > This patch adds the thrd_* definitions from C11 threads (ISO/IEC 9899:2011), > more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, > thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. > > Mostly of the definitions are composed based on POSIX conterparts, such as > thrd_t (using pthread_t). I have skimmed the C11 discussion of these types, and C11 says that mtx_t et al. are “identifiers”. To me, this suggests they are handles, just like pthread_t in the POSIX threads implementation. I'm sorry, but this would make the current implementation based on pthread types (without indirection) invalid. 8-( Thanks, Florian
On 15/11/2017 06:09, Florian Weimer wrote: > On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >> 9899:2011), >> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >> >> Mostly of the definitions are composed based on POSIX conterparts, >> such as >> thrd_t (using pthread_t). > > I have skimmed the C11 discussion of these types, and C11 says that > mtx_t et al. are “identifiers”. To me, this suggests they are > handles, just like pthread_t in the POSIX threads implementation. My understanding is "identifiers" follow the definition from C11 6.2.1 which does not exclude a tag/struct to represent it. A possible issue is POSIX has a model o flat address space that is shared between all thread while C standard makes it implementation defined (allowing for instance segmented address space or different vmas for hybrid computing). However I think C11 standard makes no amend to address it and although there is some suggestions [1] to add feature tests to handle it, it was no incorporated. [1] https://gustedt.wordpress.com/2012/10/14/c11-defects-c-threads-are-not-realizable-with-posix-threads/ > > I'm sorry, but this would make the current implementation based on > pthread types (without indirection) invalid. 8-( That is not my understanding. Could you point in C11 standard where identifier in thread.h definition exclude the use of tag types? > > Thanks, > Florian
On 11/15/2017 12:22 PM, Adhemerval Zanella wrote: > > > On 15/11/2017 06:09, Florian Weimer wrote: >> On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >>> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >>> 9899:2011), >>> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >>> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >>> >>> Mostly of the definitions are composed based on POSIX conterparts, >>> such as >>> thrd_t (using pthread_t). >> >> I have skimmed the C11 discussion of these types, and C11 says that >> mtx_t et al. are “identifiers”. To me, this suggests they are >> handles, just like pthread_t in the POSIX threads implementation. > My understanding is "identifiers" follow the definition from C11 6.2.1 > which does not exclude a tag/struct to represent it. I don't think “identifier” is used in this sense here. The standard says (7.2.6.1/4): “ The types are \begin{quote} \verb|cnd_t| \end{quote} which is a complete object type that holds an identifier for a condition variable; ” The “holds an identifier” suggests to me that this use of the term “identifier” does not refer to the C language construct. The definitions in ISO/IEC 2382:2015(en) do not seem to be applicable, either. The POSIX model assumes that the identity of a condition variable is determined by its address. This means that pthread_cond_t cannot hold an identifier, it is the thing itself, which means, among other things, that you cannot make a copy (e.g. using memcpy) and the copy will behave in the same way as the original, accessing the same condition variable. If something is just an identifier for something else, it strongly suggests to me that the underlying object is separate, and I can use a bit-wise identical identifier to reference the identical underlying object. Thanks, Florian
On 15/11/2017 10:03, Florian Weimer wrote: > On 11/15/2017 12:22 PM, Adhemerval Zanella wrote: >> >> >> On 15/11/2017 06:09, Florian Weimer wrote: >>> On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >>>> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >>>> 9899:2011), >>>> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >>>> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >>>> >>>> Mostly of the definitions are composed based on POSIX conterparts, >>>> such as >>>> thrd_t (using pthread_t). >>> >>> I have skimmed the C11 discussion of these types, and C11 says that >>> mtx_t et al. are “identifiers”. To me, this suggests they are >>> handles, just like pthread_t in the POSIX threads implementation. > >> My understanding is "identifiers" follow the definition from C11 6.2.1 >> which does not exclude a tag/struct to represent it. > > I don't think “identifier” is used in this sense here. > > The standard says (7.2.6.1/4): > > “ > The types are > \begin{quote} > \verb|cnd_t| > \end{quote} > which is a complete object type that holds an identifier for a > condition variable; > ” > > The “holds an identifier” suggests to me that this use of the term > “identifier” does not refer to the C language construct. The > definitions in ISO/IEC 2382:2015(en) do not seem to be applicable, > either. I find it quite inconsistent and improbable that the threads definition in C11 standard is using a defined vocabulary in a different meaning than the rest of document. > > The POSIX model assumes that the identity of a condition variable is > determined by its address. This means that pthread_cond_t cannot hold > an identifier, it is the thing itself, which means, among other > things, that you cannot make a copy (e.g. using memcpy) and the copy > will behave in the same way as the original, accessing the same > condition variable. > > If something is just an identifier for something else, it strongly > suggests to me that the underlying object is separate, and I can use a > bit-wise identical identifier to reference the identical underlying > object. My understanding is C11 threads standard does not create a tightly definition to try accommodate possible implementations where POSIX assumptions are not required or exercised. However I do not see that a more constrict implementation (based on POSIX for instance) is incompatible, the link I provided earlier is a suggestion to add features test to define which constraints are defined in the environment. Also the defined C11 threads API does not suggest me that the idea of the types are to point to a concrete identifier. For instance, to compare threads C11 does provide thrd_equal instead of relying of memcmp for the defined objects (as for bitwise underlying objects).
On 11/15/2017 01:43 PM, Adhemerval Zanella wrote: > > > On 15/11/2017 10:03, Florian Weimer wrote: >> On 11/15/2017 12:22 PM, Adhemerval Zanella wrote: >>> >>> >>> On 15/11/2017 06:09, Florian Weimer wrote: >>>> On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >>>>> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >>>>> 9899:2011), >>>>> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >>>>> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >>>>> >>>>> Mostly of the definitions are composed based on POSIX conterparts, >>>>> such as >>>>> thrd_t (using pthread_t). >>>> >>>> I have skimmed the C11 discussion of these types, and C11 says that >>>> mtx_t et al. are “identifiers”. To me, this suggests they are >>>> handles, just like pthread_t in the POSIX threads implementation. >> >>> My understanding is "identifiers" follow the definition from C11 6.2.1 >>> which does not exclude a tag/struct to represent it. >> >> I don't think “identifier” is used in this sense here. >> >> The standard says (7.2.6.1/4): >> >> “ >> The types are >> \begin{quote} >> \verb|cnd_t| >> \end{quote} >> which is a complete object type that holds an identifier for a >> condition variable; >> ” >> >> The “holds an identifier” suggests to me that this use of the term >> “identifier” does not refer to the C language construct. The >> definitions in ISO/IEC 2382:2015(en) do not seem to be applicable, >> either. > I find it quite inconsistent and improbable that the threads definition > in C11 > standard is using a defined vocabulary in a different meaning than the rest > of document. But how can a complete object *type* hold a C identifier? The language does not support that. We don't have call-by-name or anything like that. So this usage doesn't make sense to me, so I assume that something else is meant here. I'm trying to get access to the WG papers on which the text is based. Maybe those illuminate what is meant here. Thanks, Florian
On 15/11/2017 10:49, Florian Weimer wrote: > On 11/15/2017 01:43 PM, Adhemerval Zanella wrote: >> >> >> On 15/11/2017 10:03, Florian Weimer wrote: >>> On 11/15/2017 12:22 PM, Adhemerval Zanella wrote: >>>> >>>> >>>> On 15/11/2017 06:09, Florian Weimer wrote: >>>>> On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >>>>>> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >>>>>> 9899:2011), >>>>>> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >>>>>> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >>>>>> >>>>>> Mostly of the definitions are composed based on POSIX conterparts, >>>>>> such as >>>>>> thrd_t (using pthread_t). >>>>> >>>>> I have skimmed the C11 discussion of these types, and C11 says that >>>>> mtx_t et al. are “identifiers”. To me, this suggests they are >>>>> handles, just like pthread_t in the POSIX threads implementation. >>> >>>> My understanding is "identifiers" follow the definition from C11 6.2.1 >>>> which does not exclude a tag/struct to represent it. >>> >>> I don't think “identifier” is used in this sense here. >>> >>> The standard says (7.2.6.1/4): >>> >>> “ >>> The types are >>> \begin{quote} >>> \verb|cnd_t| >>> \end{quote} >>> which is a complete object type that holds an identifier for a >>> condition variable; >>> ” >>> >>> The “holds an identifier” suggests to me that this use of the term >>> “identifier” does not refer to the C language construct. The >>> definitions in ISO/IEC 2382:2015(en) do not seem to be applicable, >>> either. > >> I find it quite inconsistent and improbable that the threads definition >> in C11 >> standard is using a defined vocabulary in a different meaning than the rest >> of document. > > But how can a complete object *type* hold a C identifier? The language does not support that. We don't have call-by-name or anything like that. Why do we need call-by-name to provide a complete identifier for C11 mtx_t type? My understanding is we have the init functions to initialize the objects and C11 threads avoid static initializers. > > So this usage doesn't make sense to me, so I assume that something else is meant here. > > I'm trying to get access to the WG papers on which the text is based. Maybe those illuminate what is meant here. Similar objections were already raised in DR#493 [1], more specifically for "1. What is the behavior of mtx_init() when called with a pointer to an object initialized to all zeros (such as a mutex object with static storage duration)? Are such calls valid, or if not, must the function fail by returning thrd_error, or is its behavior unspecified, or perhaps undefined? (If it is the same as calling it on an uninitialized object then how does one statically initialize a mutex?)" The committee discussion for this specific topic is aiming for: "Problems with mtx_t The semantics of copying a mtx_t are not specified, much like FILE §7.21.3p6." [1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_493
On 11/15/2017 02:21 PM, Adhemerval Zanella wrote: > > > On 15/11/2017 10:49, Florian Weimer wrote: >> On 11/15/2017 01:43 PM, Adhemerval Zanella wrote: >>> >>> >>> On 15/11/2017 10:03, Florian Weimer wrote: >>>> On 11/15/2017 12:22 PM, Adhemerval Zanella wrote: >>>>> >>>>> >>>>> On 15/11/2017 06:09, Florian Weimer wrote: >>>>>> On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >>>>>>> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >>>>>>> 9899:2011), >>>>>>> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >>>>>>> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >>>>>>> >>>>>>> Mostly of the definitions are composed based on POSIX conterparts, >>>>>>> such as >>>>>>> thrd_t (using pthread_t). >>>>>> >>>>>> I have skimmed the C11 discussion of these types, and C11 says that >>>>>> mtx_t et al. are “identifiers”. To me, this suggests they are >>>>>> handles, just like pthread_t in the POSIX threads implementation. >>>> >>>>> My understanding is "identifiers" follow the definition from C11 6.2.1 >>>>> which does not exclude a tag/struct to represent it. >>>> >>>> I don't think “identifier” is used in this sense here. >>>> >>>> The standard says (7.2.6.1/4): >>>> >>>> “ >>>> The types are >>>> \begin{quote} >>>> \verb|cnd_t| >>>> \end{quote} >>>> which is a complete object type that holds an identifier for a >>>> condition variable; >>>> ” >>>> >>>> The “holds an identifier” suggests to me that this use of the term >>>> “identifier” does not refer to the C language construct. The >>>> definitions in ISO/IEC 2382:2015(en) do not seem to be applicable, >>>> either. >> >>> I find it quite inconsistent and improbable that the threads definition >>> in C11 >>> standard is using a defined vocabulary in a different meaning than the rest >>> of document. >> >> But how can a complete object *type* hold a C identifier? The language does not support that. We don't have call-by-name or anything like that. > > Why do we need call-by-name to provide a complete identifier for C11 mtx_t > type? My understanding is we have the init functions to initialize the > objects and C11 threads avoid static initializers. I read “holds” as “stores” in this context, as in: “ \begin{quote} \verb|struct timespec| \end{quote} which holds an interval specified in seconds and nanoseconds ” I think using this wording in the context of identifiers is extremely sloppy because an object cannot store an identifier. I would have expected language like this if indirection is not required: “ The types are \begin{quote} \verb|cnd_t| \end{quote} which denotes a complete object type which holds a condition variable; ” >> So this usage doesn't make sense to me, so I assume that something else is meant here. >> >> I'm trying to get access to the WG papers on which the text is based. Maybe those illuminate what is meant here. > > > Similar objections were already raised in DR#493 [1], more specifically for > > "1. What is the behavior of mtx_init() when called with a pointer to an object > initialized to all zeros (such as a mutex object with static storage duration)? > Are such calls valid, or if not, must the function fail by returning thrd_error, > or is its behavior unspecified, or perhaps undefined? (If it is the same as > calling it on an uninitialized object then how does one statically initialize a > mutex?)" > > The committee discussion for this specific topic is aiming for: > > "Problems with mtx_t > > The semantics of copying a mtx_t are not specified, much like FILE §7.21.3p6." > > [1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_493 Oh, this and the rest of the committee response assumes that the synchronization objects are not just identifiers. I really wish this was specified more explicitly. So my concerns are apparently not shared by the committee. Thanks, Florian
On 15/11/2017 11:35, Florian Weimer wrote: > On 11/15/2017 02:21 PM, Adhemerval Zanella wrote: >> >> >> On 15/11/2017 10:49, Florian Weimer wrote: >>> On 11/15/2017 01:43 PM, Adhemerval Zanella wrote: >>>> >>>> >>>> On 15/11/2017 10:03, Florian Weimer wrote: >>>>> On 11/15/2017 12:22 PM, Adhemerval Zanella wrote: >>>>>> >>>>>> >>>>>> On 15/11/2017 06:09, Florian Weimer wrote: >>>>>>> On 09/22/2017 10:26 PM, Adhemerval Zanella wrote: >>>>>>>> This patch adds the thrd_* definitions from C11 threads (ISO/IEC >>>>>>>> 9899:2011), >>>>>>>> more specifically thrd_create, thrd_curent, rhd_detach, thrd_equal, >>>>>>>> thrd_exit, thrd_join, thrd_sleep, thrd_yield, and required types. >>>>>>>> >>>>>>>> Mostly of the definitions are composed based on POSIX conterparts, >>>>>>>> such as >>>>>>>> thrd_t (using pthread_t). >>>>>>> >>>>>>> I have skimmed the C11 discussion of these types, and C11 says that >>>>>>> mtx_t et al. are “identifiers”. To me, this suggests they are >>>>>>> handles, just like pthread_t in the POSIX threads implementation. >>>>> >>>>>> My understanding is "identifiers" follow the definition from C11 6.2.1 >>>>>> which does not exclude a tag/struct to represent it. >>>>> >>>>> I don't think “identifier” is used in this sense here. >>>>> >>>>> The standard says (7.2.6.1/4): >>>>> >>>>> “ >>>>> The types are >>>>> \begin{quote} >>>>> \verb|cnd_t| >>>>> \end{quote} >>>>> which is a complete object type that holds an identifier for a >>>>> condition variable; >>>>> ” >>>>> >>>>> The “holds an identifier” suggests to me that this use of the term >>>>> “identifier” does not refer to the C language construct. The >>>>> definitions in ISO/IEC 2382:2015(en) do not seem to be applicable, >>>>> either. >>> >>>> I find it quite inconsistent and improbable that the threads definition >>>> in C11 >>>> standard is using a defined vocabulary in a different meaning than the rest >>>> of document. >>> >>> But how can a complete object *type* hold a C identifier? The language does not support that. We don't have call-by-name or anything like that. >> >> Why do we need call-by-name to provide a complete identifier for C11 mtx_t >> type? My understanding is we have the init functions to initialize the >> objects and C11 threads avoid static initializers. > > I read “holds” as “stores” in this context, as in: > > “ > \begin{quote} > \verb|struct timespec| > \end{quote} > which holds an interval specified in seconds and nanoseconds > ” > > I think using this wording in the context of identifiers is extremely sloppy because an object cannot store an identifier. > > I would have expected language like this if indirection is not required: > > “ > The types are > \begin{quote} > \verb|cnd_t| > \end{quote} > which denotes a complete object type which holds a condition variable; > ” > I agree with you the wording could be more carefully picked in this case, but the DR for C11 threads also points to a description you put. >>> So this usage doesn't make sense to me, so I assume that something else is meant here. >>> >>> I'm trying to get access to the WG papers on which the text is based. Maybe those illuminate what is meant here. >> >> >> Similar objections were already raised in DR#493 [1], more specifically for >> >> "1. What is the behavior of mtx_init() when called with a pointer to an object >> initialized to all zeros (such as a mutex object with static storage duration)? >> Are such calls valid, or if not, must the function fail by returning thrd_error, >> or is its behavior unspecified, or perhaps undefined? (If it is the same as >> calling it on an uninitialized object then how does one statically initialize a >> mutex?)" >> >> The committee discussion for this specific topic is aiming for: >> >> "Problems with mtx_t >> >> The semantics of copying a mtx_t are not specified, much like FILE §7.21.3p6." >> >> [1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_493 > > Oh, this and the rest of the committee response assumes that the synchronization objects are not just identifiers. I really wish this was specified more explicitly. > > So my concerns are apparently not shared by the committee. We had some discussion back in v3 about the opened DR for C11 threads [1]. I has the assumption we had no block back then regarding base glibc implementation on underlying POSIX one. [1] https://sourceware.org/ml/libc-alpha/2017-03/msg00461.html
On 11/15/2017 04:46 PM, Adhemerval Zanella wrote: > We had some discussion back in v3 about the opened DR for C11 threads [1]. > I has the assumption we had no block back then regarding base glibc > implementation on underlying POSIX one. I just want to minimize the risk that we implement something which is clearly incompatible with the standard. But it seems that at least as far as the handle matter is concerned, the standard doesn't say what it means, and a non-handle implementation would be conforming, so that shouldn't be a problem for us. Thanks, Florian
diff --git a/conform/Makefile b/conform/Makefile index 3883a4b..9e00d41 100644 --- a/conform/Makefile +++ b/conform/Makefile @@ -34,9 +34,9 @@ conformtest-headers-ISO := assert.h ctype.h errno.h float.h limits.h locale.h \ conformtest-headers-ISO99 := $(conformtest-headers-ISO) complex.h fenv.h \ inttypes.h iso646.h stdbool.h stdint.h tgmath.h \ wchar.h wctype.h -# Missing ISO11 expectations for: stdatomic.h threads.h. +# Missing ISO11 expectations for: stdatomic.h conformtest-headers-ISO11 := $(conformtest-headers-ISO99) stdalign.h \ - stdnoreturn.h uchar.h + stdnoreturn.h threads.h uchar.h conformtest-headers-POSIX := $(conformtest-headers-ISO) aio.h dirent.h \ fcntl.h fnmatch.h glob.h grp.h mqueue.h \ pthread.h pwd.h regex.h sched.h semaphore.h \ @@ -197,7 +197,8 @@ linknamespace-libs-xsi = $(linknamespace-libs-posix) \ $(common-objpfx)crypt/libcrypt.a linknamespace-libs-ISO = $(linknamespace-libs-isoc) linknamespace-libs-ISO99 = $(linknamespace-libs-isoc) -linknamespace-libs-ISO11 = $(linknamespace-libs-isoc) +linknamespace-libs-ISO11 = $(linknamespace-libs-isoc) \ + $(common-objpfx)nptl/libpthread.a linknamespace-libs-XPG4 = $(linknamespace-libs-isoc) \ $(common-objpfx)crypt/libcrypt.a linknamespace-libs-XPG42 = $(linknamespace-libs-XPG4) diff --git a/conform/data/threads.h-data b/conform/data/threads.h-data new file mode 100644 index 0000000..bc2d857 --- /dev/null +++ b/conform/data/threads.h-data @@ -0,0 +1,23 @@ +#if defined ISO11 + +constant thrd_success +constant thrd_busy +constant thrd_error +constant thrd_nomem +constant thrd_timedout + +type thrd_t +type thrd_start_t + +function int thrd_create (thrd_t*, thrd_start_t, void*) +function int thrd_equal (thrd_t, thrd_t) +function thrd_t thrd_current (void) +function int thrd_sleep (const struct timespec*, struct timespec*) +function void thrd_exit (int) +function int thrd_detach (thrd_t) +function int thrd_join (thrd_t, int*) +function void thrd_yield (void) + +#include "time.h-data" + +#endif diff --git a/include/stdc-predef.h b/include/stdc-predef.h index 74ade90..1cd3d73 100644 --- a/include/stdc-predef.h +++ b/include/stdc-predef.h @@ -57,7 +57,4 @@ - 3 additional Zanabazar Square characters */ #define __STDC_ISO_10646__ 201706L -/* We do not support C11 <threads.h>. */ -#define __STDC_NO_THREADS__ 1 - #endif diff --git a/nptl/Makefile b/nptl/Makefile index d819349..31761a6 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -22,7 +22,7 @@ subdir := nptl include ../Makeconfig -headers := pthread.h semaphore.h bits/semaphore.h +headers := pthread.h semaphore.h bits/semaphore.h threads.h extra-libs := libpthread extra-libs-others := $(extra-libs) @@ -138,7 +138,9 @@ libpthread-routines = nptl-init vars events version pt-interp \ pthread_mutex_getprioceiling \ pthread_mutex_setprioceiling \ pthread_setname pthread_getname \ - pthread_setattr_default_np pthread_getattr_default_np + pthread_setattr_default_np pthread_getattr_default_np \ + thrd_create thrd_current thrd_detach thrd_equal \ + thrd_exit thrd_join thrd_sleep thrd_yield # pthread_setuid pthread_seteuid pthread_setreuid \ # pthread_setresuid \ # pthread_setgid pthread_setegid pthread_setregid \ diff --git a/nptl/Versions b/nptl/Versions index 0ae5def..a282ceb 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -265,6 +265,12 @@ libpthread { GLIBC_2.22 { } + # C11 thread symbols. + GLIBC_2.27 { + thrd_create; thrd_current; thrd_detach; thrd_equal; thrd_exit; thrd_join; + thrd_sleep; thrd_yield; + } + GLIBC_PRIVATE { __pthread_initialize_minimal; __pthread_clock_gettime; __pthread_clock_settime; diff --git a/nptl/descr.h b/nptl/descr.h index c5ad0c8..c1ff711 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -371,6 +371,8 @@ struct pthread to the function. */ void *(*start_routine) (void *); void *arg; + /* Indicates whether is a C11 thread created by thrd_creat. */ + bool c11; /* Debug state. */ td_eventbuf_t eventbuf; diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index dbf46b0..ded7547 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -173,6 +173,9 @@ enum #define __PTHREAD_ONCE_DONE 2 #define __PTHREAD_ONCE_FORK_GEN_INCR 4 +/* Attribute to indicate thread creation was issued from C11 thrd_create. */ +#define ATTR_C11_THREAD ((void*)(uintptr_t)-1) + /* Condition variable definitions. See __pthread_cond_wait_common. Need to be defined here so there is one place from which diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 992331e..bef3042 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -460,7 +460,19 @@ START_THREAD_DEFN LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg); /* Run the code the user provided. */ - THREAD_SETMEM (pd, result, pd->start_routine (pd->arg)); + void *ret; + if (pd->c11) + { + /* The function pointer of the c11 thread start is cast to an incorrect + type on __pthread_create_2_1 call, however it is casted back to correct + one so the call behavior is well-defined (it is assumed that pointers + to void are able to represent all values of int. */ + int (*start)(void*) = (int (*) (void*)) pd->start_routine; + ret = (void*) (intptr_t) start (pd->arg); + } + else + ret = pd->start_routine (pd->arg); + THREAD_SETMEM (pd, result, ret); } /* Call destructors for the thread_local TLS variables. */ @@ -613,7 +625,8 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, const struct pthread_attr *iattr = (struct pthread_attr *) attr; struct pthread_attr default_attr; bool free_cpuset = false; - if (iattr == NULL) + bool c11 = (attr == ATTR_C11_THREAD); + if (iattr == NULL || c11) { lll_lock (__default_pthread_attr_lock, LLL_PRIVATE); default_attr = __default_pthread_attr; @@ -671,6 +684,7 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, get the information from its thread descriptor. */ pd->start_routine = start_routine; pd->arg = arg; + pd->c11 = c11; /* Copy the thread attribute flags. */ struct pthread *self = THREAD_SELF; diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c new file mode 100644 index 0000000..0b6b822 --- /dev/null +++ b/nptl/thrd_create.c @@ -0,0 +1,32 @@ +/* C11 threads thread creation implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Create a new thread executing the function func. Arguments to func + are passed through arg. If succesful, thr is set to new thread + identifier. */ +int +thrd_create (thrd_t *thr, thrd_start_t func, void *arg) +{ + _Static_assert (sizeof (thr) == sizeof (pthread_t), "thrd_t size"); + + int err_code = __pthread_create_2_1 (thr, ATTR_C11_THREAD, + (void* (*) (void*))func, arg); + return thrd_err_map (err_code); +} diff --git a/nptl/thrd_current.c b/nptl/thrd_current.c new file mode 100644 index 0000000..7269d4b --- /dev/null +++ b/nptl/thrd_current.c @@ -0,0 +1,26 @@ +/* C11 threads current thread implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Return current thread identifier. */ +thrd_t +thrd_current (void) +{ + return __pthread_self (); +} diff --git a/nptl/thrd_detach.c b/nptl/thrd_detach.c new file mode 100644 index 0000000..187d078 --- /dev/null +++ b/nptl/thrd_detach.c @@ -0,0 +1,30 @@ +/* C11 threads thread detach implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Detache the thread identified by thr from the current environment. + It does not allow join or wait for the thread. */ +int +thrd_detach (thrd_t thr) +{ + int err_code; + + err_code = __pthread_detach (thr); + return thrd_err_map (err_code); +} diff --git a/nptl/thrd_equal.c b/nptl/thrd_equal.c new file mode 100644 index 0000000..fcda488 --- /dev/null +++ b/nptl/thrd_equal.c @@ -0,0 +1,26 @@ +/* C11 threads thread equality check implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Check if lhs and rhs point to the same thread. */ +int +thrd_equal (thrd_t lhs, thrd_t rhs) +{ + return __pthread_equal (lhs, rhs); +} diff --git a/nptl/thrd_exit.c b/nptl/thrd_exit.c new file mode 100644 index 0000000..a49d8e0 --- /dev/null +++ b/nptl/thrd_exit.c @@ -0,0 +1,27 @@ +/* C11 threads thread exit implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Terminate current thread execution, cleaning up any thread local + storage and freeing resources. Returns the value specified in res. */ +_Noreturn void +thrd_exit (int res) +{ + __pthread_exit ((void*)(uintptr_t) res); +} diff --git a/nptl/thrd_join.c b/nptl/thrd_join.c new file mode 100644 index 0000000..1d69918 --- /dev/null +++ b/nptl/thrd_join.c @@ -0,0 +1,32 @@ +/* C11 threads thread join implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Block current thread until execution of thr is complete. In case that + res is not NULL, will store the return value of thr when exiting. */ +int +thrd_join (thrd_t thr, int *res) +{ + void *pthread_res; + int err_code = __pthread_join (thr, &pthread_res); + if (res) + *res = (int)((uintptr_t) pthread_res); + + return thrd_err_map (err_code); +} diff --git a/nptl/thrd_priv.h b/nptl/thrd_priv.h new file mode 100644 index 0000000..a431d60 --- /dev/null +++ b/nptl/thrd_priv.h @@ -0,0 +1,46 @@ +/* Internal C11 threads definitions. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef THRD_PRIV_H +# define THRD_PRIV_H + +#include <features.h> +#include <threads.h> +#include <errno.h> +#include "pthreadP.h" /* For pthread_{mutex,cond}_t definitions. */ + +/* Maps pthread error codes with thrd error codes. */ +static __always_inline int +thrd_err_map (int err_code) +{ + switch (err_code) + { + case 0: + return thrd_success; + case ENOMEM: + return thrd_nomem; + case ETIMEDOUT: + return thrd_timedout; + case EBUSY: + return thrd_busy; + default: + return thrd_error; + } +} + +#endif diff --git a/nptl/thrd_sleep.c b/nptl/thrd_sleep.c new file mode 100644 index 0000000..a49fdc4 --- /dev/null +++ b/nptl/thrd_sleep.c @@ -0,0 +1,41 @@ +/* C11 threads thread sleep implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" +#include <time.h> + +/* Block current thread execution for at least the time pointed by time_point. + The current thread may resume if receives a signal. In that case, if + remaining is not NULL, the remaining time is stored in the object pointed + by it. */ +int +thrd_sleep (const struct timespec* time_point, struct timespec* remaining) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL_CALL (nanosleep, err, time_point, remaining); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + { + /* C11 states thrd_sleep function returns -1 if it has been interrupted + by a signal, or a negative value if it fails. */ + ret = INTERNAL_SYSCALL_ERRNO (ret, err); + if (ret == EINTR) + return -1; + return -2; + } + return 0; +} diff --git a/nptl/thrd_yield.c b/nptl/thrd_yield.c new file mode 100644 index 0000000..13a02f3 --- /dev/null +++ b/nptl/thrd_yield.c @@ -0,0 +1,29 @@ +/* C11 threads thread yield implementation. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "thrd_priv.h" + +/* Stop current thread execution and call the scheduler to decide which + thread should execute next. The current thread may be selected by the + scheduler to keep running. */ +void +thrd_yield (void) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL_CALL (sched_yield, err); +} diff --git a/sysdeps/nptl/threads.h b/sysdeps/nptl/threads.h new file mode 100644 index 0000000..4b89a30 --- /dev/null +++ b/sysdeps/nptl/threads.h @@ -0,0 +1,90 @@ +/* ISO C11 Standard: 7.26 - Thread support library <threads.h>. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _THREADS_H +#define _THREADS_H 1 + +#include <features.h> +#include <time.h> + +__BEGIN_DECLS + +#include <bits/types/struct_timespec.h> + +typedef unsigned long int thrd_t; +typedef int (*thrd_start_t) (void*); + +/* Exit and error codes. */ +enum +{ + thrd_success = 0, + thrd_busy = 1, + thrd_error = 2, + thrd_nomem = 3, + thrd_timedout = 4 +}; + +/* Threads functions. */ + +/* Create a new thread executing the function __func. Arguments to __func + are passed through __arg. If succesful, __thr is set to new thread + identifier. */ +extern int thrd_create (thrd_t *__thr, thrd_start_t __func, void *__arg); + +/* Check if __lhs and __rhs point to the same thread. */ +extern int thrd_equal (thrd_t __lhs, thrd_t __rhs); + +/* Return current thread identifier. */ +extern thrd_t thrd_current (void); + +/* Block current thread execution for at least the time pointed by + __time_point. The current thread may resume if receives a signal. In + that case, if __remaining is not NULL, the remaining time is stored in + the object pointed by it. */ +extern int thrd_sleep (const struct timespec *__time_point, + struct timespec *__remaining); + +/* Terminate current thread execution, cleaning up any thread local + storage and freeing resources. Returns the value specified in __res. */ +extern void thrd_exit (int __res) __attribute__ ((__noreturn__)); + +/* Detache the thread identified by __thr from the current environment. + It does not allow join or wait for __thr. */ +extern int thrd_detach (thrd_t __thr); + +/* Block current thread until execution of __thr is complete. In case that + __res is not NULL, will store the return value of __thr when exiting. */ +extern int thrd_join (thrd_t __thr, int *__res); + +/* Stop current thread execution and call the scheduler to decide which + thread should execute next. The current thread may be selected by the + scheduler to keep running. */ +extern void thrd_yield (void); + +#ifdef __USE_EXTERN_INLINES +/* Optimizations. */ +__extern_inline int +thrd_equal (thrd_t __thread1, thrd_t __thread2) +{ + return __thread1 == __thread2; +} +#endif + +__END_DECLS + +#endif /* _THREADS_H */