blob: 3c9b0e6e6f914a39d0c3e3c8f4b7e796e95c0e5d [file] [log] [blame] [edit]
/*
* Copyright 2021 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/
#define _GNU_SOURCE
#include "pthread_impl.h"
#include <pthread.h>
#include <stdbool.h>
#include <threads.h>
// See musl's pthread_create.c
extern int __cxa_thread_atexit(void (*)(void *), void *, void *);
extern int __pthread_create_js(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
extern _Noreturn void __pthread_exit_js(void* status);
extern int8_t __dso_handle;
void __run_cleanup_handlers(void* _unused) {
pthread_t self = __pthread_self();
while (self->cancelbuf) {
void (*f)(void *) = self->cancelbuf->__f;
void *x = self->cancelbuf->__x;
self->cancelbuf = self->cancelbuf->__next;
f(x);
}
}
void __do_cleanup_push(struct __ptcb *cb) {
struct pthread *self = __pthread_self();
cb->__next = self->cancelbuf;
self->cancelbuf = cb;
static thread_local bool registered = false;
if (!registered) {
__cxa_thread_atexit(__run_cleanup_handlers, NULL, &__dso_handle);
registered = true;
}
}
void __do_cleanup_pop(struct __ptcb *cb) {
__pthread_self()->cancelbuf = cb->__next;
}
int __pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) {
return __pthread_create_js(thread, attr, start_routine, arg);
}
_Noreturn void __pthread_exit(void* status) {
__pthread_exit_js(status);
}
weak_alias(__pthread_create, emscripten_builtin_pthread_create);
weak_alias(__pthread_create, pthread_create);
weak_alias(__pthread_exit, pthread_exit);