diff options
Diffstat (limited to 'src/thread')
-rw-r--r-- | src/thread/pthread_create.c | 16 | ||||
-rw-r--r-- | src/thread/pthread_detach.c | 4 | ||||
-rw-r--r-- | src/thread/pthread_equal.c | 7 | ||||
-rw-r--r-- | src/thread/pthread_self.c | 7 | ||||
-rw-r--r-- | src/thread/thrd_create.c | 14 | ||||
-rw-r--r-- | src/thread/thrd_exit.c | 9 | ||||
-rw-r--r-- | src/thread/thrd_join.c | 12 | ||||
-rw-r--r-- | src/thread/thrd_sleep.c | 13 | ||||
-rw-r--r-- | src/thread/thrd_yield.c | 7 |
9 files changed, 82 insertions, 7 deletions
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index c170a999..1a47ed15 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 4e454634..ed77f74d 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -1,8 +1,9 @@ #include "pthread_impl.h" +#include <threads.h> 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 3e3df4fd..7c31482a 100644 --- a/src/thread/pthread_equal.c +++ b/src/thread/pthread_equal.c @@ -1,6 +1,11 @@ #include <pthread.h> +#include <threads.h> +#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 5f9e6516..241a6202 100644 --- a/src/thread/pthread_self.c +++ b/src/thread/pthread_self.c @@ -1,6 +1,11 @@ #include "pthread_impl.h" +#include <threads.h> +#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 00000000..e0336695 --- /dev/null +++ b/src/thread/thrd_create.c @@ -0,0 +1,14 @@ +#include "pthread_impl.h" +#include <threads.h> + +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 00000000..b66bd996 --- /dev/null +++ b/src/thread/thrd_exit.c @@ -0,0 +1,9 @@ +#include "pthread_impl.h" +#include <threads.h> + +_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 00000000..ac667893 --- /dev/null +++ b/src/thread/thrd_join.c @@ -0,0 +1,12 @@ +#include <stdint.h> +#include <threads.h> + +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 00000000..e8dfe400 --- /dev/null +++ b/src/thread/thrd_sleep.c @@ -0,0 +1,13 @@ +#include <threads.h> +#include <errno.h> +#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 00000000..f7ad1321 --- /dev/null +++ b/src/thread/thrd_yield.c @@ -0,0 +1,7 @@ +#include <threads.h> +#include "syscall.h" + +void thrd_yield() +{ + __syscall(SYS_sched_yield); +} |