summaryrefslogtreecommitdiffstats
path: root/libc-top-half/musl/src/thread/pthread_create.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc-top-half/musl/src/thread/pthread_create.c')
-rw-r--r--libc-top-half/musl/src/thread/pthread_create.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c
index 1aa7be7..676e2cc 100644
--- a/libc-top-half/musl/src/thread/pthread_create.c
+++ b/libc-top-half/musl/src/thread/pthread_create.c
@@ -60,7 +60,11 @@ void __tl_sync(pthread_t td)
if (tl_lock_waiters) __wake(&__thread_list_lock, 1, 0);
}
+#ifdef __wasilibc_unmodified_upstream
_Noreturn void __pthread_exit(void *result)
+#else
+static void __pthread_exit(void *result)
+#endif
{
pthread_t self = __pthread_self();
sigset_t set;
@@ -191,7 +195,7 @@ _Noreturn void __pthread_exit(void *result)
__tl_unlock();
free(self->map_base);
// Can't use `exit()` here, because it is too high level
- for (;;) __wasi_proc_exit(0);
+ return;
}
#endif
@@ -212,7 +216,6 @@ _Noreturn void __pthread_exit(void *result)
// do it manually here
__tl_unlock();
// Can't use `exit()` here, because it is too high level
- for (;;) __wasi_proc_exit(0);
#endif
}
@@ -235,9 +238,14 @@ struct start_args {
volatile int control;
unsigned long sig_mask[_NSIG/8/sizeof(long)];
#else
+ /*
+ * Note: the offset of the "stack" and "tls_base" members
+ * in this structure is hardcoded in wasi_thread_start.
+ */
+ void *stack;
+ void *tls_base;
void *(*start_func)(void *);
void *start_arg;
- void *tls_base;
#endif
};
@@ -271,32 +279,41 @@ static int start_c11(void *p)
return 0;
}
#else
-__attribute__((export_name("wasi_thread_start")))
-_Noreturn void wasi_thread_start(int tid, void *p)
+
+/*
+ * We want to ensure wasi_thread_start is linked whenever
+ * pthread_create is used. The following reference is to ensure that.
+ * Otherwise, the linker doesn't notice the dependency because
+ * wasi_thread_start is used indirectly via a wasm export.
+ */
+void wasi_thread_start(int tid, void *p);
+hidden void *__dummy_reference = wasi_thread_start;
+
+hidden void __wasi_thread_start_C(int tid, void *p)
{
struct start_args *args = p;
- __asm__(".globaltype __tls_base, i32\n"
- "local.get %0\n"
- "global.set __tls_base\n"
- :: "r"(args->tls_base));
pthread_t self = __pthread_self();
// Set the thread ID (TID) on the pthread structure. The TID is stored
// atomically since it is also stored by the parent thread; this way,
// whichever thread (parent or child) reaches this point first can proceed
// without waiting.
atomic_store((atomic_int *) &(self->tid), tid);
- // Set the stack pointer.
- __asm__(".globaltype __stack_pointer, i32\n"
- "local.get %0\n"
- "global.set __stack_pointer\n"
- :: "r"(self->stack));
// Execute the user's start function.
- int (*start)(void*) = (int(*)(void*)) args->start_func;
- __pthread_exit((void *)(uintptr_t)start(args->start_arg));
+ __pthread_exit(args->start_func(args->start_arg));
}
#endif
+#ifdef __wasilibc_unmodified_upstream
#define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
+#else
+/*
+ * As we allocate stack with malloc() instead of mmap/mprotect,
+ * there is no point to round it up to PAGE_SIZE.
+ * Instead, round up to a sane alignment.
+ * Note: PAGE_SIZE is rather big on WASM. (65536)
+ */
+#define ROUND(x) (((x)+16-1)&-16)
+#endif
/* pthread_key_create.c overrides this */
static volatile size_t dummy = 0;
@@ -484,6 +501,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
/* Correct the stack size */
new->stack_size = stack - stack_limit;
+ args->stack = new->stack; /* just for convenience of asm trampoline */
args->start_func = entry;
args->start_arg = arg;
args->tls_base = (void*)new_tls_base;
@@ -561,5 +579,7 @@ fail:
return EAGAIN;
}
+#ifdef __wasilibc_unmodified_upstream
weak_alias(__pthread_exit, pthread_exit);
+#endif
weak_alias(__pthread_create, pthread_create);