'Phil Endecott' via emscripten-discuss wrote:
> Dear Experts,
>
> I have code where I (1) use MAIN_THREAD_ASYNC_EM_ASM to
> queue code to run on the main thread from a background
> thread, and (2) protect some data structures from concurrent
> access using pthread mutexes. I am compiling with -pthread.
>
> I know that locking a mutex on the main thread involves
> polling. My question is: can work that has been submitted by
> MAIN_THREAD_ASYNC_EM_ASM run when this polling occurs?
I believe the answer is yes.
- MAIN_THREAD_ASYNC_EM_ASM eventually calls
emscripten_run_js_on_main_thread which queues the
work using emscripten_proxy_async().
- pthread_mutex_lock() eventually calls emscripten_futex_wait()
which calls emscripten_yield(), which calls
emscripten_main_thread_process_queued_calls(), which
calls emscripten_proxy_execute_queue().
This seems to be deliberate; there is a comment in
emscripten_futex_wait():
// We are performing a blocking loop here, so we must handle proxied
// events from pthreads, to avoid deadlocks.
Do others see that there is a potential problem here? Rather than
avoiding deadlocks, this can introduce them!
Consider (pseudo-code):
// main thread:
lock A
lock B
...
unlock B
unlock A
// other thread:
MAIN_THREAD_ASYNC_EM_ASM {
lock A
....
unlock A
}
When the main thread locks mutex B, it may invoke the work that
has been sent from the other thread - which tries to lock A, which
the main thread has already locked. This is undefined behaviour.
Various things could happen, none of them good.
So - is there some alternative to MAIN_THREAD_ASYNC_EM_ASM
that I should use, such that the work is only done when the main
thread is actually idle?
Thanks, Phil.