Beispiel #1
0
int acl_fiber_sem_wait(ACL_FIBER_SEM *sem)
{
	ACL_FIBER *curr;

	if (sem->tid != acl_pthread_self())
		return -1;

	if (sem->num > 0) {
		sem->num--;
		return sem->num;
	}

	curr = acl_fiber_running();
	if (curr == NULL)
		return -1;

	acl_ring_prepend(&sem->waiting, &curr->me);
	acl_fiber_switch();

	/* if switch to me because other killed me, I should detach myself;
	 * else if because other unlock, I'll be detached twice which is
	 * hamless because ACL_RING can deal with it.
	 */
	acl_ring_detach(&curr->me);

	return sem->num;
}
Beispiel #2
0
void fiber_exit(int exit_code)
{
	fiber_check();

	__thread_fiber->exitcode = exit_code;
	__thread_fiber->running->status = FIBER_STATUS_EXITING;

	acl_fiber_switch();
}
Beispiel #3
0
int acl_fiber_yield(void)
{
	int  n;

	if (acl_ring_size(&__thread_fiber->ready) == 0)
		return 0;

	n = __thread_fiber->switched;
	acl_fiber_ready(__thread_fiber->running);
	acl_fiber_switch();

	return __thread_fiber->switched - n - 1;
}
Beispiel #4
0
static int __wlock(ACL_FIBER_RWLOCK *lk, int block)
{
	ACL_FIBER *curr;

	if (lk->writer == NULL && lk->readers == 0) {
		lk->writer = acl_fiber_running();
		return 1;
	}

	if (!block)
		return 0;

	curr = acl_fiber_running();
	acl_ring_prepend(&lk->wwaiting, &curr->me);
	acl_fiber_switch();

	/* if switch to me because other killed me, I should detach myself */
	acl_ring_detach(&curr->me);

	return 1;
}
Beispiel #5
0
static int __lock(ACL_FIBER_MUTEX *lk, int block)
{
	ACL_FIBER *curr = acl_fiber_running();

	if (lk->owner == NULL) {
		lk->owner = acl_fiber_running();
		acl_ring_prepend(&curr->holding, &lk->me);
		return 0;
	}

	// xxx: no support recursion lock
	assert(lk->owner != curr);

	if (!block)
		return -1;

	acl_ring_prepend(&lk->waiting, &curr->me);
	curr->waiting = lk;

	acl_fiber_switch();

	/* if switch to me because other killed me, I should detach myself;
	 * else if because other unlock, I'll be detached twice which is
	 * hamless because ACL_RING can deal with it.
	 */
	acl_ring_detach(&curr->me);

	if (lk->owner == curr)
		return 0;

	if (acl_fiber_killed(curr))
		acl_msg_info("%s(%d), %s: lock fiber-%u was killed",
			__FILE__, __LINE__, __FUNCTION__, acl_fiber_id(curr));
	else
		acl_msg_warn("%s(%d), %s: qlock: owner=%p self=%p oops",
			__FILE__, __LINE__, __FUNCTION__, lk->owner, curr);

	return 0;
}
Beispiel #6
0
void fiber::switch_to_next(void)
{
	acl_fiber_switch();
}
Beispiel #7
0
static int channel_alt(FIBER_ALT a[])
{
	int i, j, ncan, n, canblock;
	ACL_CHANNEL *c;
	ACL_FIBER *t;

	for (i = 0; a[i].op != CHANEND && a[i].op != CHANNOBLK; i++) {}

	n = i;
	canblock = a[i].op == CHANEND;

	t = fiber_running();

	for (i = 0; i < n; i++) {
		a[i].fiber = t;
		a[i].xalt = a;
	}

	if (dbgalt)
		printf("alt ");

	ncan = 0;

	for (i = 0; i < n; i++) {
		c = a[i].c;

		if (dbgalt) {
			printf(" %c:", "esrnb"[a[i].op]);
			if (c->name)
				printf("%s", c->name);
			else
				printf("%p", c);
		}

		if (alt_can_exec(&a[i])) {
			if (dbgalt)
				printf("*");
			ncan++;
		}
	}

	if (ncan) {
		j = rand() % ncan;

		for (i = 0; i < n; i++) {
			if (!alt_can_exec(&a[i]))
				continue;

			if (j-- > 0)
				continue;

			if (dbgalt) {
				c = a[i].c;
				printf(" => %c:", "esrnb"[a[i].op]);
				if(c->name)
					printf("%s", c->name);
				else
					printf("%p", c);
				printf("\n");
			}

			alt_exec(&a[i]);
			return i;
		}
	}

	if (dbgalt)
		printf("\n");

	if (!canblock)
		return -1;

	for (i = 0; i < n; i++) {
		if (a[i].op != CHANNOP)
			alt_queue(&a[i]);
	}

	acl_fiber_switch();

	/*
	 * the guy who ran the op took care of dequeueing us
	 * and then set a[0].alt to the one that was executed.
	 */
	return a[0].xalt - a;
}