5 #include "threadimpl.h"
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)
182 chaninit(&s.c, sizeof(ulong), 1);
183 s.c.qentry = (volatile Alt**)s.qentry;
185 memset(s.qentry, 0, sizeof s.qentry);
186 for(i=0; i<npoll; i++)
190 if(npoll >= nelem(polls)){
191 fprint(2, "Too many polled fds.\n");
198 pfd[i].events = rw=='r' ? POLLIN : POLLOUT;
200 if(0) fprint(2, "%s [%3d] fdwait %d %c list *0x%lux\n",
201 argv0, threadid(), fd, rw, pc);
206 threadfdwait(int fd, int rw)
208 _threadfdwait(fd, rw, getcallerpc(&fd));
221 chaninit(&s.c, sizeof(ulong), 1);
222 s.c.qentry = (volatile Alt**)s.qentry;
224 memset(s.qentry, 0, sizeof s.qentry);
226 sleepchan[nsleep] = &s.c;
227 sleeptime[nsleep++] = p9nsec()/1000000+ms;
232 threadfdnoblock(int fd)
234 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
238 threadread(int fd, void *a, long n)
249 if(errno == EAGAIN || errno == EWOULDBLOCK){
250 _threadfdwait(fd, 'r', getcallerpc(&fd));
268 if(errno == EAGAIN || errno == EWOULDBLOCK){
269 _threadfdwait(fd, 'r', getcallerpc(&fd));
277 threadsendfd(int fd, int sfd)
283 nn = sendfd(fd, sfd);
287 if(errno == EAGAIN || errno == EWOULDBLOCK){
288 _threadfdwait(fd, 'w', getcallerpc(&fd));
296 threadreadn(int fd, void *a, long n)
300 for(tot = 0; tot<n; tot+=nn){
301 nn = threadread(fd, (char*)a+tot, n-tot);
312 _threadwrite(int fd, const void *a, long n)
318 nn = write(fd, a, n);
322 if(errno == EAGAIN || errno == EWOULDBLOCK){
323 _threadfdwait(fd, 'w', getcallerpc(&fd));
331 threadwrite(int fd, const void *a, long n)
335 for(tot = 0; tot<n; tot+=nn){
336 nn = _threadwrite(fd, (char*)a+tot, n-tot);