#define NOPLAN9DEFINES #include #include #include #include #include #include #define debugpoll 0 #ifdef __APPLE__ #include enum { POLLIN=1, POLLOUT=2, POLLERR=4 }; struct pollfd { int fd; int events; int revents; }; int poll(struct pollfd *p, int np, int ms) { int i, maxfd, n; struct timeval tv, *tvp; fd_set rfd, wfd, efd; maxfd = -1; FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&efd); for(i=0; i maxfd) maxfd = p[i].fd; if(p[i].events & POLLIN) FD_SET(p[i].fd, &rfd); if(p[i].events & POLLOUT) FD_SET(p[i].fd, &wfd); FD_SET(p[i].fd, &efd); } if(ms != -1){ tv.tv_usec = (ms%1000)*1000; tv.tv_sec = ms/1000; tvp = &tv; }else tvp = nil; if(debugpoll){ fprint(2, "select %d:", maxfd+1); for(i=0; i<=maxfd; i++){ if(FD_ISSET(i, &rfd)) fprint(2, " r%d", i); if(FD_ISSET(i, &wfd)) fprint(2, " w%d", i); if(FD_ISSET(i, &efd)) fprint(2, " e%d", i); } fprint(2, "; tp=%p, t=%d.%d\n", tvp, tv.tv_sec, tv.tv_usec); } n = select(maxfd+1, &rfd, &wfd, &efd, tvp); if(n <= 0) return n; for(i=0; i #endif /* * Poll file descriptors in an idle loop. */ typedef struct Poll Poll; struct Poll { Channel *c; /* for sending back */ }; static Channel *sleepchan[64]; static int sleeptime[64]; static int nsleep; static struct pollfd pfd[64]; static struct Poll polls[64]; static int npoll; static void pollidle(void *v) { int i, n, t; uint now; for(;; yield()){ if(debugpoll) fprint(2, "poll %d:", npoll); for(i=0; i= nelem(polls)){ fprint(2, "Too many polled fds.\n"); abort(); } npoll++; } pfd[i].fd = fd; pfd[i].events = rw=='r' ? POLLIN : POLLOUT; polls[i].c = &s.c; if(0) fprint(2, "%s [%3d] fdwait %d %c list *0x%lux\n", argv0, threadid(), fd, rw, pc); recvul(&s.c); } void threadfdwait(int fd, int rw) { _threadfdwait(fd, rw, getcallerpc(&fd)); } void threadsleep(int ms) { struct { Channel c; ulong x; } s; threadfdwaitsetup(); chaninit(&s.c, sizeof(ulong), 1); sleepchan[nsleep] = &s.c; sleeptime[nsleep++] = p9nsec()/1000000+ms; recvul(&s.c); } void threadfdnoblock(int fd) { fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK); } long threadread(int fd, void *a, long n) { int nn; threadfdnoblock(fd); again: nn = read(fd, a, n); if(nn < 0){ if(errno == EINTR) goto again; if(errno == EAGAIN || errno == EWOULDBLOCK){ _threadfdwait(fd, 'r', getcallerpc(&fd)); goto again; } } return nn; } int threadrecvfd(int fd) { int nn; threadfdnoblock(fd); again: nn = recvfd(fd); if(nn < 0){ if(errno == EINTR) goto again; if(errno == EAGAIN || errno == EWOULDBLOCK){ _threadfdwait(fd, 'r', getcallerpc(&fd)); goto again; } } return nn; } int threadsendfd(int fd, int sfd) { int nn; threadfdnoblock(fd); again: nn = sendfd(fd, sfd); if(nn < 0){ if(errno == EINTR) goto again; if(errno == EAGAIN || errno == EWOULDBLOCK){ _threadfdwait(fd, 'w', getcallerpc(&fd)); goto again; } } return nn; } long threadreadn(int fd, void *a, long n) { int tot, nn; for(tot = 0; tot