1 2517c38a 2004-02-29 devnull #define NOPLAN9DEFINES
2 2517c38a 2004-02-29 devnull #include <u.h>
3 2517c38a 2004-02-29 devnull #include <libc.h>
4 2517c38a 2004-02-29 devnull #include <thread.h>
6 2517c38a 2004-02-29 devnull #include <errno.h>
7 2517c38a 2004-02-29 devnull #include <unistd.h>
8 2517c38a 2004-02-29 devnull #include <fcntl.h>
10 53dbac94 2004-03-02 devnull #define debugpoll 0
12 53dbac94 2004-03-02 devnull #ifdef __APPLE__
13 53dbac94 2004-03-02 devnull #include <sys/time.h>
14 53dbac94 2004-03-02 devnull enum { POLLIN=1, POLLOUT=2, POLLERR=4 };
15 53dbac94 2004-03-02 devnull struct pollfd
18 53dbac94 2004-03-02 devnull int events;
19 53dbac94 2004-03-02 devnull int revents;
23 53dbac94 2004-03-02 devnull poll(struct pollfd *p, int np, int ms)
25 53dbac94 2004-03-02 devnull int i, maxfd, n;
26 53dbac94 2004-03-02 devnull struct timeval tv, *tvp;
27 53dbac94 2004-03-02 devnull fd_set rfd, wfd, efd;
29 53dbac94 2004-03-02 devnull maxfd = -1;
30 53dbac94 2004-03-02 devnull FD_ZERO(&rfd);
31 53dbac94 2004-03-02 devnull FD_ZERO(&wfd);
32 53dbac94 2004-03-02 devnull FD_ZERO(&efd);
33 53dbac94 2004-03-02 devnull for(i=0; i<np; i++){
34 53dbac94 2004-03-02 devnull p[i].revents = 0;
35 53dbac94 2004-03-02 devnull if(p[i].fd == -1)
36 53dbac94 2004-03-02 devnull continue;
37 53dbac94 2004-03-02 devnull if(p[i].fd > maxfd)
38 53dbac94 2004-03-02 devnull maxfd = p[i].fd;
39 53dbac94 2004-03-02 devnull if(p[i].events & POLLIN)
40 53dbac94 2004-03-02 devnull FD_SET(p[i].fd, &rfd);
41 53dbac94 2004-03-02 devnull if(p[i].events & POLLOUT)
42 53dbac94 2004-03-02 devnull FD_SET(p[i].fd, &wfd);
43 53dbac94 2004-03-02 devnull FD_SET(p[i].fd, &efd);
46 53dbac94 2004-03-02 devnull if(ms != -1){
47 53dbac94 2004-03-02 devnull tv.tv_usec = (ms%1000)*1000;
48 53dbac94 2004-03-02 devnull tv.tv_sec = ms/1000;
49 53dbac94 2004-03-02 devnull tvp = &tv;
51 53dbac94 2004-03-02 devnull tvp = nil;
53 53dbac94 2004-03-02 devnull if(debugpoll){
54 53dbac94 2004-03-02 devnull fprint(2, "select %d:", maxfd+1);
55 53dbac94 2004-03-02 devnull for(i=0; i<=maxfd; i++){
56 53dbac94 2004-03-02 devnull if(FD_ISSET(i, &rfd))
57 53dbac94 2004-03-02 devnull fprint(2, " r%d", i);
58 53dbac94 2004-03-02 devnull if(FD_ISSET(i, &wfd))
59 53dbac94 2004-03-02 devnull fprint(2, " w%d", i);
60 53dbac94 2004-03-02 devnull if(FD_ISSET(i, &efd))
61 53dbac94 2004-03-02 devnull fprint(2, " e%d", i);
63 53dbac94 2004-03-02 devnull fprint(2, "; tp=%p, t=%d.%d\n", tvp, tv.tv_sec, tv.tv_usec);
66 53dbac94 2004-03-02 devnull n = select(maxfd+1, &rfd, &wfd, &efd, tvp);
68 53dbac94 2004-03-02 devnull if(n <= 0)
69 53dbac94 2004-03-02 devnull return n;
71 53dbac94 2004-03-02 devnull for(i=0; i<np; i++){
72 53dbac94 2004-03-02 devnull if(p[i].fd == -1)
73 53dbac94 2004-03-02 devnull continue;
74 53dbac94 2004-03-02 devnull if(FD_ISSET(p[i].fd, &rfd))
75 53dbac94 2004-03-02 devnull p[i].revents |= POLLIN;
76 53dbac94 2004-03-02 devnull if(FD_ISSET(p[i].fd, &wfd))
77 53dbac94 2004-03-02 devnull p[i].revents |= POLLOUT;
78 53dbac94 2004-03-02 devnull if(FD_ISSET(p[i].fd, &efd))
79 53dbac94 2004-03-02 devnull p[i].revents |= POLLERR;
81 53dbac94 2004-03-02 devnull return n;
85 53dbac94 2004-03-02 devnull #include <poll.h>
89 2517c38a 2004-02-29 devnull * Poll file descriptors in an idle loop.
92 2517c38a 2004-02-29 devnull typedef struct Poll Poll;
94 2517c38a 2004-02-29 devnull struct Poll
96 2517c38a 2004-02-29 devnull Channel *c; /* for sending back */
99 2517c38a 2004-02-29 devnull static Channel *sleepchan[64];
100 2517c38a 2004-02-29 devnull static int sleeptime[64];
101 2517c38a 2004-02-29 devnull static int nsleep;
103 2517c38a 2004-02-29 devnull static struct pollfd pfd[64];
104 2517c38a 2004-02-29 devnull static struct Poll polls[64];
105 2517c38a 2004-02-29 devnull static int npoll;
107 2517c38a 2004-02-29 devnull static void
108 2517c38a 2004-02-29 devnull pollidle(void *v)
110 2517c38a 2004-02-29 devnull int i, n, t;
111 2517c38a 2004-02-29 devnull uint now;
113 2517c38a 2004-02-29 devnull for(;; yield()){
114 53dbac94 2004-03-02 devnull if(debugpoll) fprint(2, "poll %d:", npoll);
115 2517c38a 2004-02-29 devnull for(i=0; i<npoll; i++){
116 53dbac94 2004-03-02 devnull if(debugpoll) fprint(2, " %d%c", pfd[i].fd, pfd[i].events==POLLIN ? 'r' : 'w');
117 2517c38a 2004-02-29 devnull pfd[i].revents = 0;
120 53dbac94 2004-03-02 devnull now = p9nsec()/1000000;
121 2517c38a 2004-02-29 devnull for(i=0; i<nsleep; i++){
122 2517c38a 2004-02-29 devnull n = sleeptime[i] - now;
123 53dbac94 2004-03-02 devnull if(debugpoll) fprint(2, " s%d", n);
124 2517c38a 2004-02-29 devnull if(n < 0)
126 2517c38a 2004-02-29 devnull if(t == -1 || n < t)
129 53dbac94 2004-03-02 devnull if(debugpoll) fprint(2, "; t=%d\n", t);
131 2517c38a 2004-02-29 devnull n = poll(pfd, npoll, t);
132 2517c38a 2004-02-29 devnull //fprint(2, "poll ret %d:", n);
133 2517c38a 2004-02-29 devnull now = p9nsec()/1000000;
134 2517c38a 2004-02-29 devnull for(i=0; i<nsleep; i++){
135 2517c38a 2004-02-29 devnull if((int)(sleeptime[i] - now) < 0){
136 2517c38a 2004-02-29 devnull nbsendul(sleepchan[i], 0);
137 2517c38a 2004-02-29 devnull nsleep--;
138 2517c38a 2004-02-29 devnull sleepchan[i] = sleepchan[nsleep];
139 2517c38a 2004-02-29 devnull sleeptime[i] = sleeptime[nsleep];
144 2517c38a 2004-02-29 devnull if(n <= 0)
145 2517c38a 2004-02-29 devnull continue;
146 2517c38a 2004-02-29 devnull for(i=0; i<npoll; i++)
147 2517c38a 2004-02-29 devnull if(pfd[i].fd != -1 && pfd[i].revents){
148 2517c38a 2004-02-29 devnull //fprint(2, " %d", pfd[i].fd);
149 2517c38a 2004-02-29 devnull pfd[i].fd = -1;
150 2517c38a 2004-02-29 devnull pfd[i].events = 0;
151 2517c38a 2004-02-29 devnull pfd[i].revents = 0;
152 4da83e7c 2004-03-05 devnull nbsendul(polls[i].c, 1);
153 4da83e7c 2004-03-05 devnull //fprint(2, " x%d", pfd[i].fd);
155 2517c38a 2004-02-29 devnull //fprint(2, "\n");
160 2517c38a 2004-02-29 devnull threadfdwaitsetup(void)
162 2517c38a 2004-02-29 devnull static int setup = 0;
164 2517c38a 2004-02-29 devnull if(!setup){
165 2517c38a 2004-02-29 devnull setup = 1;
166 2517c38a 2004-02-29 devnull threadcreateidle(pollidle, nil, 16384);
171 c91bd328 2004-03-05 devnull _threadfdwait(int fd, int rw, ulong pc)
175 2517c38a 2004-02-29 devnull struct {
176 2517c38a 2004-02-29 devnull Channel c;
177 2517c38a 2004-02-29 devnull ulong x;
180 2517c38a 2004-02-29 devnull threadfdwaitsetup();
181 2517c38a 2004-02-29 devnull chaninit(&s.c, sizeof(ulong), 1);
182 2517c38a 2004-02-29 devnull for(i=0; i<npoll; i++)
183 2517c38a 2004-02-29 devnull if(pfd[i].fd == -1)
185 2517c38a 2004-02-29 devnull if(i==npoll){
186 2517c38a 2004-02-29 devnull if(npoll >= nelem(polls)){
187 2517c38a 2004-02-29 devnull fprint(2, "Too many polled fds.\n");
188 2517c38a 2004-02-29 devnull abort();
190 2517c38a 2004-02-29 devnull npoll++;
193 2517c38a 2004-02-29 devnull pfd[i].fd = fd;
194 2517c38a 2004-02-29 devnull pfd[i].events = rw=='r' ? POLLIN : POLLOUT;
195 2517c38a 2004-02-29 devnull polls[i].c = &s.c;
196 4da83e7c 2004-03-05 devnull if(0) fprint(2, "%s [%3d] fdwait %d %c list *0x%lux\n",
197 c91bd328 2004-03-05 devnull argv0, threadid(), fd, rw, pc);
198 2517c38a 2004-02-29 devnull recvul(&s.c);
202 c91bd328 2004-03-05 devnull threadfdwait(int fd, int rw)
204 c91bd328 2004-03-05 devnull _threadfdwait(fd, rw, getcallerpc(&fd));
208 2517c38a 2004-02-29 devnull threadsleep(int ms)
210 2517c38a 2004-02-29 devnull struct {
211 2517c38a 2004-02-29 devnull Channel c;
212 2517c38a 2004-02-29 devnull ulong x;
215 2517c38a 2004-02-29 devnull threadfdwaitsetup();
216 2517c38a 2004-02-29 devnull chaninit(&s.c, sizeof(ulong), 1);
218 2517c38a 2004-02-29 devnull sleepchan[nsleep] = &s.c;
219 2517c38a 2004-02-29 devnull sleeptime[nsleep++] = p9nsec()/1000000+ms;
220 2517c38a 2004-02-29 devnull recvul(&s.c);
224 2517c38a 2004-02-29 devnull threadfdnoblock(int fd)
226 2517c38a 2004-02-29 devnull fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
230 2517c38a 2004-02-29 devnull threadread(int fd, void *a, long n)
234 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
236 2517c38a 2004-02-29 devnull nn = read(fd, a, n);
237 2517c38a 2004-02-29 devnull if(nn < 0){
238 2517c38a 2004-02-29 devnull if(errno == EINTR)
239 2517c38a 2004-02-29 devnull goto again;
240 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
241 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'r', getcallerpc(&fd));
242 2517c38a 2004-02-29 devnull goto again;
245 2517c38a 2004-02-29 devnull return nn;
249 2517c38a 2004-02-29 devnull threadrecvfd(int fd)
253 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
255 2517c38a 2004-02-29 devnull nn = recvfd(fd);
256 2517c38a 2004-02-29 devnull if(nn < 0){
257 2517c38a 2004-02-29 devnull if(errno == EINTR)
258 2517c38a 2004-02-29 devnull goto again;
259 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
260 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'r', getcallerpc(&fd));
261 2517c38a 2004-02-29 devnull goto again;
264 2517c38a 2004-02-29 devnull return nn;
268 2517c38a 2004-02-29 devnull threadsendfd(int fd, int sfd)
272 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
274 2517c38a 2004-02-29 devnull nn = sendfd(fd, sfd);
275 2517c38a 2004-02-29 devnull if(nn < 0){
276 2517c38a 2004-02-29 devnull if(errno == EINTR)
277 2517c38a 2004-02-29 devnull goto again;
278 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
279 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'w', getcallerpc(&fd));
280 2517c38a 2004-02-29 devnull goto again;
283 2517c38a 2004-02-29 devnull return nn;
287 2517c38a 2004-02-29 devnull threadreadn(int fd, void *a, long n)
289 2517c38a 2004-02-29 devnull int tot, nn;
291 2517c38a 2004-02-29 devnull for(tot = 0; tot<n; tot+=nn){
292 2517c38a 2004-02-29 devnull nn = threadread(fd, (char*)a+tot, n-tot);
293 2517c38a 2004-02-29 devnull if(nn <= 0){
294 2517c38a 2004-02-29 devnull if(tot == 0)
295 2517c38a 2004-02-29 devnull return nn;
296 2517c38a 2004-02-29 devnull return tot;
299 2517c38a 2004-02-29 devnull return tot;
303 2517c38a 2004-02-29 devnull _threadwrite(int fd, const void *a, long n)
307 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
309 2517c38a 2004-02-29 devnull nn = write(fd, a, n);
310 2517c38a 2004-02-29 devnull if(nn < 0){
311 2517c38a 2004-02-29 devnull if(errno == EINTR)
312 2517c38a 2004-02-29 devnull goto again;
313 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
314 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'w', getcallerpc(&fd));
315 2517c38a 2004-02-29 devnull goto again;
318 2517c38a 2004-02-29 devnull return nn;
322 2517c38a 2004-02-29 devnull threadwrite(int fd, const void *a, long n)
324 2517c38a 2004-02-29 devnull int tot, nn;
326 2517c38a 2004-02-29 devnull for(tot = 0; tot<n; tot+=nn){
327 2517c38a 2004-02-29 devnull nn = _threadwrite(fd, (char*)a+tot, n-tot);
328 2517c38a 2004-02-29 devnull if(nn <= 0){
329 2517c38a 2004-02-29 devnull if(tot == 0)
330 2517c38a 2004-02-29 devnull return nn;
331 2517c38a 2004-02-29 devnull return tot;
334 2517c38a 2004-02-29 devnull return tot;