void wunlock(RWLock *l) { Task *t; if(l->writer == nil){ fprint(2, "wunlock: not locked\n"); abort(); } l->writer = nil; if(l->readers != 0){ fprint(2, "wunlock: readers\n"); abort(); } while((t = l->rwaiting.head) != nil){ deltask(&l->rwaiting, t); l->readers++; taskready(t); } if(l->readers == 0 && (t = l->wwaiting.head) != nil){ deltask(&l->wwaiting, t); l->writer = t; taskready(t); } }
int taskcreate(void (*fn)(void*), void *arg, uint stack) { int id; Task *t; //fprintf(stderr,"taskcreate 1\n"); t = taskalloc(fn, arg, stack); //fprintf(stderr,"taskcreate 2\n"); taskcount++; id = t->id; //fprintf(stderr,"taskcreate 3\n"); if(nalltask%64 == 0){ alltask = (Task**) realloc(alltask, (nalltask+64)*sizeof(alltask[0])); //fprintf(stderr,"taskcreate 4\n"); if(alltask == nil){ fprint(2, "out of memory\n"); abort(); } } //fprintf(stderr,"taskcreate 5\n"); t->alltaskslot = nalltask; alltask[nalltask++] = t; //fprintf(stderr,"taskcreate 6\n"); taskready(t); //fprintf(stderr,"taskcreate 7\n"); return id; }
/* a->op is Recv: 从对应得Channel的发送队列随机取出一个Alt, 并读取数据,Alt对应的Task可以进入就绪队列了 a->op is Send: 将数据拷贝到Buffer中 */ static void altexec(Alt *a) { int i; Altarray *ar; Alt *other; Channel *c; c = a->c; ar = chanarray(c, otherop(a->op)); if(ar && ar->n){ // 这里的逻辑目前看都是a->op == RECV才跑得到 i = rand()%ar->n; other = ar->a[i]; // a->v = other->v altcopy(a, other); // 将other从Channel的队列(接收队列)中删除 altalldequeue(other->xalt); other->xalt[0].xalt = other; // Task重新进入就绪队列 taskready(other->task); }else { // 将a->v的数据放到buffer里面 altcopy(a, nil); } }
// 使用函数 fn 创建一个新的协程, 并添加到协程队列 int taskcreate(void (*fn)(void*), void *arg, uint stack) { int id; Task *t; // 申请协程结构的空间以及初始化 t = taskalloc(fn, arg, stack); // 当前协程数目 +1 taskcount++; id = t->id; // 存储所有协程的数组是否需要扩容 // 为什么是 nalltask % 64 == 0 是扩容的条件? // 因为每次增加64,所以每当能整除的时候说明,空间用完 if(nalltask%64 == 0){ alltask = realloc(alltask, (nalltask+64)*sizeof(alltask[0])); if(alltask == nil){ fprint(2, "out of memory\n"); abort(); } } // 放到数组尾部 t->alltaskslot = nalltask; alltask[nalltask++] = t; // 协程状态设置为就绪, 可以进行调度 taskready(t); return id; }
void fdtask(void *v) { int i, ms; PollResult result; int rc = 0; rc = PollResult_init(POLL, &result); check(rc == 0, "Failed to initialize the poll result."); tasksystem(); taskname("fdtask"); for(;;){ /* let everyone else run */ while(taskyield() > 0) ; /* we're the only one runnable - poll for i/o */ errno = 0; taskstate("poll"); ms = next_task_sleeptime(500); if(SIGNALED) { for(i = 0; i < SuperPoll_active_hot(POLL); i++) { Task *target = (Task *)SuperPoll_data(POLL, i); if(target) taskready(target); SuperPoll_compact_down(POLL, i); } } else { rc = SuperPoll_poll(POLL, &result, ms); check(rc != -1, "SuperPoll failure, aborting."); for(i = 0; i < rc; i++) { taskready(result.hits[i].data); } } wake_sleepers(); } PollResult_clean(&result); taskexit(0); error: taskexitall(1); }
void runlock(RWLock *l) { Task *t; if (--l->readers == 0 && (t = l->wwaiting.head) != nil) { deltask(&l->wwaiting, t); l->writer = t; taskready(t); } }
int taskyield(void) { int n; n = tasknswitch; taskready(taskrunning); taskstate("yield"); taskswitch(); return tasknswitch - n - 1; }
int taskyield(void) { int n; n = tasknswitch;//用来计算自愿放弃协程后,到恢复所发生的切换次数 taskready(taskrunning);//挂到taskrunqueue后面 taskstate("yield"); taskswitch(); return tasknswitch - n - 1; }
void qunlock(QLock *l) { Task *ready; if (l->owner == 0) { fprint(2, "qunlock: owner=0\n"); abort(); } if ((l->owner = ready = l->waiting.head) != nil) { deltask(&l->waiting, ready); taskready(ready); } }
static inline void wake_sleepers() { Task *t; uvlong now = nsec(); while((t =sleeping.head) && now >= t->alarmtime){ deltask(&sleeping, t); if(!t->system && --sleepingcounted == 0) taskcount--; taskready(t); } }
// 协程让出 cpu int taskyield(void) { int n; n = tasknswitch; // 添加到就绪队列的尾部, 相当于让排在它后面的协程优先调度 taskready(taskrunning); // 状态标识为 yield taskstate("yield"); // 切换上下文 taskswitch(); // tasknswitch表示协程调度次数,出让到再次调用,两次相减就是出让的调度次数 return tasknswitch - n - 1; }
void fdtask(void *v) { int i, ms; PollResult result; int rc = 0; FDTASK = taskself(); rc = PollResult_init(POLL, &result); check(rc == 0, "Failed to initialize the poll result."); tasksystem(); taskname("fdtask"); for(;;){ /* let everyone else run */ while(taskyield() > 0) ; /* we're the only one runnable - poll for i/o */ errno = 0; taskstate("poll"); ms = next_task_sleeptime(500); if(task_was_signaled()) { fdtask_shutdown(); task_clear_signal(); break; } else { rc = SuperPoll_poll(POLL, &result, ms); check(rc != -1, "SuperPoll failure, aborting."); for(i = 0; i < rc; i++) { taskready(result.hits[i].data); } wake_sleepers(); } } PollResult_clean(&result); FDTASK = NULL; return; error: taskexitall(1); }
static int _taskwakeup(Rendez *r, int all) { int i; Task *t; for (i = 0;; ++i) { if (i == 1 && !all) { break; } if ((t = r->waiting.head) == nil) { break; } deltask(&r->waiting, t); taskready(t); } return i; }
static void altexec(Alt *a) { int i; Altarray *ar; Alt *other; Channel *c; c = a->c; ar = chanarray(c, otherop(a->op)); if(ar && ar->n){ i = rand()%ar->n; other = ar->a[i]; altcopy(a, other); altalldequeue(other->xalt); other->xalt[0].xalt = other; taskready(other->task); }else altcopy(a, nil); }
int taskcreate(void (*fn)(void*), void *arg, uint stack) { int id; Task *t; t = taskalloc(fn, arg, stack);//初始化申请Task数据结构,设置堆栈内容等 taskcount++;//当前OK的协程数目,不包括系统级别的协程 id = t->id; if(nalltask%64 == 0){//一次申请64个槽位,只能往后放 alltask = realloc(alltask, (nalltask+64)*sizeof(alltask[0])); if(alltask == nil){ fprint(2, "out of memory\n"); abort(); } } t->alltaskslot = nalltask; alltask[nalltask++] = t; taskready(t);//加入taskrunqueue的运行队列 return id; }
void fdtask(void *v) { int i, ms; Task *t; uvlong now; tasksystem(); taskname("fdtask"); for(;;){ //fprintf(stderr,"pooling0\n"); /* let everyone else run */ taskyield(); //fprintf(stderr,"\n after yield %d\n", maysamYieldRet); //while(taskyield() > 0); /* we're the only one runnable - poll for i/o */ errno = 0; taskstate("poll"); //Added by Maysam Yabandeh //taskname("fdtask(%d)",npollfd); if((t=sleeping.head) == nil) ms = -1; else{ /* sleep at most 5s */ now = nsec(); if(now >= t->alarmtime) ms = 0; else if(now+5*1000*1000*1000LL >= t->alarmtime) ms = (t->alarmtime - now)/1000000; else ms = 5000; } //Added by Maysam Yabandeh //if (ms == -1 && maysamYieldRet == 0) ms = 0; if (ms == -1) ms = 0; //fprintf(stderr,"pooling ms is %d npollfd is %d\n", ms, npollfd); #ifndef USE_SHM if(poll(pollfd, npollfd, ms) < 0){ //fprintf(stderr,"pooling error\n"); if(errno == EINTR) continue; fprint(2, "poll: %s\n", strerror(errno)); taskexitall(0); } //fprintf(stderr,"pooling2\n"); /* wake up the guys who deserve it */ for(i=0; i<npollfd; i++){ while(i < npollfd && pollfd[i].revents){ //fprintf(stderr,"pooling3\n"); taskready(polltask[i]); --npollfd; pollfd[i] = pollfd[npollfd]; polltask[i] = polltask[npollfd]; } } #else /* wake up the guys who deserve it */ //extern mpass::MessageEndPoint msg_end_point; mpass::MessageEndPoint *end_point = &mpass::msg_end_point; for(i=0; i<npollfd; i++){ int &fd = pollfd[i].fd; bool read = pollfd[i].events & POLLIN; mpass::Connection *conn = &end_point->conn_array[fd]; if ( (read && !conn->rcv_q->is_empty()) || (!read && !conn->snd_q->is_full()) ) { taskready(polltask[i]); --npollfd; pollfd[i] = pollfd[npollfd]; polltask[i] = polltask[npollfd]; } } #endif //fprintf(stderr,"pooling4\n"); now = nsec(); while((t=sleeping.head) && now >= t->alarmtime){ //fprintf(stderr,"pooling5\n"); deltask(&sleeping, t); if(!t->system && --sleepingcounted == 0) taskcount--; taskready(t); } } }
void fdtask(void *v) { int i, ms; Task *t; uvlong now; tasksystem(); taskname("fdtask"); struct epoll_event events[20000]; for(;;){ /* let everyone else run */ while(taskyield() > 0) ; /* we're the only one runnable - epoll for i/o */ errno = 0; taskstate("epoll"); if(sleeping.head == nil && blocking.head == nil) ms = -1; else{ /* sleep at most 100ms */ now = nsec(); if (t) { if(now >= t->alarmtime) ms = 0; else if(now+500*1000*1000LL >= t->alarmtime) ms = (t->alarmtime - now)/1000000; else ms = 500; }else{ ms = 500; } } int nevents; if((nevents = epoll_wait(epfd, events, 20000, ms)) < 0){ if(errno == EINTR) continue; fprint(2, "epoll: %s\n", strerror(errno)); taskexitall(0); } /* wake up the guys who deserve it */ for(i=0; i<nevents; i++){ //deleting it from blocking queue for (t = blocking.head; t!= nil && t!= events[i].data.ptr; t=t->next) ; if(t==events[i].data.ptr) deltask(&blocking,t); taskready((Task *)events[i].data.ptr); } now = nsec(); while((t=sleeping.head) && now >= t->alarmtime){ deltask(&sleeping, t); if(!t->system && --sleepingcounted == 0) taskcount--; taskready(t); } /*wake up the guys who are blocked */ while((t=blocking.head) && now >= t->alarmtime){ deltask(&blocking, t); if(!t->system && --blockingcounted == 0) taskcount--; taskready(t); } } }