Beispiel #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);
}
Beispiel #2
0
void __lock(volatile int *l)
{
	int spins=100000;
	/* Do not use futexes because we insist that unlocking is a simple
	 * assignment to optimize non-pathological code with no contention. */
	while (a_xchg(l, 1))
		if (spins) spins--, a_spin();
		else __syscall(SYS_sched_yield);
}
Beispiel #3
0
void __wait(volatile int *addr, volatile int *waiters, int val, int priv)
{
	int spins=50000;
	if (priv) priv = 128; priv=0;
	while (spins--) {
		if (*addr==val) a_spin();
		else return;
	}
	if (waiters) a_inc(waiters);
	while (*addr==val)
		__syscall(SYS_futex, (long)addr, FUTEX_WAIT|priv, val, 0);
	if (waiters) a_dec(waiters);
}
Beispiel #4
0
int pthread_barrier_wait(pthread_barrier_t *b)
{
	int limit = b->_b_limit;
	struct instance *inst;

	/* Trivial case: count was set at 1 */
	if (!limit) return PTHREAD_BARRIER_SERIAL_THREAD;

	/* Process-shared barriers require a separate, inefficient wait */
	if (limit < 0) return pshared_barrier_wait(b);

	/* Otherwise we need a lock on the barrier object */
	while (a_swap(&b->_b_lock, 1))
		__wait(&b->_b_lock, &b->_b_waiters, 1, 1);
	inst = b->_b_inst;

	/* First thread to enter the barrier becomes the "instance owner" */
	if (!inst) {
		struct instance new_inst = { 0 };
		int spins = 10000;
		b->_b_inst = inst = &new_inst;
		a_store(&b->_b_lock, 0);
		if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
		while (spins-- && !inst->finished)
			a_spin();
		a_inc(&inst->finished);
		while (inst->finished == 1)
			__syscall(SYS_futex, &inst->finished, FUTEX_WAIT,1,0);
		return PTHREAD_BARRIER_SERIAL_THREAD;
	}

	/* Last thread to enter the barrier wakes all non-instance-owners */
	if (++inst->count == limit) {
		b->_b_inst = 0;
		a_store(&b->_b_lock, 0);
		if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
		a_store(&inst->last, 1);
		if (inst->waiters)
			__wake(&inst->last, -1, 1);
	} else {
		a_store(&b->_b_lock, 0);
		if (b->_b_waiters) __wake(&b->_b_lock, 1, 1);
		__wait(&inst->last, &inst->waiters, 0, 1);
	}

	/* Last thread to exit the barrier wakes the instance owner */
	if (a_fetch_add(&inst->count,-1)==1 && a_fetch_add(&inst->finished,1))
		__wake(&inst->finished, 1, 1);

	return 0;
}
Beispiel #5
0
int pthread_spin_lock(pthread_spinlock_t *s)
{
	while (a_swap(s, 1)) a_spin();
	return 0;
}