void* coro_fun(void *arg) { //printf("a coro start\n"); coro_t co = (coro_t)arg; LINK_LIST_PUSH_BACK(co->_sche->active_list_2,co); co->status = CORO_ACTIVE; uthread_switch(co->ut,co->_sche->co->ut,co); void *ret = co->fun(co->arg); co->status = CORO_DIE; uthread_switch(co->ut,co->_sche->co->ut,co); return NULL; }
static inline coro_t _sche_next(sche_t s,coro_t co) { coro_t next = NULL; coro_t coro_goback = co->_goback; if(NULL == coro_goback) { next = LINK_LIST_POP(coro_t,s->active_list_1); if(!next) next = LINK_LIST_POP(coro_t,s->active_list_2); if(!next) next = s->co; } else { next = coro_goback; co->_goback = NULL; } if(co->status == CORO_YIELD) { co->status = CORO_ACTIVE; LINK_LIST_PUSH_BACK(s->active_list_2,co); } assert(co != next); set_current_coro(next); return (coro_t)uthread_switch(co->ut,next->ut,co); }
/* * uthread_yield * * Causes the currently running thread to yield use of the processor to * another thread. */ void uthread_yield(void) { /* Yield the processor to somebody */ /* Always succeeds */ /* When we call this function, the thread is not in CPU anymore */ int offset = ut_curthr - &uthreads[0]; /* Make sure it's not hack */ if (offset >= 0 && offset < UTH_MAX_UTHREADS && ut_curthr->ut_state == UT_ON_CPU) { ut_curthr->ut_state = UT_RUNNABLE; /* Set the priority */ if (uthread_setprio(ut_curthr->ut_id, ut_curthr->ut_prio) != 0) { char pbuffer[256] = {0}; sprintf(pbuffer, "error in setprio\n"); int ret = write(STDOUT_FILENO, pbuffer, strlen(pbuffer)); if (ret < 0) { perror("write"); } exit(EXIT_FAILURE); } } /* do switch */ uthread_switch(); }
void* ufun1(void *arg) { uthread_t self = (uthread_t)arg; uthread_t u = uthread_create(self,stack2,4096,ufun2); char* _arg[2]; _arg[0] = (char*)u; _arg[1] = (char*)self; int i = 0; uint32_t tick = GetSystemMs(); for( ; i < 30000000; ++i) { uthread_switch(self,u,&_arg[0]); } printf("%d\n",GetSystemMs()-tick); uthread_switch(self,u,NULL); return arg; }
/* * uthread_yield * * Causes the currently running thread to yield use of the processor to * another thread. The thread is still runnable however, so it should * be in the UT_RUNNABLE state and schedulable by the scheduler. When this * function returns, the thread should be executing again. A bit more clearly, * when this function is called, the current thread stops executing for some * period of time (allowing another thread to execute). Then, when the time * is right (ie when a call to uthread_switch() results in this thread * being swapped in), the function returns. */ void uthread_yield(void) { //NOT_YET_IMPLEMENTED("UTHREADS: uthread_yield"); ut_curthr-> ut_state = UT_RUNNABLE; uthread_switch(); ut_curthr->ut_state = UT_ON_CPU; return; }
/* * uthread_block * * Put the current thread to sleep, pending an appropriate call to * uthread_wake(). */ void uthread_block(void) { //NOT_YET_IMPLEMENTED("UTHREADS: uthread_block"); ut_curthr -> ut_state = UT_WAIT; uthread_switch(); //woken up by others ut_curthr->ut_state = UT_ON_CPU; return; }
int32_t sche_spawn(sche_t s,void*(*fun)(void*),void*arg) { if(s->coro_size > s->max_coro) return -1; coro_t co = coro_create(s,s->stack_size,coro_fun); co->arg = arg; co->fun = fun; ++s->coro_size; double_link_push(&s->coros,&co->dblink); uthread_switch(s->co->ut,co->ut,co); return 0; }
/* * uthread_block * * Put the current thread to sleep, pending an appropriate call to * uthread_wake(). */ void uthread_block(void) { /* Already waiting? deadlock */ if (ut_curthr->ut_state == UT_WAIT) { uthread_switch(); } /* If the current thread is on cpu, then do context switch */ if (ut_curthr->ut_state == UT_ON_CPU) { ut_curthr->ut_state = UT_WAIT; uthread_switch(); } /* If the current thread is in the queue, remove it from the queue */ else if (ut_curthr->ut_state == UT_RUNNABLE) { ut_curthr->ut_state = UT_WAIT; utqueue_remove(&runq_table[ut_curthr->ut_prio], ut_curthr); } }
void* ufun2(void *arg) { printf("ufun2\n"); char **tmp = (char**)arg; uthread_t self = (uthread_t)tmp[0]; uthread_t parent = (uthread_t)tmp[1]; volatile void *ptr = self; while(ptr) { ptr = uthread_switch(self,parent,NULL); } return NULL; }
int main() { stack1 = (char*)malloc(4096); stack2 = (char*)malloc(4096); /* if use ucontext version char dummy_stack[4096]; uthread_t p = uthread_create(NULL,dummy_stack,0,NULL); */ uthread_t p = uthread_create(NULL,NULL,0,NULL); uthread_t u = uthread_create(p,stack1,4096,ufun1); uthread_switch(p,u,u); printf("main end\n"); return 0; };
/* * next选择方案,如果有goback优先选择goback作为下一个被运行的coro, * 否则取active_list_1首元素作为下一个被运行的coro,如果active_list_1 * 为空则直接返回. */ coro_t _sche_next_1(sche_t s,coro_t co) { coro_t next = NULL; coro_t coro_goback = co->_goback; if(NULL == coro_goback) { coro_t next = LINK_LIST_POP(coro_t,s->active_list_1); if(!next) return NULL; } else { next = coro_goback; co->_goback = NULL; } LINK_LIST_PUSH_BACK(s->active_list_2,co); assert(co != next); set_current_coro(next); return (coro_t)uthread_switch(co->ut,next->ut,co); }
void sche_sche_co(coro_t from,coro_t to) { set_current_coro(to); uthread_switch(from->ut,to->ut,from); }