int main() { sharedVar = 0; int s = pthread_create(&thr, NULL, thread_start, 0); assert(s == 0); // Wait until thread kicks in and sets the shared variable. while(sharedVar == 0) BusySleep(10); s = pthread_kill(thr, SIGKILL); assert(s == 0); // Wait until we see the shared variable stop incrementing. (This is a bit heuristic and hacky) for(;;) { int val = emscripten_atomic_load_u32((void*)&sharedVar); BusySleep(100); int val2 = emscripten_atomic_load_u32((void*)&sharedVar); if (val == val2) break; } // Reset to 0. sharedVar = 0; emscripten_atomic_store_u32((void*)&sharedVar, 0); // Wait for a long time, if the thread is still running, it should progress and set sharedVar by this time. BusySleep(3000); // Finally test that the thread is not doing any work and it is dead. assert(sharedVar == 0); assert(emscripten_atomic_load_u32((void*)&sharedVar) == 0); EM_ASM_INT( { Module['print']('Main: Done. Successfully killed thread. sharedVar: '+$0+'.'); }, sharedVar);
EMSCRIPTEN_RESULT emscripten_fetch_wait(emscripten_fetch_t *fetch, double timeoutMsecs) { #if __EMSCRIPTEN_PTHREADS__ if (!fetch) return EMSCRIPTEN_RESULT_INVALID_PARAM; uint32_t proxyState = emscripten_atomic_load_u32(&fetch->__proxyState); if (proxyState == 2) return EMSCRIPTEN_RESULT_SUCCESS; // already finished. if (proxyState != 1) return EMSCRIPTEN_RESULT_INVALID_PARAM; // the fetch should be ongoing? // #ifdef FETCH_DEBUG EM_ASM({ console.log('fetch: emscripten_fetch_wait..') }); // #endif // TODO: timeoutMsecs is currently ignored. Return EMSCRIPTEN_RESULT_TIMED_OUT on timeout. while(proxyState == 1/*sent to proxy worker*/) { emscripten_futex_wait(&fetch->__proxyState, proxyState, 100 /*TODO HACK:Sleep sometimes doesn't wake up?*/);//timeoutMsecs); proxyState = emscripten_atomic_load_u32(&fetch->__proxyState); } // #ifdef FETCH_DEBUG EM_ASM({ console.log('fetch: emscripten_fetch_wait done..') }); // #endif if (proxyState == 2) return EMSCRIPTEN_RESULT_SUCCESS; else return EMSCRIPTEN_RESULT_FAILED; #else EM_ASM({ console.error('fetch: emscripten_fetch_wait is not available when building without pthreads!') }); return EMSCRIPTEN_RESULT_FAILED; #endif }
// TEMP to make this test pass: // Our Clang backend doesn't define this builtin function, so implement it ourselves. // The current Atomics spec doesn't have the nand atomic op either, so must use a cas loop. // TODO: Move this to Clang backend? T __sync_nand_and_fetch(T *ptr, T x) { for(;;) { T old = emscripten_atomic_load_u32(ptr); T newVal = ~(old & x); T old2 = emscripten_atomic_cas_u32(ptr, old, newVal); if (old2 == old) return old; } }
// Test __sync_bool_compare_and_swap. T nand_and_fetch_bool(T *ptr, T x) { for(;;) { T old = emscripten_atomic_load_u32(ptr); T newVal = ~(old & x); Bool success = __sync_bool_compare_and_swap(ptr, old, newVal); if (success) return newVal; } }
// Test __sync_val_compare_and_swap. T nand_and_fetch(T *ptr, T x) { for(;;) { T old = emscripten_atomic_load_u32(ptr); T newVal = ~(old & x); T old2 = __sync_val_compare_and_swap(ptr, old, newVal); if (old2 == old) return newVal; } }
void PollThreadExit(void *) { if (!emscripten_atomic_load_u32(&threadRunning)) { EmscriptenWebGLContextAttributes attr; emscripten_webgl_init_context_attributes(&attr); #ifdef TEST_MAIN_THREAD_EXPLICIT_COMMIT attr.explicitSwapControl = EM_TRUE; #endif ctx = emscripten_webgl_create_context(0, &attr); emscripten_webgl_make_context_current(ctx); printf("Main thread rendering. You should see the WebGL canvas fade from black to green.\n"); emscripten_set_main_loop(MainThreadRender, 0, 0); } else { emscripten_async_call(PollThreadExit, 0, 1000); } }
int main() { int result; if (!emscripten_has_threading_support()) { #ifdef REPORT_RESULT result = 1; REPORT_RESULT(); #endif printf("Skipped: Threading is not supported.\n"); return 0; } pthread_t thr; int rc = pthread_create(&thr, NULL, thread_start, (void*)0); if (rc != 0) { #ifdef REPORT_RESULT int result = (rc != EAGAIN); REPORT_RESULT(); return 0; #endif } #ifdef USE_C_VOLATILE while(sharedVar == 0) ; #else while(emscripten_atomic_load_u32((void*)&sharedVar) == 0) {} #endif #ifdef REPORT_RESULT result = sharedVar; REPORT_RESULT(); #endif }