diff --git a/libc-bottom-half/headers/public/wasi/api.h b/libc-bottom-half/headers/public/wasi/api.h index 45a6506e2..f2cfbe7a1 100644 --- a/libc-bottom-half/headers/public/wasi/api.h +++ b/libc-bottom-half/headers/public/wasi/api.h @@ -2099,12 +2099,14 @@ __wasi_errno_t __wasi_sock_shutdown( * * @see https://github.com/WebAssembly/wasi-threads/#readme */ -int32_t __wasi_thread_spawn( +uint8_t __wasi_thread_spawn( /** * A pointer to an opaque struct to be passed to the module's entry * function. */ - void *start_arg + void *start_arg, + uint8_t *error, + uint32_t *tid ) __attribute__((__warn_unused_result__)); #endif diff --git a/libc-bottom-half/sources/__wasilibc_real.c b/libc-bottom-half/sources/__wasilibc_real.c index d2e6b71c6..6f8bbdadd 100644 --- a/libc-bottom-half/sources/__wasilibc_real.c +++ b/libc-bottom-half/sources/__wasilibc_real.c @@ -660,12 +660,25 @@ __wasi_errno_t __wasi_sock_shutdown( } #ifdef _REENTRANT -int32_t __imported_wasi_thread_spawn(int32_t arg0) __attribute__(( +void __imported_wasi_thread_spawn(int32_t arg0, int32_t arg1) __attribute__(( __import_module__("wasi"), - __import_name__("thread_spawn") -)); - -int32_t __wasi_thread_spawn(void* start_arg) { - return __imported_wasi_thread_spawn((int32_t) start_arg); + __import_name__("thread-spawn") +)); + +uint8_t __wasi_thread_spawn(void *start_arg, uint8_t *error, uint32_t *tid) { + struct { + uint8_t is_error; + union { + uint8_t error; + uint32_t tid; + } u; + } error_or_tid; + __imported_wasi_thread_spawn((int32_t) start_arg, (int32_t)(intptr_t) &error_or_tid); + if (error_or_tid.is_error) { + *error = error_or_tid.u.error; + return 1; + } + *tid = error_or_tid.u.tid; + return 0; } #endif diff --git a/libc-top-half/musl/src/thread/pthread_create.c b/libc-top-half/musl/src/thread/pthread_create.c index 676e2ccf9..a5bcd3fca 100644 --- a/libc-top-half/musl/src/thread/pthread_create.c +++ b/libc-top-half/musl/src/thread/pthread_create.c @@ -351,6 +351,9 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att void* new_tls_base; size_t tls_offset; tls_size += tls_align; + uint8_t is_error; + uint32_t tid; + uint8_t error; #endif #ifdef __wasilibc_unmodified_upstream @@ -516,7 +519,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att * of the current module and start executing the entry function. The * wasi-threads specification requires the module to export a * `wasi_thread_start` function, which is invoked with `args`. */ - ret = __wasi_thread_spawn((void *) args); + is_error = __wasi_thread_spawn((void *) args, &error, &tid); #endif #ifdef __wasilibc_unmodified_upstream @@ -542,10 +545,15 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att * did succeed, then we store the TID atomically, since this parent thread * is racing with the child thread to set this field; this way, whichever * thread reaches this point first can continue without waiting. */ - if (ret < 0) { + if (is_error) { + /* + * At this point EAGAIN is the only defined error in wasi-threads. + * when the list grows, maybe we should convert errno. + */ ret = -EAGAIN; } else { - atomic_store((atomic_int *) &(new->tid), ret); + atomic_store((atomic_int *) &(new->tid), (int)tid); + ret = 0; } #endif