summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/internal/pthread_impl.h2
-rw-r--r--src/thread/pthread_create.c16
-rw-r--r--src/thread/pthread_detach.c4
-rw-r--r--src/thread/pthread_equal.c7
-rw-r--r--src/thread/pthread_self.c7
-rw-r--r--src/thread/thrd_create.c14
-rw-r--r--src/thread/thrd_exit.c9
-rw-r--r--src/thread/thrd_join.c12
-rw-r--r--src/thread/thrd_sleep.c13
-rw-r--r--src/thread/thrd_yield.c7
10 files changed, 84 insertions, 7 deletions
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 74c62cce..ae6e60b5 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 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);
+}