int _wait(void *socket, int fd, int rw) { startfdtask(); check(socket != NULL || fd >= 0, "Attempt to wait on a dead socket/fd: %p or %d", socket, fd); int max = 0; int hot_add = SuperPoll_active_hot(POLL) < SuperPoll_max_hot(POLL); int was_registered = 0; if(socket != NULL) { taskstate(rw == 'r' ? "read handler" : "write handler"); } else { was_registered = Register_fd_exists(fd) != NULL; taskstate(rw == 'r' ? "read fd" : "write fd"); } max = SuperPoll_add(POLL, (void *)taskrunning, socket, fd, rw, hot_add); check(max != -1, "Error adding fd: %d or socket: %p to task wait list.", fd, socket); taskswitch(); if(task_was_signaled()) { debug("GOT SIGNAL %d AFTER WAIT", taskrunning->signal); SuperPoll_del(POLL, socket, fd, hot_add); return -1; } if(was_registered && Register_fd_exists(fd) == NULL) { debug("Socket %d was closed after a wait.", fd); return -1; } else { return 0; } error: return -1; }
// 非阻塞的接收新连接 int netaccept(int fd, char *server, int *port) { int cfd, one; struct sockaddr_in sa; uchar *ip; socklen_t len; // 注册读事件, 出让 cpu 直到事件到来才会重新调度 fdwait(fd, 'r'); taskstate("netaccept"); len = sizeof sa; // accept 新连接 if((cfd = accept(fd, (void*)&sa, &len)) < 0){ taskstate("accept failed"); return -1; } if(server){ ip = (uchar*)&sa.sin_addr; snprint(server, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); } if(port) *port = ntohs(sa.sin_port); // 连接 fd 设置为非阻塞 fdnoblock(cfd); one = 1; setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one); taskstate("netaccept succeeded"); return cfd; }
int sockdial(char* name) { int fd, len; struct sockaddr_un sa; taskstate("sockdial"); if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { taskstate("socket failed"); return -1; } fdnoblock(fd); /* start connecting */ memset(&sa, 0, sizeof sa); sa.sun_family = AF_UNIX; strcpy(sa.sun_path, name); len = strlen(sa.sun_path) + sizeof(sa.sun_family); if(connect(fd, (struct sockaddr*)&sa, len) < 0 && errno != EINPROGRESS) { taskstate("connect failed"); close(fd); return -1; } fdwait(fd, 'w'); taskstate("connect succeeded"); return fd; }
// 链接server:port,链接成功返回fd int netdial(int istcp, char *server, int port) { int proto, fd, n; uint32_t ip; struct sockaddr_in sa; socklen_t sn; if(netlookup(server, &ip) < 0) return -1; taskstate("netdial"); proto = istcp ? SOCK_STREAM : SOCK_DGRAM; if((fd = socket(AF_INET, proto, 0)) < 0){ taskstate("socket failed"); return -1; } fdnoblock(fd); /* for udp */ if(!istcp){ n = 1; setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof n); } /* start connecting */ memset(&sa, 0, sizeof sa); memmove(&sa.sin_addr, &ip, 4); sa.sin_family = AF_INET; sa.sin_port = htons(port); if(connect(fd, (struct sockaddr*)&sa, sizeof sa) < 0 && errno != EINPROGRESS){ printf(">>>>>>> connect failed \n"); taskstate("connect failed"); close(fd); return -1; } /* wait for finish */ fdwait(fd, 'w'); sn = sizeof sa; if(getpeername(fd, (struct sockaddr*)&sa, &sn) >= 0){ taskstate("connect succeeded"); return fd; } /* report error */ sn = sizeof n; getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&n, &sn); if(n == 0) n = ECONNREFUSED; close(fd); taskstate("connect failed"); errno = n; return -1; }
void Action_task(void *v) { Action *action = (Action *)v; int rc = 0; pid_t child = 0; Profile *prof = Profile_load(action->profile_dir); taskname(bdata(action->name)); taskstate("depends"); rc = Rampart_wait(action->before); check(rc != -1, "A dependency failed to start, we can't start."); Rampart_running(&action->after); taskstate("ready"); debug("STARTED %s", bdata(action->name)); while(RUNNING) { taskstate("starting"); if(Unixy_still_running(prof->pid_file, &child)) { debug("Looks like %s is already running, we'll just leave it alone.", bdata(action->name)); } else { Unixy_remove_dead_pidfile(prof->pid_file); Action_exec(action, prof); } if(access(bdatae(prof->pid_file, ""), R_OK) != 0) { log_warn("%s didn't make pidfile %s. Waiting then trying again.", bdata(action->name), bdata(prof->pid_file)); Action_sleep(2); } taskstate("waiting"); while(Unixy_still_running(prof->pid_file, &child) && RUNNING) { Action_sleep(1); } if(!prof->restart) { break; } taskstate("restarting"); Action_sleep(1); } debug("ACTION %s exited.", bdata(action->name)); error: Rampart_failed(&action->after); return; }
// 开启监听 int netannounce(int istcp, char *server, int port) { int fd, n, proto; struct sockaddr_in sa; socklen_t sn; uint32_t ip; taskstate("netannounce"); // 协议是 tcp 还是 udp proto = istcp ? SOCK_STREAM : SOCK_DGRAM; memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; if(server != nil && strcmp(server, "*") != 0){ // 根据 server 来获取 ip,server 可以是 ip 或者域名 if(netlookup(server, &ip) < 0){ taskstate("netlookup failed"); return -1; } memmove(&sa.sin_addr, &ip, 4); } // 端口转为网络字节序, 忘了是大端还是小端,懒,不想查 sa.sin_port = htons(port); // 设置协议 if((fd = socket(AF_INET, proto, 0)) < 0){ taskstate("socket failed"); return -1; } /* set reuse flag for tcp */ // 设置 resue 选项, 当 time_wait 过多的时候,可以重用端口 if(istcp && getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0){ n = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); } // 绑定监听的地址和端口到 fd if(bind(fd, (struct sockaddr*)&sa, sizeof sa) < 0){ taskstate("bind failed"); close(fd); return -1; } // 如果是 tcp 就开启监听 if(proto == SOCK_STREAM) listen(fd, 16); // 设置为非阻塞 fdnoblock(fd); taskstate("netannounce succeeded"); return fd; }
void fdwait(int fd, int rw) { if(!startedfdtask){ startedfdtask = 1; epfd = epoll_create(1); assert(epfd >= 0); taskcreate(fdtask, 0, 32768 * 10); } taskstate("fdwait for %s", rw=='r' ? "read" : rw=='w' ? "write" : "error"); struct epoll_event ev = {0}; ev.data.ptr = taskrunning; switch(rw){ case 'r': ev.events |= EPOLLIN | EPOLLPRI; break; case 'w': ev.events |= EPOLLOUT; break; } int r = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); int duped = 0; if (r < 0 || errno == EEXIST) { duped = 1; fd = dup(fd); int r = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); assert(r == 0); } taskswitch(); epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev); if (duped) close(fd); }
void printres(resource_t *r) { switch(r->type){ case RSRC_PORT: kprintf(" PORT %U: (slave=%d) (size=%d) \"%s\"",r->id, ((port_t*)r)->slaved, ((port_t*)r)->msgcount,r->name); break; case RSRC_TASK: kprintf(" TASK %U: \"%s\"",r->id,r->name); kprintf(" : %s",taskstate((task_t*)r)); break; case RSRC_ASPACE: kprintf(" ASPACE %U: @ %x",r->id,((aspace_t*)r)->pdir[0]&0xFFFFF000); break; case RSRC_RIGHT: kprintf(" RIGHT %U: %x",r->id,((right_t*)r)->flags); break; case RSRC_SEM: kprintf(" SEM %U: (count=%d) \"%s\"", r->id,((sem_t*)r)->count,r->name); break; case RSRC_AREA: kprintf(" AREA %U: virt %x size %x pgroup %x (refcnt=%d)",r->id, ((area_t*)r)->virt_addr * 0x1000, ((area_t*)r)->length * 0x1000, ((area_t*)r)->pgroup, ((area_t*)r)->pgroup->refcount); break; case RSRC_QUEUE: kprintf(" QUEUE %U: (count=%d) \"%s\"",r->id,r->queue.count,r->name); break; case RSRC_TEAM: kprintf(" TEAM %U: \"%s\"",r->id,r->name); break; } }
void Handler_task(void *v) { int rc = 0; int i = 0; Handler *handler = (Handler *)v; HandlerParser *parser = NULL; int max_targets = Setting_get_int("limits.handler_targets", 128); log_info("MAX allowing limits.handler_targets=%d", max_targets); parser = HandlerParser_create(max_targets); check_mem(parser); check(Handler_setup(handler) == 0, "Failed to initialize handler, exiting."); while(handler->running && !task_was_signaled()) { taskstate("delivering"); rc = handler_recv_parse(handler, parser); if(task_was_signaled()) { log_warn("Handler task signaled, exiting."); break; } else if( rc == -1 || parser->target_count <= 0) { log_warn("Skipped invalid message from handler: %s", bdata(handler->send_spec)); taskdelay(100); continue; } else { for(i = 0; i < (int)parser->target_count; i++) { int id = (int)parser->targets[i]; int fd = Register_fd_for_id(id); Connection *conn = fd == -1 ? NULL : Register_fd_exists(fd); // don't bother calling process request if there's nothing to handle if(conn && fd >= 0) { handler_process_request(handler, id, fd, conn, parser->body); } else { // TODO: I believe we need to notify the connection that it is dead too Handler_notify_leave(handler, id); } } } HandlerParser_reset(parser); } handler->running = 0; handler->task = NULL; HandlerParser_destroy(parser); taskexit(0); error: log_err("HANDLER TASK DIED: %s", bdata(handler->send_spec)); handler->running = 0; handler->task = NULL; HandlerParser_destroy(parser); taskexit(1); }
// 建立一个socket,绑定本地某个端口,且监听 int netannounce(int istcp, char *server, int port) { int fd, n, proto; struct sockaddr_in sa; socklen_t sn; uint32_t ip; taskstate("netannounce"); proto = istcp ? SOCK_STREAM : SOCK_DGRAM; memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; if(server != nil && strcmp(server, "*") != 0){ if(netlookup(server, &ip) < 0){ taskstate("netlookup failed"); return -1; } memmove(&sa.sin_addr, &ip, 4); } sa.sin_port = htons(port); if((fd = socket(AF_INET, proto, 0)) < 0){ taskstate("socket failed"); return -1; } /* set reuse flag for tcp */ if(istcp && getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0){ n = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); } if(bind(fd, (struct sockaddr*)&sa, sizeof sa) < 0){ taskstate("bind failed"); close(fd); return -1; } if(proto == SOCK_STREAM) listen(fd, 16); fdnoblock(fd); taskstate("netannounce succeeded"); return fd; }
int netlookup(char *name, uint32_t *ip) { struct hostent *he; if(parseip(name, ip) >= 0) return 0; /* BUG - Name resolution blocks. Need a non-blocking DNS. */ taskstate("netlookup"); if((he = gethostbyname(name)) != 0){ *ip = *(uint32_t*)he->h_addr; taskstate("netlookup succeeded"); return 0; } taskstate("netlookup failed"); return -1; }
int taskyield(void) { int n; n = tasknswitch;//用来计算自愿放弃协程后,到恢复所发生的切换次数 taskready(taskrunning);//挂到taskrunqueue后面 taskstate("yield"); taskswitch(); return tasknswitch - n - 1; }
int taskyield(void) { int n; n = tasknswitch; taskready(taskrunning); taskstate("yield"); taskswitch(); return tasknswitch - n - 1; }
int sockaccept(int fd) { int cfd; struct sockaddr_un sa; socklen_t len; fdwait(fd, 'r'); taskstate("sockaccept"); len = sizeof sa; if((cfd = accept(fd, (void*)&sa, &len)) < 0) { taskstate("accept failed"); return -1; } fdnoblock(cfd); taskstate("sockaccept succeeded"); return cfd; }
/* * sleep and wakeup */ void tasksleep(Rendez *r) { addtask(&r->waiting, taskrunning); if (r->l) { qunlock(r->l); } taskstate("sleep"); taskswitch(); if (r->l) { qlock(r->l); } }
static int _rlock(RWLock *l, int block) { if(l->writer == nil && l->wwaiting.head == nil){ l->readers++; return 1; } if(!block) return 0; addtask(&l->rwaiting, taskrunning); taskstate("rlock"); taskswitch(); return 1; }
static int _wlock(RWLock *l, int block) { if(l->writer == nil && l->readers == 0){ l->writer = taskrunning; return 1; } if(!block) return 0; addtask(&l->wwaiting, taskrunning); taskstate("wlock"); taskswitch(); return 1; }
int netaccept(int fd, char *server, int *port) { int cfd, one; struct sockaddr_in sa; uchar *ip; socklen_t len; Task *t; fdwait(fd, 'r'); /* bv */ t = taskrunning; if (t->signaled) { return -1; } taskstate("netaccept"); len = sizeof sa; if((cfd = accept(fd, (void*)&sa, &len)) < 0){ taskstate("accept failed"); return -1; } if(server){ ip = (uchar*)&sa.sin_addr; snprintf(server, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); } if(port) *port = ntohs(sa.sin_port); fdnoblock(cfd); one = 1; setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one); taskstate("netaccept succeeded"); return cfd; }
// 协程让出 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); }
void fdwait(int fd, int rw) { int bits; #ifdef maysam_dbg fprintf(stderr,"fdwait on fd=%d 1 startedfdtask=%d\n",fd, startedfdtask); #endif if(!startedfdtask){ startedfdtask = 1; taskcreate(fdtask, 0, 32768); } #ifdef maysam_dbg fprintf(stderr,"fdwait on fd=%d 2\n",fd); #endif if(npollfd >= MAXFD){ fprint(2, "too many poll file descriptors\n"); abort(); } #ifdef maysam_dbg fprintf(stderr,"fdwait on fd=%d 3\n",fd); #endif taskstate("fdwait for %s", rw=='r' ? "read" : rw=='w' ? "write" : "error"); bits = 0; switch(rw){ case 'r': bits |= POLLIN; break; case 'w': bits |= POLLOUT; break; } #ifdef maysam_dbg fprintf(stderr,"fdwait on fd=%d 4\n",fd); #endif polltask[npollfd] = taskrunning; pollfd[npollfd].fd = fd; pollfd[npollfd].events = bits; pollfd[npollfd].revents = 0; npollfd++; #ifdef maysam_dbg fprintf(stderr,"fdwait on fd=%d before taskswitch\n"); #endif taskswitch(); }
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); }
/* * locking */ static int _qlock(QLock *l, int block) { if(l->owner == nil){ l->owner = taskrunning; return 1; } if(!block) return 0; addtask(&l->waiting, taskrunning); taskstate("qlock"); taskswitch(); if(l->owner != taskrunning){ fprint(2, "qlock: owner=%p self=%p oops\n", l->owner, taskrunning); abort(); } return 1; }
void Handler_task(void *v) { int rc = 0; int i = 0; Handler *handler = (Handler *)v; HandlerParser *parser = NULL; int max_targets = Setting_get_int("limits.handler_targets", 128); log_info("MAX allowing limits.handler_targets=%d", 128); parser = HandlerParser_create(max_targets); check_mem(parser); check(Handler_setup(handler) == 0, "Failed to initialize handler, exiting."); while(handler->running) { taskstate("delivering"); rc = handler_recv_parse(handler, parser); if(rc != -1 && parser->target_count > 0) { for(i = 0; i < (int)parser->target_count; i++) { int id = (int)parser->targets[i]; int fd = Register_fd_for_id(id); Connection *conn = (Connection *)Register_fd_exists(fd); handler_process_request(handler, id, fd, conn, parser->body); } } else { debug("Skipped invalid message from handler: %s", bdata(handler->send_spec)); } HandlerParser_reset(parser); } HandlerParser_destroy(parser); debug("HANDLER EXITED."); taskexit(0); error: HandlerParser_destroy(parser); log_err("HANDLER TASK DIED"); taskexit(1); }
int _wait(void *socket, int fd, int rw) { startfdtask(); int max = 0; int hot_add = SuperPoll_active_hot(POLL) < SuperPoll_max_hot(POLL); taskstate(rw == 'r' ? "read wait" : "write wait"); max = SuperPoll_add(POLL, (void *)taskrunning, socket, fd, rw, hot_add); check(max != -1, "Error adding fd %d to task wait list.", fd); taskswitch(); return 0; error: taskswitch(); return -1; }
static inline int handler_recv_parse(Handler *handler, HandlerParser *parser) { check(handler->running, "Called while handler wasn't running, that's not good."); zmq_msg_t *inmsg = calloc(sizeof(zmq_msg_t), 1); int rc = 0; check_mem(inmsg); rc = zmq_msg_init(inmsg); check(rc == 0, "Failed to initialize message."); taskstate("recv"); rc = mqrecv(handler->recv_socket, inmsg, ZMQ_NOBLOCK); check(rc == 0, "Receive on handler socket failed."); check(handler->running, "Received shutdown notification, goodbye."); rc = HandlerParser_execute(parser, zmq_msg_data(inmsg), zmq_msg_size(inmsg)); check(rc == 1, "Failed to parse message from handler."); check(parser->target_count > 0, "Message sent had 0 targets: %.*s", (int)zmq_msg_size(inmsg), (char *)zmq_msg_data(inmsg)); debug("Parsed message with %d targets, first: %d, uuid: %s, and body: %d", (int)parser->target_count, parser->targets[0], bdata(parser->uuid), blength(parser->body)); zmq_msg_close(inmsg); free(inmsg); return 0; error: if(inmsg) { zmq_msg_close(inmsg); free(inmsg); } return -1; }
static inline int handler_recv_parse(Handler *handler, HandlerParser *parser) { log_info("handler_recv_parse"); zmq_msg_t *inmsg = NULL; check(handler->running, "Called while handler wasn't running, that's not good."); inmsg = calloc(sizeof(zmq_msg_t), 1); int rc = 0; check_mem(inmsg); rc = zmq_msg_init(inmsg); check(rc == 0, "Failed to initialize message."); taskstate("recv"); rc = mqrecv(handler->recv_socket, inmsg, 0); check(rc == 0, "Receive on handler socket failed."); check(handler->running, "Handler marked as not running."); rc = HandlerParser_execute(parser, zmq_msg_data(inmsg), zmq_msg_size(inmsg)); log_info("handler_recv_parse - HandlerParser_execute %d", rc); check(rc == 1, "Failed to parse message from handler."); check(parser->target_count > 0, "Message sent had 0 targets: %.*s", (int)zmq_msg_size(inmsg), (char *)zmq_msg_data(inmsg)); zmq_msg_close(inmsg); free(inmsg); return 0; error: if(inmsg) { zmq_msg_close(inmsg); free(inmsg); } return -1; }
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); } } }