staticvoidfd_reify(struct ev_loop *loop){int i;for(i =0; i < loop->fdchangecnt;++i){int fd = loop->fdchanges[i];// 取出文件描述符
ANFD *anfd = loop->anfds + fd;// 取出文件描述符数据
ev_io *w;unsignedchar o_events = anfd->events;unsignedchar o_reify = anfd->reify;
anfd->reify =0;{
anfd->events =0;// 汇总文件描述符的所有事件for(w =(ev_io *) anfd->head; w; w =(ev_io *)((WL) w)->next)
anfd->events |=(unsignedchar) w->events;if(o_events != anfd->events)
o_reify = EV__IOFDSET;}// 注册到 epoll, backend_modify 指向 epoll_modify if(o_reify & EV__IOFDSET)
loop->backend_modify(loop, fd, o_events, anfd->events);}
loop->fdchangecnt =0;}staticvoidepoll_modify(struct ev_loop *loop,int fd,int oev,int nev){struct epoll_event ev;unsignedchar oldmask;if(!nev)return;
oldmask = loop->anfds[fd].emask;
loop->anfds[fd].emask = nev;/*store the generation counter in the upper 32 bits, the fd in the lower 32 bits*/
ev.data.u64 =(uint64_t)(uint32_t) fd
|((uint64_t)(uint32_t)++loop->anfds[fd].egen <<32);
ev.events =(nev & EV_READ ? EPOLLIN :0)|(nev & EV_WRITE ? EPOLLOUT :0);// 注册事件if(expect_true (!epoll_ctl (backend_fd,
oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd,&ev)))return;if(expect_true (errno == ENOENT)){/* if ENOENT then the fd went away, so try to do the right thing */if(!nev)goto dec_egen;if(!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd,&ev))return;}elseif(expect_true (errno == EEXIST)){/* EEXIST means we ignored a previous DEL, but the fd is still active *//* if the kernel mask is the same as the new mask, we assume it hasn't changed */if(oldmask == nev)goto dec_egen;if(!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd,&ev))return;}elseif(expect_true (errno == EPERM)){/* EPERM means the fd is always ready, but epoll is too snobbish *//* to handle it, unlike select or poll. */
anfds [fd].emask = EV_EMASK_EPERM;/* add fd to epoll_eperms, if not already inside */if(!(oldmask & EV_EMASK_EPERM)){
array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt +1, EMPTY2);
epoll_eperms [epoll_epermcnt++]= fd;}return;}
fd_kill (EV_A_ fd);
dec_egen:/* we didn't successfully call epoll_ctl, so decrement the generation counter again */--anfds [fd].egen;}
staticvoid epoll_poll (struct ev_loop *loop, ev_tstamp timeout){int i;int eventcnt;if(expect_false (loop->epoll_epermcnt))
timeout =0.;// 等待事件发生
EV_RELEASE_CB;
eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, timeout *1e3);
EV_ACQUIRE_CB;if(expect_false (eventcnt <0)){if(errno != EINTR)
ev_syserr ("(libev) epoll_wait");return;}for(i =0; i < eventcnt;++i){struct epoll_event *ev = epoll_events + i;int fd =(uint32_t)ev->data.u64;/* mask out the lower 32 bits */int want = anfds [fd].events;int got =(ev->events &(EPOLLOUT | EPOLLERR | EPOLLHUP)? EV_WRITE :0)|(ev->events &(EPOLLIN | EPOLLERR | EPOLLHUP)? EV_READ :0);/*
* check for spurious notification.
* this only finds spurious notifications on egen updates
* other spurious notifications will be found by epoll_ctl, below
* we assume that fd is always in range, as we never shrink the anfds array
*/if(expect_false ((uint32_t)anfds [fd].egen !=(uint32_t)(ev->data.u64 >>32))){/* recreate kernel state */
postfork |=2;continue;}if(expect_false (got &~want)){
anfds [fd].emask = want;/*
* we received an event but are not interested in it, try mod or del
* this often happens because we optimistically do not unregister fds
* when we are no longer interested in them, but also when we get spurious
* notifications for fds from another process. this is partially handled
* above with the gencounter check (== our fd is not the event fd), and
* partially here, when epoll_ctl returns an error (== a child has the fd
* but we closed it).
*/
ev->events =(want & EV_READ ? EPOLLIN :0)|(want & EV_WRITE ? EPOLLOUT :0);/* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, *//* which is fortunately easy to do for us. */if(epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)){
postfork |=2;/* an error occurred, recreate kernel state */continue;}}// 把事件加入待处理列表
fd_event (EV_A_ fd, got);}/* if the receive array was full, increase its size */if(expect_false (eventcnt == epoll_eventmax)){
ev_free (epoll_events);
epoll_eventmax = array_nextsize (sizeof(struct epoll_event),
epoll_eventmax,
epoll_eventmax +1);
epoll_events =(struct epoll_event *)ev_malloc (sizeof(struct epoll_event)* epoll_eventmax);}/* now synthesize events for all fds where epoll fails, while select works... */for(i = epoll_epermcnt; i--;){int fd = epoll_eperms [i];unsignedchar events = anfds [fd].events &(EV_READ | EV_WRITE);if(anfds [fd].emask & EV_EMASK_EPERM && events)
fd_event (EV_A_ fd, events);else{
epoll_eperms [i]= epoll_eperms [--epoll_epermcnt];
anfds [fd].emask =0;}}}staticvoidfd_event(struct ev_loop *loop,int fd,int revents){
ANFD *anfd = loop->anfds + fd;if(expect_true (!anfd->reify))fd_event_nocheck(loop, fd, revents);}staticvoidfd_event_nocheck(struct ev_loop *loop,int fd,int revents){
ANFD *anfd = loop->anfds + fd;
ev_io *w;for(w =(ev_io *) anfd->head; w; w =(ev_io *)((ev_watcher_list *) w)->next){int ev = w->events & revents;if(ev)ev_feed_event(loop,(ev_watcher *) w, ev);}}voidev_feed_event(struct ev_loop *loop,void*w,int revents){
ev_watcher *w_ =(ev_watcher *) w;int pri = w_->priority -(EV_FEATURES &4?-2:0);if(expect_false (w_->pending))
loop->pendings[pri][w_->pending -1].events |= revents;else{
w_->pending =++loop->pendingcnt[pri];if(expect_false(w_->pending > loop->pendingmax[pri])){
loop->pendings[pri]=(ANPENDING *)array_realloc(sizeof(ANPENDING),
loop->pendings[pri],&loop->pendingmax[pri],
w_->pending
);};// 按优先级将事件放入 loop->pendings[][]
loop->pendings[pri][w_->pending -1].w = w_;
loop->pendings[pri][w_->pending -1].events = revents;}
loop->pendingpri =((EV_FEATURES &4)?+2:0)-((EV_FEATURES &4)?-2:0);}