#include #include #include #include "linuxsys.h" #include "linux.h" SYSCALL(sys_epoll_create) { int size; size = ARG1; RETURN(epoll_create(size)); } SYSCALL(sys_epoll_ctl) { int epfd; int op; int fd; epoll_event *event; epfd = ARG1; op = ARG2; fd = ARG3; event = (epoll_event*)ARG4; RETURN(epoll_ctl(epfd, op, fd, event)); } SYSCALL(sys_epoll_wait) { int epfd; epoll_event *events; int maxevents; int timeout; epfd = ARG1; events = (epoll_event*)ARG2; maxevents = ARG3; timeout = ARG4; RETURN(epoll_wait(epfd, events, maxevents, timeout)); } IOCTL(ioctl_FIONREAD) { int *p; int r; USED(cmd); p = (int*)arg; if(p==nil) return -EINVAL; r = buffdionread(fd); if(r < 0){ *p = 0; return r; } *p = r; return 0; } struct pollfd { int fd; short events; short revents; }; SYSCALL(sys_poll) { struct pollfd *fds; int nfds; long timeout; int epfd; int i, n; epoll_event *rev; fds = (struct pollfd*)ARG1; nfds = ARG2; timeout = ARG3; if(nfds <= 0) RETURN(-EINVAL); epfd = epoll_create(nfds); if(epfd < 0) RETURN(-EINVAL); for(i=0; iel[i]) || (wfds && wfds->el[i]) || (efds && efds->el[i]))) continue; for(j=0; j= nfds) goto start; ev.events = 0; if(rfds && (rfds->el[i] & bit)){ ev.events |= POLLIN; rfds->el[i] &= ~bit; } if(wfds && (wfds->el[i] & bit)){ ev.events |= POLLOUT; wfds->el[i] &= ~bit; } if(efds && (efds->el[i] & bit)){ ev.events |= POLLERR | POLLHUP | POLLRDHUP; efds->el[i] &= ~bit; } // no events selected, skip this fd if(ev.events == 0) continue; ev.data = fd; epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev); n++; } } start: // clear result fdsets if(n == 0){ _close(epfd); RETURN(0); } rev = malloc(sizeof(epoll_event) * n); if(rev == nil){ _close(epfd); RETURN(-ENOMEM); } if(tv==nil){ timeout = -1; } else { t = nsec(); timeout = (tv->tv_sec*1000) + (tv->tv_usec/1000); if(timeout < 0) timeout = 0; } n = epoll_wait(epfd, rev, n, timeout); _close(epfd); DPRINT("select ->\n"); nfds = 0; for(i=0; iel[j] |= bit; nfds++; } if(wfds && (rev[i].events&POLLOUT)){ DPRINT("O"); wfds->el[j] |= bit; nfds++; } if(efds && (rev[i].events&(POLLERR|POLLHUP|POLLRDHUP))){ DPRINT("E"); efds->el[j] |= bit; nfds++; } DPRINT("]\n"); } free(rev); DPRINT("got %d ready pollevents in total...", n); if(tv && timeout>=0){ t = timeout*1000000 - (nsec() - t); if(t < 0) t = 0; tv->tv_sec = (long)(t/1000000000LL); tv->tv_usec = (long)((t%1000000000LL)/1000LL); } DPRINT("select returns %d\n", n); RETURN(nfds); }