Skip to content

Mt deadlock issue #12309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
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
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -509,3 +509,4 @@ a license to everyone to use it as detailed in LICENSE.)
* Julien Jorge <[email protected]>
* Attila Oláh <[email protected]> (copyright owned by Google, LLC)
* Marat Dukhan <[email protected]> (copyright owned by Google, LLC)
* Alexander Jährling <[email protected]>
6 changes: 3 additions & 3 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ var LibraryPThread = {
__pthread_testcancel_js();
// In main runtime thread (the thread that initialized the Emscripten C runtime and launched main()), assist pthreads in performing operations
// that they need to access the Emscripten main runtime for.
if (!ENVIRONMENT_IS_PTHREAD) _emscripten_main_thread_process_queued_calls();
if (!ENVIRONMENT_IS_PTHREAD) _emscripten_current_thread_process_proxied_queued_calls();
_emscripten_futex_wait(thread + {{{ C_STRUCTS.pthread.threadStatus }}}, threadStatus, ENVIRONMENT_IS_PTHREAD ? 100 : 1);
}
},
Expand Down Expand Up @@ -1107,7 +1107,7 @@ var LibraryPThread = {
_main_thread_futex_wait_address: '0',

// Returns 0 on success, or one of the values -ETIMEDOUT, -EWOULDBLOCK or -EINVAL on error.
emscripten_futex_wait__deps: ['_main_thread_futex_wait_address', 'emscripten_main_thread_process_queued_calls'],
emscripten_futex_wait__deps: ['_main_thread_futex_wait_address', 'emscripten_current_thread_process_proxied_queued_calls'],
emscripten_futex_wait: function(addr, val, timeout) {
if (addr <= 0 || addr > HEAP8.length || addr&3 != 0) return -{{{ cDefine('EINVAL') }}};
if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_WORKER) {
Expand Down Expand Up @@ -1146,7 +1146,7 @@ var LibraryPThread = {
#endif
return -{{{ cDefine('ETIMEDOUT') }}};
}
_emscripten_main_thread_process_queued_calls(); // We are performing a blocking loop here, so must pump any pthreads if they want to perform operations that are proxied.
_emscripten_current_thread_process_proxied_queued_calls(); // We are performing a blocking loop here, so must pump any pthreads if they want to perform operations that are proxied.
addr = Atomics.load(HEAP32, __main_thread_futex_wait_address >> 2); // Look for a worker thread waking us up.
}
#if PTHREADS_PROFILING
Expand Down
2 changes: 2 additions & 0 deletions system/include/emscripten/threading.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ void emscripten_main_thread_process_queued_calls(void);

void emscripten_current_thread_process_queued_calls(void);

void emscripten_current_thread_process_proxied_queued_calls(void);

pthread_t emscripten_main_browser_thread_id(void);

// Synchronously sleeps the calling thread for the given number of milliseconds.
Expand Down
2 changes: 1 addition & 1 deletion system/lib/libc/musl/src/thread/__timedwait.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ int __timedwait_cp(volatile int *addr, int val,
return ECANCELED;
}
// Assist other threads by executing proxied operations that are effectively singlethreaded.
if (is_main_thread) emscripten_main_thread_process_queued_calls();
if (is_main_thread) emscripten_current_thread_process_proxied_queued_calls();
// Must wait in slices in case this thread is cancelled in between.
double waitMsecs = sleepUntilTime - emscripten_get_now();
if (waitMsecs <= 0) {
Expand Down
53 changes: 51 additions & 2 deletions system/lib/pthread/library_pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void emscripten_thread_sleep(double msecs) {

__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();
emscripten_current_thread_process_proxied_queued_calls();

// If we have less than this many msecs left to wait, busy spin that instead.
const double minimumTimeSliceToSleep = 0.1;
Expand All @@ -137,7 +137,7 @@ void emscripten_thread_sleep(double msecs) {
// 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();
emscripten_current_thread_process_proxied_queued_calls();

now = emscripten_get_now();
double msecsToSleep = target - now;
Expand Down Expand Up @@ -200,6 +200,10 @@ int emscripten_builtin_pthread_create(void *thread, void *attr,

static void _do_call(em_queued_call* q) {
// C function pointer
if (q == 0) {
return;
}

assert(EM_FUNC_SIG_NUM_FUNC_ARGUMENTS(q->functionEnum) <= EM_QUEUED_CALL_MAX_ARGS);
switch (q->functionEnum) {
case EM_PROXIED_PTHREAD_CREATE:
Expand Down Expand Up @@ -651,6 +655,51 @@ void* EMSCRIPTEN_KEEPALIVE emscripten_sync_run_in_main_thread_7(int function, vo
return q.returnValue.vp;
}

void EMSCRIPTEN_KEEPALIVE emscripten_current_thread_process_proxied_queued_calls() {
// this call should just handled proxied calls
pthread_mutex_lock(&call_queue_lock);
CallQueue* q = GetQueue(pthread_self());
if (!q) {
pthread_mutex_unlock(&call_queue_lock);
return;
}

if (!emscripten_is_main_browser_thread()) {
EM_ASM({console.log('!!!emscripten_current_thread_process_proxied_queued_calls called from worker: thread ' + _pthread_self() + "\n" + new Error().stack)});
}

int head = emscripten_atomic_load_u32((void*)&q->call_queue_head);
int tail = emscripten_atomic_load_u32((void*)&q->call_queue_tail);
while (head != tail) {
// Assume that the call is heavy, so unlock access to the call queue while it is being
// performed.
em_queued_call* call = q->call_queue[head];
if (call == 0) {
// already processed
head = (head + 1) % CALL_QUEUE_SIZE;
continue;
}
if ((call->functionEnum & EM_FUNC_SIG_SPECIAL_INTERNAL) == 0) {
head = (head + 1) % CALL_QUEUE_SIZE;
continue;
}
pthread_mutex_unlock(&call_queue_lock);
_do_call(call);
pthread_mutex_lock(&call_queue_lock);

// remove from queue
q->call_queue[head] = 0;

head = (head + 1) % CALL_QUEUE_SIZE;
//emscripten_atomic_store_u32((void*)&q->call_queue_head, head);
tail = emscripten_atomic_load_u32((void*)&q->call_queue_tail);
}
pthread_mutex_unlock(&call_queue_lock);

// If the queue was full and we had waiters pending to get to put data to queue, wake them up.
emscripten_futex_wake((void*)&q->call_queue_head, 0x7FFFFFFF);
}

void EMSCRIPTEN_KEEPALIVE emscripten_current_thread_process_queued_calls() {
// #if PTHREADS_DEBUG == 2
// EM_ASM(console.error('thread ' + _pthread_self() + ':
Expand Down
4 changes: 4 additions & 0 deletions system/lib/pthread/library_pthread_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ void emscripten_main_thread_process_queued_calls() {
// nop
}

void emscripten_current_thread_process_proxied_queued_calls() {
// nop
}

void emscripten_current_thread_process_queued_calls() {
// nop
}
Expand Down