Blame


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 2517c38a 2004-02-29 devnull
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>
9 53dbac94 2004-03-02 devnull
10 53dbac94 2004-03-02 devnull #define debugpoll 0
11 53dbac94 2004-03-02 devnull
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
16 53dbac94 2004-03-02 devnull {
17 53dbac94 2004-03-02 devnull int fd;
18 53dbac94 2004-03-02 devnull int events;
19 53dbac94 2004-03-02 devnull int revents;
20 53dbac94 2004-03-02 devnull };
21 53dbac94 2004-03-02 devnull
22 53dbac94 2004-03-02 devnull int
23 53dbac94 2004-03-02 devnull poll(struct pollfd *p, int np, int ms)
24 53dbac94 2004-03-02 devnull {
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;
28 53dbac94 2004-03-02 devnull
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);
44 53dbac94 2004-03-02 devnull }
45 53dbac94 2004-03-02 devnull
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;
50 53dbac94 2004-03-02 devnull }else
51 53dbac94 2004-03-02 devnull tvp = nil;
52 53dbac94 2004-03-02 devnull
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);
62 53dbac94 2004-03-02 devnull }
63 53dbac94 2004-03-02 devnull fprint(2, "; tp=%p, t=%d.%d\n", tvp, tv.tv_sec, tv.tv_usec);
64 53dbac94 2004-03-02 devnull }
65 2517c38a 2004-02-29 devnull
66 53dbac94 2004-03-02 devnull n = select(maxfd+1, &rfd, &wfd, &efd, tvp);
67 53dbac94 2004-03-02 devnull
68 53dbac94 2004-03-02 devnull if(n <= 0)
69 53dbac94 2004-03-02 devnull return n;
70 53dbac94 2004-03-02 devnull
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;
80 53dbac94 2004-03-02 devnull }
81 53dbac94 2004-03-02 devnull return n;
82 53dbac94 2004-03-02 devnull }
83 53dbac94 2004-03-02 devnull
84 53dbac94 2004-03-02 devnull #else
85 53dbac94 2004-03-02 devnull #include <poll.h>
86 53dbac94 2004-03-02 devnull #endif
87 53dbac94 2004-03-02 devnull
88 2517c38a 2004-02-29 devnull /*
89 2517c38a 2004-02-29 devnull * Poll file descriptors in an idle loop.
90 2517c38a 2004-02-29 devnull */
91 2517c38a 2004-02-29 devnull
92 2517c38a 2004-02-29 devnull typedef struct Poll Poll;
93 2517c38a 2004-02-29 devnull
94 2517c38a 2004-02-29 devnull struct Poll
95 2517c38a 2004-02-29 devnull {
96 2517c38a 2004-02-29 devnull Channel *c; /* for sending back */
97 2517c38a 2004-02-29 devnull };
98 2517c38a 2004-02-29 devnull
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;
102 2517c38a 2004-02-29 devnull
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;
106 2517c38a 2004-02-29 devnull
107 2517c38a 2004-02-29 devnull static void
108 2517c38a 2004-02-29 devnull pollidle(void *v)
109 2517c38a 2004-02-29 devnull {
110 2517c38a 2004-02-29 devnull int i, n, t;
111 2517c38a 2004-02-29 devnull uint now;
112 2517c38a 2004-02-29 devnull
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;
118 2517c38a 2004-02-29 devnull }
119 2517c38a 2004-02-29 devnull t = -1;
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)
125 2517c38a 2004-02-29 devnull n = 0;
126 2517c38a 2004-02-29 devnull if(t == -1 || n < t)
127 2517c38a 2004-02-29 devnull t = n;
128 2517c38a 2004-02-29 devnull }
129 53dbac94 2004-03-02 devnull if(debugpoll) fprint(2, "; t=%d\n", t);
130 2517c38a 2004-02-29 devnull
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];
140 2517c38a 2004-02-29 devnull i--;
141 2517c38a 2004-02-29 devnull }
142 2517c38a 2004-02-29 devnull }
143 2517c38a 2004-02-29 devnull
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);
154 2517c38a 2004-02-29 devnull }
155 2517c38a 2004-02-29 devnull //fprint(2, "\n");
156 2517c38a 2004-02-29 devnull }
157 2517c38a 2004-02-29 devnull }
158 2517c38a 2004-02-29 devnull
159 2517c38a 2004-02-29 devnull void
160 2517c38a 2004-02-29 devnull threadfdwaitsetup(void)
161 2517c38a 2004-02-29 devnull {
162 2517c38a 2004-02-29 devnull static int setup = 0;
163 2517c38a 2004-02-29 devnull
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);
167 2517c38a 2004-02-29 devnull }
168 2517c38a 2004-02-29 devnull }
169 2517c38a 2004-02-29 devnull
170 2517c38a 2004-02-29 devnull void
171 c91bd328 2004-03-05 devnull _threadfdwait(int fd, int rw, ulong pc)
172 2517c38a 2004-02-29 devnull {
173 2517c38a 2004-02-29 devnull int i;
174 2517c38a 2004-02-29 devnull
175 2517c38a 2004-02-29 devnull struct {
176 2517c38a 2004-02-29 devnull Channel c;
177 2517c38a 2004-02-29 devnull ulong x;
178 2517c38a 2004-02-29 devnull } s;
179 2517c38a 2004-02-29 devnull
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)
184 2517c38a 2004-02-29 devnull break;
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();
189 2517c38a 2004-02-29 devnull }
190 2517c38a 2004-02-29 devnull npoll++;
191 2517c38a 2004-02-29 devnull }
192 2517c38a 2004-02-29 devnull
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);
199 2517c38a 2004-02-29 devnull }
200 2517c38a 2004-02-29 devnull
201 2517c38a 2004-02-29 devnull void
202 c91bd328 2004-03-05 devnull threadfdwait(int fd, int rw)
203 c91bd328 2004-03-05 devnull {
204 c91bd328 2004-03-05 devnull _threadfdwait(fd, rw, getcallerpc(&fd));
205 c91bd328 2004-03-05 devnull }
206 c91bd328 2004-03-05 devnull
207 c91bd328 2004-03-05 devnull void
208 2517c38a 2004-02-29 devnull threadsleep(int ms)
209 2517c38a 2004-02-29 devnull {
210 2517c38a 2004-02-29 devnull struct {
211 2517c38a 2004-02-29 devnull Channel c;
212 2517c38a 2004-02-29 devnull ulong x;
213 2517c38a 2004-02-29 devnull } s;
214 2517c38a 2004-02-29 devnull
215 2517c38a 2004-02-29 devnull threadfdwaitsetup();
216 2517c38a 2004-02-29 devnull chaninit(&s.c, sizeof(ulong), 1);
217 2517c38a 2004-02-29 devnull
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);
221 2517c38a 2004-02-29 devnull }
222 2517c38a 2004-02-29 devnull
223 2517c38a 2004-02-29 devnull void
224 2517c38a 2004-02-29 devnull threadfdnoblock(int fd)
225 2517c38a 2004-02-29 devnull {
226 2517c38a 2004-02-29 devnull fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
227 2517c38a 2004-02-29 devnull }
228 2517c38a 2004-02-29 devnull
229 2517c38a 2004-02-29 devnull long
230 2517c38a 2004-02-29 devnull threadread(int fd, void *a, long n)
231 2517c38a 2004-02-29 devnull {
232 2517c38a 2004-02-29 devnull int nn;
233 2517c38a 2004-02-29 devnull
234 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
235 2517c38a 2004-02-29 devnull again:
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;
243 2517c38a 2004-02-29 devnull }
244 2517c38a 2004-02-29 devnull }
245 2517c38a 2004-02-29 devnull return nn;
246 2517c38a 2004-02-29 devnull }
247 2517c38a 2004-02-29 devnull
248 2517c38a 2004-02-29 devnull int
249 2517c38a 2004-02-29 devnull threadrecvfd(int fd)
250 2517c38a 2004-02-29 devnull {
251 2517c38a 2004-02-29 devnull int nn;
252 2517c38a 2004-02-29 devnull
253 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
254 2517c38a 2004-02-29 devnull again:
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;
262 2517c38a 2004-02-29 devnull }
263 2517c38a 2004-02-29 devnull }
264 2517c38a 2004-02-29 devnull return nn;
265 2517c38a 2004-02-29 devnull }
266 2517c38a 2004-02-29 devnull
267 2517c38a 2004-02-29 devnull int
268 2517c38a 2004-02-29 devnull threadsendfd(int fd, int sfd)
269 2517c38a 2004-02-29 devnull {
270 2517c38a 2004-02-29 devnull int nn;
271 2517c38a 2004-02-29 devnull
272 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
273 2517c38a 2004-02-29 devnull again:
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;
281 2517c38a 2004-02-29 devnull }
282 2517c38a 2004-02-29 devnull }
283 2517c38a 2004-02-29 devnull return nn;
284 2517c38a 2004-02-29 devnull }
285 2517c38a 2004-02-29 devnull
286 2517c38a 2004-02-29 devnull long
287 2517c38a 2004-02-29 devnull threadreadn(int fd, void *a, long n)
288 2517c38a 2004-02-29 devnull {
289 2517c38a 2004-02-29 devnull int tot, nn;
290 2517c38a 2004-02-29 devnull
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;
297 2517c38a 2004-02-29 devnull }
298 2517c38a 2004-02-29 devnull }
299 2517c38a 2004-02-29 devnull return tot;
300 2517c38a 2004-02-29 devnull }
301 2517c38a 2004-02-29 devnull
302 2517c38a 2004-02-29 devnull long
303 2517c38a 2004-02-29 devnull _threadwrite(int fd, const void *a, long n)
304 2517c38a 2004-02-29 devnull {
305 2517c38a 2004-02-29 devnull int nn;
306 2517c38a 2004-02-29 devnull
307 2517c38a 2004-02-29 devnull threadfdnoblock(fd);
308 2517c38a 2004-02-29 devnull again:
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;
316 2517c38a 2004-02-29 devnull }
317 2517c38a 2004-02-29 devnull }
318 2517c38a 2004-02-29 devnull return nn;
319 2517c38a 2004-02-29 devnull }
320 2517c38a 2004-02-29 devnull
321 2517c38a 2004-02-29 devnull long
322 2517c38a 2004-02-29 devnull threadwrite(int fd, const void *a, long n)
323 2517c38a 2004-02-29 devnull {
324 2517c38a 2004-02-29 devnull int tot, nn;
325 2517c38a 2004-02-29 devnull
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;
332 2517c38a 2004-02-29 devnull }
333 2517c38a 2004-02-29 devnull }
334 2517c38a 2004-02-29 devnull return tot;
335 2517c38a 2004-02-29 devnull }
336 2517c38a 2004-02-29 devnull