14 enum { POLLIN=1, POLLOUT=2, POLLERR=4 };
23 poll(struct pollfd *p, int np, int ms)
26 struct timeval tv, *tvp;
39 if(p[i].events & POLLIN)
40 FD_SET(p[i].fd, &rfd);
41 if(p[i].events & POLLOUT)
42 FD_SET(p[i].fd, &wfd);
43 FD_SET(p[i].fd, &efd);
47 tv.tv_usec = (ms%1000)*1000;
54 fprint(2, "select %d:", maxfd+1);
55 for(i=0; i<=maxfd; i++){
63 fprint(2, "; tp=%p, t=%d.%d\n", tvp, tv.tv_sec, tv.tv_usec);
66 n = select(maxfd+1, &rfd, &wfd, &efd, tvp);
74 if(FD_ISSET(p[i].fd, &rfd))
75 p[i].revents |= POLLIN;
76 if(FD_ISSET(p[i].fd, &wfd))
77 p[i].revents |= POLLOUT;
78 if(FD_ISSET(p[i].fd, &efd))
79 p[i].revents |= POLLERR;
89 * Poll file descriptors in an idle loop.
92 typedef struct Poll Poll;
96 Channel *c; /* for sending back */
99 static Channel *sleepchan[64];
100 static int sleeptime[64];
103 static struct pollfd pfd[64];
104 static struct Poll polls[64];
114 if(debugpoll) fprint(2, "poll %d:", npoll);
115 for(i=0; i<npoll; i++){
116 if(debugpoll) fprint(2, " %d%c", pfd[i].fd, pfd[i].events==POLLIN ? 'r' : 'w');
120 now = p9nsec()/1000000;
121 for(i=0; i<nsleep; i++){
122 n = sleeptime[i] - now;
123 if(debugpoll) fprint(2, " s%d", n);
129 if(debugpoll) fprint(2, "; t=%d\n", t);
131 n = poll(pfd, npoll, t);
132 //fprint(2, "poll ret %d:", n);
133 now = p9nsec()/1000000;
134 for(i=0; i<nsleep; i++){
135 if((int)(sleeptime[i] - now) < 0){
136 nbsendul(sleepchan[i], 0);
138 sleepchan[i] = sleepchan[nsleep];
139 sleeptime[i] = sleeptime[nsleep];
146 for(i=0; i<npoll; i++)
147 if(pfd[i].fd != -1 && pfd[i].revents){
148 //fprint(2, " %d", pfd[i].fd);
152 nbsendul(polls[i].c, 1);
153 //fprint(2, " x%d", pfd[i].fd);
160 threadfdwaitsetup(void)
162 static int setup = 0;
166 threadcreateidle(pollidle, nil, 16384);
171 _threadfdwait(int fd, int rw, ulong pc)
181 chaninit(&s.c, sizeof(ulong), 1);
182 for(i=0; i<npoll; i++)
186 if(npoll >= nelem(polls)){
187 fprint(2, "Too many polled fds.\n");
194 pfd[i].events = rw=='r' ? POLLIN : POLLOUT;
196 if(0) fprint(2, "%s [%3d] fdwait %d %c list *0x%lux\n",
197 argv0, threadid(), fd, rw, pc);
202 threadfdwait(int fd, int rw)
204 _threadfdwait(fd, rw, getcallerpc(&fd));
216 chaninit(&s.c, sizeof(ulong), 1);
218 sleepchan[nsleep] = &s.c;
219 sleeptime[nsleep++] = p9nsec()/1000000+ms;
224 threadfdnoblock(int fd)
226 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
230 threadread(int fd, void *a, long n)
240 if(errno == EAGAIN || errno == EWOULDBLOCK){
241 _threadfdwait(fd, 'r', getcallerpc(&fd));
259 if(errno == EAGAIN || errno == EWOULDBLOCK){
260 _threadfdwait(fd, 'r', getcallerpc(&fd));
268 threadsendfd(int fd, int sfd)
274 nn = sendfd(fd, sfd);
278 if(errno == EAGAIN || errno == EWOULDBLOCK){
279 _threadfdwait(fd, 'w', getcallerpc(&fd));
287 threadreadn(int fd, void *a, long n)
291 for(tot = 0; tot<n; tot+=nn){
292 nn = threadread(fd, (char*)a+tot, n-tot);
303 _threadwrite(int fd, const void *a, long n)
309 nn = write(fd, a, n);
313 if(errno == EAGAIN || errno == EWOULDBLOCK){
314 _threadfdwait(fd, 'w', getcallerpc(&fd));
322 threadwrite(int fd, const void *a, long n)
326 for(tot = 0; tot<n; tot+=nn){
327 nn = _threadwrite(fd, (char*)a+tot, n-tot);