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; }
void fiber_exit(int exit_code) { fiber_check(); __thread_fiber->exitcode = exit_code; __thread_fiber->running->status = FIBER_STATUS_EXITING; acl_fiber_switch(); }
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; }
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; }
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; }
void fiber::switch_to_next(void) { acl_fiber_switch(); }
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; }