summaryrefslogtreecommitdiff
path: root/nptl/pthread_create.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-06-27 10:29:29 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2018-07-24 14:06:45 -0300
commitce7528f637f7b9cddb3c22081d7e09b2a26c89bf (patch)
tree96263946f49c1ac25f61ee9aeebd3b0e34fd5036 /nptl/pthread_create.c
parente27f41ba2b6101be1a511905bff5502ffd23828b (diff)
nptl: Add C11 threads thrd_* functions
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). For thrd_* function internally direct POSIX pthread call are used with the exceptions: 1. thrd_start uses pthread_create internal implementation, but changes how to actually calls the start routine. This is due the difference in signature between POSIX and C11, where former return a 'void *' and latter 'int'. To avoid calling convention issues due 'void *' to int cast, routines from C11 threads are started slight different than default pthread one. Explicit cast to expected return are used internally on pthread_create and the result is stored back to void also with an explicit cast. 2. thrd_sleep uses nanosleep internal direct syscall to avoid clobbering errno and to handle expected standard return codes. It is a cancellation entrypoint to be consistent with both thrd_join and cnd_{timed}wait. 3. thrd_yield also uses internal direct syscall to avoid errno clobbering. Checked with a build for all major ABI (aarch64-linux-gnu, alpha-linux-gnu, arm-linux-gnueabi, i386-linux-gnu, ia64-linux-gnu, m68k-linux-gnu, microblaze-linux-gnu [1], mips{64}-linux-gnu, nios2-linux-gnu, powerpc{64le}-linux-gnu, s390{x}-linux-gnu, sparc{64}-linux-gnu, and x86_64-linux-gnu). Also ran a full check on aarch64-linux-gnu, x86_64-linux-gnu, i686-linux-gnu, arm-linux-gnueabhf, and powerpc64le-linux-gnu. [BZ #14092] * conform/Makefile (conformtest-headers-ISO11): Add threads.h. (linknamespace-libs-ISO11): Add libpthread.a. * conform/data/threads.h-data: New file: add C11 thrd_* types and functions. * include/stdc-predef.h (__STDC_NO_THREADS__): Remove definition. * nptl/Makefile (headers): Add threads.h. (libpthread-routines): Add new C11 thread thrd_create, thrd_current, thrd_detach, thrd_equal, thrd_exit, thrd_join, thrd_sleep, and thrd_yield. * nptl/Versions (libpthread) [GLIBC_2.28]): Add new C11 thread thrd_create, thrd_current, thrd_detach, thrd_equal, thrd_exit, thrd_join, thrd_sleep, and thrd_yield symbols. * nptl/descr.h (struct pthread): Add c11 field. * nptl/pthreadP.h (ATTR_C11_THREAD): New define. * nptl/pthread_create.c (START_THREAD_DEFN): Call C11 thread start routine with expected function prototype. (__pthread_create_2_1): Add C11 threads check based on attribute value. * sysdeps/unix/sysdep.h (INTERNAL_SYSCALL_CANCEL): New macro. * nptl/thrd_create.c: New file. * nptl/thrd_current.c: Likewise. * nptl/thrd_detach.c: Likewise. * nptl/thrd_equal.c: Likewise. * nptl/thrd_exit.c: Likewise. * nptl/thrd_join.c: Likewise. * nptl/thrd_priv.h: Likewise. * nptl/thrd_sleep.c: Likewise. * nptl/thrd_yield.c: Likewise. * include/threads.h: Likewise.
Diffstat (limited to 'nptl/pthread_create.c')
-rw-r--r--nptl/pthread_create.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 5f5a007b7f..fe75d04113 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -472,7 +472,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*) (uintptr_t) start (pd->arg);
+ }
+ else
+ ret = pd->start_routine (pd->arg);
+ THREAD_SETMEM (pd, result, ret);
}
/* Call destructors for the thread_local TLS variables. */
@@ -625,7 +637,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;
@@ -683,6 +696,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;