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);
244 2b4b2ae1 2004-04-21 devnull errno = 0;
245 2517c38a 2004-02-29 devnull nn = read(fd, a, n);
246 2b4b2ae1 2004-04-21 devnull if(nn <= 0){
247 2517c38a 2004-02-29 devnull if(errno == EINTR)
248 2517c38a 2004-02-29 devnull goto again;
249 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
250 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'r', getcallerpc(&fd));
251 2517c38a 2004-02-29 devnull goto again;
254 2517c38a 2004-02-29 devnull return nn;
258 2517c38a 2004-02-29 devnull threadrecvfd(int fd)
262 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
264 2517c38a 2004-02-29 devnull nn = recvfd(fd);
265 2517c38a 2004-02-29 devnull if(nn < 0){
266 2517c38a 2004-02-29 devnull if(errno == EINTR)
267 2517c38a 2004-02-29 devnull goto again;
268 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
269 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'r', getcallerpc(&fd));
270 2517c38a 2004-02-29 devnull goto again;
273 2517c38a 2004-02-29 devnull return nn;
277 2517c38a 2004-02-29 devnull threadsendfd(int fd, int sfd)
281 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
283 2517c38a 2004-02-29 devnull nn = sendfd(fd, sfd);
284 2517c38a 2004-02-29 devnull if(nn < 0){
285 2517c38a 2004-02-29 devnull if(errno == EINTR)
286 2517c38a 2004-02-29 devnull goto again;
287 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
288 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'w', getcallerpc(&fd));
289 2517c38a 2004-02-29 devnull goto again;
292 2517c38a 2004-02-29 devnull return nn;
296 2517c38a 2004-02-29 devnull threadreadn(int fd, void *a, long n)
298 2517c38a 2004-02-29 devnull int tot, nn;
300 2517c38a 2004-02-29 devnull for(tot = 0; tot<n; tot+=nn){
301 2517c38a 2004-02-29 devnull nn = threadread(fd, (char*)a+tot, n-tot);
302 2517c38a 2004-02-29 devnull if(nn <= 0){
303 2517c38a 2004-02-29 devnull if(tot == 0)
304 2517c38a 2004-02-29 devnull return nn;
305 2517c38a 2004-02-29 devnull return tot;
308 2517c38a 2004-02-29 devnull return tot;
312 2517c38a 2004-02-29 devnull _threadwrite(int fd, const void *a, long n)
316 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
318 2517c38a 2004-02-29 devnull nn = write(fd, a, n);
319 2517c38a 2004-02-29 devnull if(nn < 0){
320 2517c38a 2004-02-29 devnull if(errno == EINTR)
321 2517c38a 2004-02-29 devnull goto again;
322 2517c38a 2004-02-29 devnull if(errno == EAGAIN || errno == EWOULDBLOCK){
323 c91bd328 2004-03-05 devnull _threadfdwait(fd, 'w', getcallerpc(&fd));
324 2517c38a 2004-02-29 devnull goto again;
327 2517c38a 2004-02-29 devnull return nn;
331 2517c38a 2004-02-29 devnull threadwrite(int fd, const void *a, long n)
333 2517c38a 2004-02-29 devnull int tot, nn;
335 2517c38a 2004-02-29 devnull for(tot = 0; tot<n; tot+=nn){
336 2517c38a 2004-02-29 devnull nn = _threadwrite(fd, (char*)a+tot, n-tot);
337 2517c38a 2004-02-29 devnull if(nn <= 0){
338 2517c38a 2004-02-29 devnull if(tot == 0)
339 2517c38a 2004-02-29 devnull return nn;
340 2517c38a 2004-02-29 devnull return tot;
343 2517c38a 2004-02-29 devnull return tot;