Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 17 additions & 38 deletions system/lib/pthread/library_pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,54 +65,33 @@ int sched_get_priority_min(int policy) {
return 0;
}

int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *restrict attr, int *restrict prioceiling)
{
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *restrict attr, int *restrict prioceiling) {
// Not supported either in Emscripten or musl, return a faked value.
if (prioceiling) *prioceiling = 99;
return 0;
}

int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
{
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling) {
// Not supported either in Emscripten or musl, return an error.
return EPERM;
}

static uint32_t dummyZeroAddress = 0;

void emscripten_thread_sleep(double msecs) {
double now = emscripten_get_now();
double target = now + msecs;

// If we have less than this many msecs left to wait, busy spin that instead.
double min_ms_slice_to_sleep = 0.1;

// Break up sleeping so that we process proxied work at regular intervals.
// TODO(sbc): This should be removed and/or moved down into
// `emscripten_futex_wait`.
double max_ms_slice_to_sleep = 100;

emscripten_conditional_set_current_thread_status(
EM_THREAD_STATUS_RUNNING, EM_THREAD_STATUS_SLEEPING);

do {
// Keep processing the main loop of the calling thread.
__pthread_testcancel(); // pthreads spec: sleep is a cancellation point, so must test if this
// thread is cancelled during the sleep.
emscripten_current_thread_process_queued_calls();

now = emscripten_get_now();
double ms_to_sleep = target - now;
if (ms_to_sleep < min_ms_slice_to_sleep)
continue;
if (ms_to_sleep > max_ms_slice_to_sleep)
ms_to_sleep = max_ms_slice_to_sleep;
emscripten_futex_wait(&dummyZeroAddress, 0, ms_to_sleep);
now = emscripten_get_now();
} while (now < target);

emscripten_conditional_set_current_thread_status(
EM_THREAD_STATUS_SLEEPING, EM_THREAD_STATUS_RUNNING);
// We include emscripten_current_thread_process_queued_calls before and
// after sleeping since that is how we recieve "async" signals.
// We include
// We include __pthread_testcancel here becuase clock_nanosleep is
// a pthread cancelation point.
emscripten_current_thread_process_queued_calls();
__pthread_testcancel();
emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS_RUNNING,
EM_THREAD_STATUS_SLEEPING);
uint32_t dummyZeroAddress = 0;
emscripten_futex_wait(&dummyZeroAddress, 0, msecs);
emscripten_conditional_set_current_thread_status(EM_THREAD_STATUS_SLEEPING,
EM_THREAD_STATUS_RUNNING);
emscripten_current_thread_process_queued_calls();
__pthread_testcancel();
}

static struct pthread __main_pthread;
Expand Down
4 changes: 3 additions & 1 deletion system/lib/pthread/library_pthread_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ int pthread_cancel(pthread_t thread) {
return 0;
}

void pthread_testcancel() {}
void __pthread_testcancel() {}

weak_alias(__pthread_testcancel, pthread_testcancel);

_Noreturn void __pthread_exit(void* status) {
exit(0);
Expand Down
9 changes: 6 additions & 3 deletions test/pthread/test_pthread_kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,26 @@

#include <pthread.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>

#include <emscripten/console.h>

pthread_cond_t started_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t started_lock = PTHREAD_MUTEX_INITIALIZER;
_Atomic int got_term_signal = 0;
_Atomic bool got_term_signal = false;

pthread_t thr;

void signal_handler(int sig, siginfo_t * info, void * arg) {
printf("signal: %d onthread=%d\n", sig, pthread_self() == thr);
if (sig == SIGTERM) {
got_term_signal = 1;
got_term_signal = true;
}
}

Expand Down Expand Up @@ -63,9 +66,9 @@ int main() {
printf("thread has started, sending SIGTERM\n");

s = pthread_kill(thr, SIGTERM);
assert(s == 0);
printf("SIGTERM sent\n");

assert(s == 0);

pthread_join(thr, NULL);
return 0;
Expand Down
5 changes: 4 additions & 1 deletion test/wasm_worker/lock_waitinf_acquire.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
// When WASM_WORKERS is not defined we create dummy/fake version of
// emscripten_wasm_worker_sleep.
void emscripten_wasm_worker_sleep(int64_t nsecs) {
emscripten_thread_sleep(nsecs / 1000000);
double ms = nsecs / 1000000.0;
emscripten_outf("emscripten_wasm_worker_sleep %f", ms);
emscripten_thread_sleep(ms);
}
#endif

Expand Down Expand Up @@ -86,6 +88,7 @@ void* pthread_main(void* arg) {
#endif

int main() {
emscripten_outf("Main thread running... %d", gettid());
emscripten_lock_init(&lock);

for (int i = 0; i < NUM_THREADS; ++i) {
Expand Down
Loading