Ejemplo n.º 1
0
void __wait(volatile int *addr, volatile int *waiters, int val, int priv)
{
	int spins=10000;
	if (priv) priv = 128; priv=0;
	while (spins--) {
		if (*addr==val) a_spin();
		else return;
	}
	if (waiters) a_inc(waiters);
	while (*addr==val) {
#ifdef __EMSCRIPTEN__
		if (pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) {
			// Must wait in slices in case this thread is cancelled in between.
			int e;
			do {
				if (_pthread_isduecanceled(pthread_self())) {
					if (waiters) a_dec(waiters);
					return;
				}
				e = emscripten_futex_wait((void*)addr, val, 100);
			} while(e == -ETIMEDOUT);
		} else {
			// Can wait in one go.
			emscripten_futex_wait((void*)addr, val, INFINITY);
		}
#else
		__syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0);
#endif
	}
	if (waiters) a_dec(waiters);
}
Ejemplo n.º 2
0
static int do_wait(volatile int *addr, int val,
	clockid_t clk, const struct timespec *at, int priv)
{
	int r;
	struct timespec to, *top=0;

	if (at) {
		if (at->tv_nsec >= 1000000000UL) return EINVAL;
		if (clock_gettime(clk, &to)) return EINVAL;
		to.tv_sec = at->tv_sec - to.tv_sec;
		if ((to.tv_nsec = at->tv_nsec - to.tv_nsec) < 0) {
			to.tv_sec--;
			to.tv_nsec += 1000000000;
		}
		if (to.tv_sec < 0) return ETIMEDOUT;
		top = &to;
	}

#ifdef __EMSCRIPTEN__
	if (1 || pthread_self()->cancelasync == PTHREAD_CANCEL_ASYNCHRONOUS) {
		do {
			if (_pthread_isduecanceled(pthread_self())) {
				// Emscripten-specific return value: The wait was canceled by user calling
				// pthread_cancel() for this thread, and the caller needs to cooperatively
				// cancel execution.
				return ECANCELED;
			}
			// Must wait in slices in case this thread is cancelled in between.
			double waitMsecs = at ? _pthread_msecs_until(at) : INFINITY;
			if (waitMsecs <= 0) {
				r = ETIMEDOUT;
				break;
			}
			if (waitMsecs > 100) waitMsecs = 100;
			r = -emscripten_futex_wait((void*)addr, val, waitMsecs);
			// Assist other threads by executing proxied operations that are effectively singlethreaded.
			if (emscripten_is_main_runtime_thread()) emscripten_main_thread_process_queued_calls();
		} while(r == ETIMEDOUT);
	} else {
		// Can wait in one go.
		double waitMsecs = at ? _pthread_msecs_until(at) : INFINITY;
		r = -emscripten_futex_wait((void*)addr, val, waitMsecs);
	}
#else
	r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top);
#endif
	if (r == EINTR || r == EINVAL || r == ETIMEDOUT) return r;
	return 0;
}
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
}
int main()
{
	if (!emscripten_has_threading_support())
	{
#ifdef REPORT_RESULT
		REPORT_RESULT(0);
#endif
		printf("Skipped: Threading is not supported.\n");
		return 0;
	}

	pthread_t thread;
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
	int rc = pthread_create(&thread, &attr, ThreadMain, 0);
	assert(rc == 0);
	rc = emscripten_futex_wait(&main_thread_wait_val, 1, 15 * 1000);
	if (rc != 0)
	{
		printf("ERROR! futex wait timed out!\n");
		result = 2;
#ifdef REPORT_RESULT
		REPORT_RESULT(result);
#endif
		exit(1);
	}
	pthread_attr_destroy(&attr);
	pthread_join(thread, 0);		

#ifdef REPORT_RESULT
	REPORT_RESULT(result);
#endif
}
Ejemplo n.º 5
0
void *mandelbrot_thread(void *arg)
{
  int idx = (int)arg;

  for(;;)
  {
    emscripten_futex_wait(&tasksPending[idx], 0, INFINITY);
    emscripten_atomic_store_u32(&tasksPending[idx], 0);
    double t0 = emscripten_get_now();
    int ni;
    if (use_sse)
      ni = ComputeMandelbrot_SSE(mandelReal, mandelImag, outputImage, sizeof(float)*W, sizeof(uint32_t)*W, 0, idx, numTasks, W, H, left, top, incrX, incrY, numItersDoneOnCanvas, numItersPerFrame);
    else
      ni = ComputeMandelbrot(mandelReal, mandelImag, outputImage, sizeof(float)*W, sizeof(uint32_t)*W, 0, idx, numTasks, W, H, left, top, incrX, incrY, numItersDoneOnCanvas, numItersPerFrame);
    //emscripten_atomic_add_u32(&numIters, ni);
    double t1 = emscripten_get_now();
    numIters[idx] += ni;
    timeSpentInMandelbrot[idx] += t1-t0;
    emscripten_atomic_add_u32(&tasksDone, 1);
    emscripten_futex_wake(&tasksDone, 9999);
  }
}