diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 74c62cce81774cdcdbcb9f0f586788c6a98fb9d4..ae6e60b5ebc6d4bfd28ee9bb8adc136b8321d5dd 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -128,4 +128,6 @@ void __restore_sigs(void *); #define DEFAULT_STACK_SIZE 81920 #define DEFAULT_GUARD_SIZE PAGE_SIZE +#define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1) + #endif diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index c170a999cb0b2ddc070e56ebe215585f9e482944..1a47ed15eebf96d0c8d5de4aea54108bc8cc3f53 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -119,7 +119,15 @@ static int start(void *p) if (self->unblock_cancel) __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8); - pthread_exit(self->start(self->start_arg)); + __pthread_exit(self->start(self->start_arg)); + return 0; +} + +static int start_c11(void *p) +{ + pthread_t self = p; + int (*start)(void*) = (int(*)(void*)) self->start; + __pthread_exit((void *)(uintptr_t)start(self->start_arg)); return 0; } @@ -145,7 +153,7 @@ void *__copy_tls(unsigned char *); int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg) { - int ret; + int ret, c11 = (attrp == __ATTRP_C11_THREAD); size_t size, guard; struct pthread *self, *new; unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit; @@ -167,7 +175,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att self->tsd = (void **)__pthread_tsd_main; libc.threaded = 1; } - if (attrp) attr = *attrp; + if (attrp && !c11) attr = *attrp; __acquire_ptc(); @@ -234,7 +242,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att new->canary = self->canary; a_inc(&libc.threads_minus_1); - ret = __clone(start, stack, flags, new, &new->tid, TP_ADJ(new), &new->tid); + ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->tid); __release_ptc(); diff --git a/src/thread/pthread_detach.c b/src/thread/pthread_detach.c index 4e45463489153a1ffdbae4858268a1d204356513..ed77f74d520bff3a16ef5e055f08bbf021fe91d4 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -1,8 +1,9 @@ #include "pthread_impl.h" +#include int __pthread_join(pthread_t, void **); -int __pthread_detach(pthread_t t) +static int __pthread_detach(pthread_t t) { /* Cannot detach a thread that's already exiting */ if (a_swap(t->exitlock, 1)) @@ -13,3 +14,4 @@ int __pthread_detach(pthread_t t) } weak_alias(__pthread_detach, pthread_detach); +weak_alias(__pthread_detach, thrd_detach); diff --git a/src/thread/pthread_equal.c b/src/thread/pthread_equal.c index 3e3df4fda37db0f3aafb47e8fda60c38ea575ae4..7c31482af3f8fec7710d0e995ef8d40cf149ebe4 100644 --- a/src/thread/pthread_equal.c +++ b/src/thread/pthread_equal.c @@ -1,6 +1,11 @@ #include +#include +#include "libc.h" -int (pthread_equal)(pthread_t a, pthread_t b) +static int __pthread_equal(pthread_t a, pthread_t b) { return a==b; } + +weak_alias(__pthread_equal, pthread_equal); +weak_alias(__pthread_equal, thrd_equal); diff --git a/src/thread/pthread_self.c b/src/thread/pthread_self.c index 5f9e6516ac922742b308da019a974876c0f0e507..241a6202d2ea5e15ca53a5e8676398f6c5c95b8e 100644 --- a/src/thread/pthread_self.c +++ b/src/thread/pthread_self.c @@ -1,6 +1,11 @@ #include "pthread_impl.h" +#include +#include "libc.h" -pthread_t pthread_self() +static pthread_t __pthread_self_internal() { return __pthread_self(); } + +weak_alias(__pthread_self_internal, pthread_self); +weak_alias(__pthread_self_internal, thrd_current); diff --git a/src/thread/thrd_create.c b/src/thread/thrd_create.c new file mode 100644 index 0000000000000000000000000000000000000000..e03366952657117198219b49999d2b3985500fd3 --- /dev/null +++ b/src/thread/thrd_create.c @@ -0,0 +1,14 @@ +#include "pthread_impl.h" +#include + +int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict); + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) +{ + int ret = __pthread_create(thr, __ATTRP_C11_THREAD, (void *(*)(void *))func, arg); + switch (ret) { + case 0: return thrd_success; + case EAGAIN: return thrd_nomem; + default: return thrd_error; + } +} diff --git a/src/thread/thrd_exit.c b/src/thread/thrd_exit.c new file mode 100644 index 0000000000000000000000000000000000000000..b66bd99695ca63da6a7f2cc9dbc3f42e88d2e255 --- /dev/null +++ b/src/thread/thrd_exit.c @@ -0,0 +1,9 @@ +#include "pthread_impl.h" +#include + +_Noreturn void __pthread_exit(void *); + +_Noreturn void thrd_exit(int result) +{ + __pthread_exit((void*)(intptr_t)result); +} diff --git a/src/thread/thrd_join.c b/src/thread/thrd_join.c new file mode 100644 index 0000000000000000000000000000000000000000..ac6678939f6b3436818936eaf56b395479c4f3c2 --- /dev/null +++ b/src/thread/thrd_join.c @@ -0,0 +1,12 @@ +#include +#include + +int __pthread_join(thrd_t, void**); + +int thrd_join(thrd_t t, int *res) +{ + void *pthread_res; + __pthread_join(t, &pthread_res); + if (res) *res = (int)(intptr_t)pthread_res; + return thrd_success; +} diff --git a/src/thread/thrd_sleep.c b/src/thread/thrd_sleep.c new file mode 100644 index 0000000000000000000000000000000000000000..e8dfe400cb701f7ae470b192ec04c495a7bfbb18 --- /dev/null +++ b/src/thread/thrd_sleep.c @@ -0,0 +1,13 @@ +#include +#include +#include "syscall.h" + +int thrd_sleep(const struct timespec *req, struct timespec *rem) +{ + int ret = __syscall(SYS_nanosleep, req, rem); + switch (ret) { + case 0: return 0; + case -EINTR: return -1; /* value specified by C11 */ + default: return -2; + } +} diff --git a/src/thread/thrd_yield.c b/src/thread/thrd_yield.c new file mode 100644 index 0000000000000000000000000000000000000000..f7ad13219ce0db9912d1eaf259fbf9048eda8a4f --- /dev/null +++ b/src/thread/thrd_yield.c @@ -0,0 +1,7 @@ +#include +#include "syscall.h" + +void thrd_yield() +{ + __syscall(SYS_sched_yield); +}