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>
5 c4097c29 2004-05-11 devnull #include "threadimpl.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;
178 1a8f27c3 2004-05-14 devnull Alt *qentry[2];
181 2517c38a 2004-02-29 devnull threadfdwaitsetup();
182 2517c38a 2004-02-29 devnull chaninit(&s.c, sizeof(ulong), 1);
183 c4097c29 2004-05-11 devnull s.c.qentry = (volatile Alt**)s.qentry;
184 c4097c29 2004-05-11 devnull s.c.nentry = 2;
185 c4097c29 2004-05-11 devnull memset(s.qentry, 0, sizeof s.qentry);
186 2517c38a 2004-02-29 devnull for(i=0; i<npoll; i++)
187 2517c38a 2004-02-29 devnull if(pfd[i].fd == -1)
189 2517c38a 2004-02-29 devnull if(i==npoll){
190 2517c38a 2004-02-29 devnull if(npoll >= nelem(polls)){
191 2517c38a 2004-02-29 devnull fprint(2, "Too many polled fds.\n");
192 2517c38a 2004-02-29 devnull abort();
194 2517c38a 2004-02-29 devnull npoll++;
197 2517c38a 2004-02-29 devnull pfd[i].fd = fd;
198 2517c38a 2004-02-29 devnull pfd[i].events = rw=='r' ? POLLIN : POLLOUT;
199 2517c38a 2004-02-29 devnull polls[i].c = &s.c;
200 4da83e7c 2004-03-05 devnull if(0) fprint(2, "%s [%3d] fdwait %d %c list *0x%lux\n",
201 c91bd328 2004-03-05 devnull argv0, threadid(), fd, rw, pc);
202 2517c38a 2004-02-29 devnull recvul(&s.c);
206 c91bd328 2004-03-05 devnull threadfdwait(int fd, int rw)
208 c91bd328 2004-03-05 devnull _threadfdwait(fd, rw, getcallerpc(&fd));
212 2517c38a 2004-02-29 devnull threadsleep(int ms)
214 2517c38a 2004-02-29 devnull struct {
215 2517c38a 2004-02-29 devnull Channel c;
216 2517c38a 2004-02-29 devnull ulong x;
217 1a8f27c3 2004-05-14 devnull Alt *qentry[2];
220 2517c38a 2004-02-29 devnull threadfdwaitsetup();
221 2517c38a 2004-02-29 devnull chaninit(&s.c, sizeof(ulong), 1);
222 1a8f27c3 2004-05-14 devnull s.c.qentry = (volatile Alt**)s.qentry;
223 1a8f27c3 2004-05-14 devnull s.c.nentry = 2;
224 1a8f27c3 2004-05-14 devnull memset(s.qentry, 0, sizeof s.qentry);
226 2517c38a 2004-02-29 devnull sleepchan[nsleep] = &s.c;
227 2517c38a 2004-02-29 devnull sleeptime[nsleep++] = p9nsec()/1000000+ms;
228 2517c38a 2004-02-29 devnull recvul(&s.c);
232 2517c38a 2004-02-29 devnull threadfdnoblock(int fd)
234 2517c38a 2004-02-29 devnull fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
238 2517c38a 2004-02-29 devnull threadread(int fd, void *a, long n)
242 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
245 c6687d45 2004-09-21 devnull * Always call wait (i.e. don't optimistically try the read)
246 c6687d45 2004-09-21 devnull * so that the scheduler gets a chance to run other threads.
248 c6687d45 2004-09-21 devnull _threadfdwait(fd, 'r', getcallerpc(&fd));
249 2b4b2ae1 2004-04-21 devnull errno = 0;
250 2517c38a 2004-02-29 devnull nn = read(fd, a, n);
251 2b4b2ae1 2004-04-21 devnull if(nn <= 0){
252 c6687d45 2004-09-21 devnull if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
253 2517c38a 2004-02-29 devnull goto again;
255 2517c38a 2004-02-29 devnull return nn;
259 2517c38a 2004-02-29 devnull threadrecvfd(int fd)
263 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
266 c6687d45 2004-09-21 devnull * Always call wait (i.e. don't optimistically try the recvfd)
267 c6687d45 2004-09-21 devnull * so that the scheduler gets a chance to run other threads.
269 c6687d45 2004-09-21 devnull _threadfdwait(fd, 'r', getcallerpc(&fd));
270 2517c38a 2004-02-29 devnull nn = recvfd(fd);
271 2517c38a 2004-02-29 devnull if(nn < 0){
272 c6687d45 2004-09-21 devnull if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
273 2517c38a 2004-02-29 devnull goto again;
275 2517c38a 2004-02-29 devnull return nn;
279 2517c38a 2004-02-29 devnull threadsendfd(int fd, int sfd)
283 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
286 c6687d45 2004-09-21 devnull * Always call wait (i.e. don't optimistically try the sendfd)
287 c6687d45 2004-09-21 devnull * so that the scheduler gets a chance to run other threads.
289 c6687d45 2004-09-21 devnull _threadfdwait(fd, 'w', getcallerpc(&fd));
290 2517c38a 2004-02-29 devnull nn = sendfd(fd, sfd);
291 2517c38a 2004-02-29 devnull if(nn < 0){
292 c6687d45 2004-09-21 devnull if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
293 2517c38a 2004-02-29 devnull goto again;
295 2517c38a 2004-02-29 devnull return nn;
299 2517c38a 2004-02-29 devnull threadreadn(int fd, void *a, long n)
301 2517c38a 2004-02-29 devnull int tot, nn;
303 2517c38a 2004-02-29 devnull for(tot = 0; tot<n; tot+=nn){
304 2517c38a 2004-02-29 devnull nn = threadread(fd, (char*)a+tot, n-tot);
305 2517c38a 2004-02-29 devnull if(nn <= 0){
306 2517c38a 2004-02-29 devnull if(tot == 0)
307 2517c38a 2004-02-29 devnull return nn;
308 2517c38a 2004-02-29 devnull return tot;
311 2517c38a 2004-02-29 devnull return tot;
315 2517c38a 2004-02-29 devnull _threadwrite(int fd, const void *a, long n)
319 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
322 c6687d45 2004-09-21 devnull * Always call wait (i.e. don't optimistically try the write)
323 c6687d45 2004-09-21 devnull * so that the scheduler gets a chance to run other threads.
325 c6687d45 2004-09-21 devnull _threadfdwait(fd, 'w', getcallerpc(&fd));
326 2517c38a 2004-02-29 devnull nn = write(fd, a, n);
327 2517c38a 2004-02-29 devnull if(nn < 0){
328 c6687d45 2004-09-21 devnull if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
329 2517c38a 2004-02-29 devnull goto again;
331 2517c38a 2004-02-29 devnull return nn;
335 2517c38a 2004-02-29 devnull threadwrite(int fd, const void *a, long n)
337 2517c38a 2004-02-29 devnull int tot, nn;
339 2517c38a 2004-02-29 devnull for(tot = 0; tot<n; tot+=nn){
340 2517c38a 2004-02-29 devnull nn = _threadwrite(fd, (char*)a+tot, n-tot);
341 2517c38a 2004-02-29 devnull if(nn <= 0){
342 2517c38a 2004-02-29 devnull if(tot == 0)
343 2517c38a 2004-02-29 devnull return nn;
344 2517c38a 2004-02-29 devnull return tot;
347 2517c38a 2004-02-29 devnull return tot;
351 9a4289cf 2004-06-09 devnull threadannounce(char *addr, char *dir)
353 9a4289cf 2004-06-09 devnull return p9announce(addr, dir);
357 9a4289cf 2004-06-09 devnull threadlisten(char *dir, char *newdir)
359 9a4289cf 2004-06-09 devnull int fd, ret;
360 9a4289cf 2004-06-09 devnull extern int _p9netfd(char*);
362 9a4289cf 2004-06-09 devnull fd = _p9netfd(dir);
363 9a4289cf 2004-06-09 devnull if(fd < 0){
364 9a4289cf 2004-06-09 devnull werrstr("bad 'directory' in listen: %s", dir);
365 9a4289cf 2004-06-09 devnull return -1;
367 9a4289cf 2004-06-09 devnull threadfdnoblock(fd);
368 9a4289cf 2004-06-09 devnull while((ret = p9listen(dir, newdir)) < 0 && errno==EAGAIN)
369 9a4289cf 2004-06-09 devnull _threadfdwait(fd, 'r', getcallerpc(&dir));
370 9a4289cf 2004-06-09 devnull return ret;
374 9a4289cf 2004-06-09 devnull threadaccept(int cfd, char *dir)
376 9a4289cf 2004-06-09 devnull return p9accept(cfd, dir);