1 #if defined(HAS_DEVPOLL)
2 #include <sys/devpoll.h>
3 static int dpfd=0;
4 static struct pollfd *Pollfd=0;
5 static int pollMax=200;
6 static int Nfds;
7
8 #define MAXFD 65000
9
10 typedef struct _fdToEvent {
11 pe_io *ev;
12 } FdToEvent;
13
14 static FdToEvent fdToEvent[MAXFD];
15 #endif /*HAS_DEVPOLL*/
16
boot_devpoll()17 static void boot_devpoll() {
18 #if defined(HAS_DEVPOLL)
19 memset(fdToEvent, 0, MAXFD*sizeof(FdToEvent));
20
21 EvNew(9, Pollfd, pollMax, struct pollfd);
22
23 /* Open /dev/poll driver */
24 if (!dpfd) {
25 fprintf(stderr, "INIT Open /dev/poll!!!\n");
26 if ((dpfd = open("/dev/poll", O_RDWR)) < 0) {
27 croak("Event: Can't open /dev/poll!\n");
28 }
29 }
30 #endif /*HAS_DEVPOLL*/
31 }
32
pe_sys_fileno(SV * sv,char * context)33 static int pe_sys_fileno(SV *sv, char *context) {
34 IO *io;
35 PerlIO *fp;
36
37 if (!sv)
38 croak("Event %s: no filehandle available", context);
39 if (SvGMAGICAL(sv))
40 mg_get(sv);
41 if (SvIOK(sv)) /* maybe non-portable but nice for unixen */
42 return SvIV(sv);
43 if (SvROK(sv))
44 sv = SvRV(sv);
45 if (SvTYPE(sv) == SVt_PVGV) {
46 if (!(io=GvIO((GV*)sv)) || !(fp = IoIFP(io))) {
47 croak("Event '%s': GLOB(0x%x) isn't a valid IO", context, sv);
48 }
49 return PerlIO_fileno(fp);
50 }
51 sv_dump(sv);
52 croak("Event '%s': can't find fileno", context);
53 return -1;
54 }
55
_queue_io(pe_io * wa,int got)56 static void _queue_io(pe_io *wa, int got) {
57 pe_ioevent *ev;
58 got &= wa->poll;
59 if (!got) {
60 if (WaDEBUGx(wa) >= 3) {
61 STRLEN n_a;
62 warn("Event: io '%s' queued nothing", SvPV(wa->base.desc, n_a));
63 }
64 return;
65 }
66 ev = (pe_ioevent*) (*wa->base.vtbl->new_event)((pe_watcher*) wa);
67 ++ev->base.hits;
68 ev->got |= got;
69 queueEvent((pe_event*) ev);
70 }
71
72 /************************************************* DEVPOLL */
73 #if defined(HAS_DEVPOLL) && !PE_SYS_IO
74 #define PE_SYS_IO 1
75
pe_sys_sleep(NV left)76 static void pe_sys_sleep(NV left) {
77 int ret;
78 NV t0 = NVtime();
79 NV t1 = t0 + left;
80 while (1) {
81 ret = poll(0, 0, (int) (left * 1000)); /* hope zeroes okay */
82 if (ret < 0 && errno != EAGAIN && errno != EINTR)
83 croak("poll(%.2f) got errno %d", left, errno);
84 left = t1 - NVtime();
85 if (left > IntervalEpsilon) {
86 if (ret==0) ++TimeoutTooEarly;
87 continue;
88 }
89 break;
90 }
91 }
92
pe_sys_io_add(pe_io * ev)93 static void pe_sys_io_add (pe_io *ev) {
94 struct pollfd tmp_pfd;
95 int bits=0;
96
97 if (ev->fd <= 0 || ev->fd > MAXFD) {
98 croak("pe_sys_io_add: non-valid fd (%d)", ev->fd);
99 return;
100 }
101
102 if (ev->poll & PE_R) bits |= (POLLIN | POLLPRI);
103 if (ev->poll & PE_W) bits |= POLLOUT;
104 if (ev->poll & PE_E) bits |= (POLLRDBAND | POLLPRI);
105
106 tmp_pfd.fd = ev->fd;
107 tmp_pfd.events = bits;
108
109 if (write(dpfd, &tmp_pfd, sizeof(struct pollfd)) !=
110 sizeof(struct pollfd)) {
111 fprintf(stderr, "pe_sys_io_add(fd %d): could not write fd to /dev/poll",
112 dpfd);
113 return;
114 }
115
116 if (fdToEvent[ev->fd].ev != NULL) {
117 fprintf(stderr, "pe_sys_io_add(fd %d): mapping between fd and event already exists!", ev->fd);
118 } else {
119 fdToEvent[ev->fd].ev = ev;
120 }
121 }
122
pe_sys_io_del(pe_io * ev)123 static void pe_sys_io_del (pe_io *ev) {
124 struct pollfd tmp_pfd;
125 int bits=0;
126
127 if (ev-> fd <= 0) {
128 return;
129 }
130
131 if (ev->poll & PE_R) bits |= (POLLIN | POLLPRI);
132 if (ev->poll & PE_W) bits |= POLLOUT;
133 if (ev->poll & PE_E) bits |= (POLLRDBAND | POLLPRI);
134
135 tmp_pfd.fd = ev->fd;
136 tmp_pfd.events = POLLREMOVE;
137
138 if (write(dpfd, &tmp_pfd, sizeof(struct pollfd)) !=
139 sizeof(struct pollfd)) {
140 fprintf(stderr, "pe_sys_io_del(fd %d): could not write fd to /dev/poll", dpfd);
141 }
142
143 fdToEvent[ev->fd].ev = NULL;
144 }
145
pe_sys_multiplex(NV timeout)146 static void pe_sys_multiplex(NV timeout) {
147 pe_io *ev;
148 int xx, got, mask, fd;
149 int ret;
150 int err, m_rfds;
151 struct dvpoll dopoll;
152
153 if (pollMax < IOWatchCount) {
154 if (Pollfd)
155 EvFree(9, Pollfd);
156 pollMax = IOWatchCount*2;
157 EvNew(9, Pollfd, pollMax, struct pollfd);
158 IOWatch_OK = 0;
159 }
160
161
162 if (!IOWatch_OK) {
163 Nfds = 0;
164 if (Pollfd)
165 Zero(Pollfd, pollMax, struct pollfd);
166 ev = (pe_io*) IOWatch.next->self;
167 while (ev) {
168 int fd = ev->fd;
169 ev->xref = -1;
170 assert(fd >= 0); {
171 int bits=0;
172 if (ev->poll & PE_R) bits |= (POLLIN | POLLPRI);
173 if (ev->poll & PE_W) bits |= POLLOUT;
174 if (ev->poll & PE_E) bits |= (POLLRDBAND | POLLPRI);
175 assert(bits); {
176 Pollfd[Nfds].fd = fd;
177 Pollfd[Nfds].events |= bits;
178 Nfds++;
179 }
180 }
181 ev = (pe_io*) ev->ioring.next->self;
182 }
183 IOWatch_OK = 1;
184 }
185
186 for (xx=0; xx < Nfds; xx++)
187 Pollfd[xx].revents = 0; /* needed? XXX */
188
189 if (timeout < 0)
190 timeout = 0;
191
192 dopoll.dp_timeout = (int) (timeout * 1000);
193 dopoll.dp_nfds = pollMax;
194 dopoll.dp_fds = Pollfd;
195
196 /* Wait for I/O events the clients are interested in */
197 m_rfds = ioctl(dpfd, DP_POLL, &dopoll);
198 if (m_rfds == -1) {
199 err = errno;
200 fprintf(stderr, "pe_sys_multiplex: poll() returned -1, errno %d\n", err);
201 return;
202 }
203
204 while (m_rfds >= 1) {
205 m_rfds--;
206 fd = Pollfd[m_rfds].fd;
207 ev = fdToEvent[fd].ev;
208 got = 0;
209 mask = Pollfd[m_rfds].revents;
210 if (mask & (POLLIN | POLLPRI | POLLHUP | POLLERR)) got |= PE_R;
211 if (mask & (POLLOUT | POLLERR)) got |= PE_W;
212 if (mask & (POLLRDBAND | POLLPRI | POLLHUP | POLLERR)) got |= PE_E;
213 if (mask & POLLNVAL) {
214 STRLEN n_a;
215 warn("Event: '%s' was unexpectedly closed",
216 SvPV(ev->base.desc, n_a));
217 pe_io_reset_handle((pe_watcher*) ev);
218 } else {
219 if ((mask & POLLHUP) && (ev->poll & PE_W) && (!(got & PE_W))
220 && (!(ev->poll & PE_R)) && (!(ev->poll & PE_E))) {
221 /* Must notify about POLLHUP _some_ way - Allen */
222 got |= PE_W;
223 }
224 }
225
226 if (got) _queue_io(ev, got);
227
228 }
229 }
230 #endif /*HAS_DEVPOLL*/
231
232 /************************************************* POLL */
233 #if defined(HAS_POLL) && !PE_SYS_IO
234 #define PE_SYS_IO 1
235
236 static struct pollfd *Pollfd=0;
237 static int pollMax=0;
238 static int Nfds;
239
pe_sys_sleep(NV left)240 static void pe_sys_sleep(NV left) {
241 int ret;
242 NV t0 = NVtime();
243 NV t1 = t0 + left;
244 while (1) {
245 ret = poll(0, 0, (int) (left * 1000)); /* hope zeroes okay */
246 if (ret < 0 && errno != EAGAIN && errno != EINTR)
247 croak("poll(%.2f) got errno %d", left, errno);
248 left = t1 - NVtime();
249 if (left > IntervalEpsilon) {
250 if (ret==0) ++TimeoutTooEarly;
251 continue;
252 }
253 break;
254 }
255 }
256
pe_sys_io_add(pe_io * ev)257 static void pe_sys_io_add (pe_io *ev) {}
pe_sys_io_del(pe_io * ev)258 static void pe_sys_io_del (pe_io *ev) {}
259
pe_sys_multiplex(NV timeout)260 static void pe_sys_multiplex(NV timeout) {
261 pe_io *ev;
262 int xx;
263 int ret;
264 if (pollMax < IOWatchCount) {
265 if (Pollfd)
266 EvFree(9, Pollfd);
267 pollMax = IOWatchCount+5;
268 EvNew(9, Pollfd, pollMax, struct pollfd);
269 IOWatch_OK = 0;
270 }
271 if (!IOWatch_OK) {
272 Nfds = 0;
273 if (Pollfd)
274 Zero(Pollfd, pollMax, struct pollfd);
275 ev = (pe_io*) IOWatch.next->self;
276 while (ev) {
277 int fd = ev->fd;
278 ev->xref = -1;
279 assert(fd >= 0); {
280 int bits=0;
281 if (ev->poll & PE_R) bits |= (POLLIN | POLLPRI);
282 if (ev->poll & PE_W) bits |= POLLOUT;
283 if (ev->poll & PE_E) bits |= (POLLRDBAND | POLLPRI);
284 assert(bits); {
285 int ok=0;;
286 for (xx = 0; xx < Nfds; xx++) {
287 if (Pollfd[xx].fd == fd) { ok=1; break; }
288 }
289 if (!ok) xx = Nfds++;
290 Pollfd[xx].fd = fd;
291 Pollfd[xx].events |= bits;
292 ev->xref = xx;
293 }
294 }
295 ev = (pe_io*) ev->ioring.next->self;
296 }
297 IOWatch_OK = 1;
298 }
299 for (xx=0; xx < Nfds; xx++)
300 Pollfd[xx].revents = 0; /* needed? XXX */
301 if (timeout < 0)
302 timeout = 0;
303 ret = poll(Pollfd, Nfds, (int) (timeout * 1000));
304
305 if (ret < 0) {
306 if (errno == EINTR || errno == EAGAIN)
307 return;
308 if (errno == EINVAL) {
309 warn("poll: bad args %d %.2f", Nfds, timeout);
310 return;
311 }
312 warn("poll got errno %d", errno);
313 return;
314 }
315 ev = (pe_io*) IOWatch.next->self;
316 while (ev) {
317 pe_io *next_ev = (pe_io*) ev->ioring.next->self;
318 STRLEN n_a;
319 int xref = ev->xref;
320 if (xref >= 0) {
321 int got = 0;
322 int mask = Pollfd[xref].revents;
323 if (mask & (POLLIN | POLLPRI | POLLHUP | POLLERR)) got |= PE_R;
324 if (mask & (POLLOUT | POLLERR)) got |= PE_W;
325 if (mask & (POLLRDBAND | POLLPRI | POLLHUP | POLLERR)) got |= PE_E;
326 if (mask & POLLNVAL) {
327 warn("Event: '%s' was unexpectedly closed",
328 SvPV(ev->base.desc, n_a));
329 pe_io_reset_handle((pe_watcher*) ev);
330 } else {
331 if ((mask & POLLHUP) && (ev->poll & PE_W) && (!(got & PE_W))
332 && (!(ev->poll & PE_R)) && (!(ev->poll & PE_E))) {
333 /* Must notify about POLLHUP _some_ way - Allen */
334 got |= PE_W;
335 }
336
337 if (got) _queue_io(ev, got);
338 /*
339 Can only do this if fd-to-watcher is 1-to-1
340 if (--ret == 0) { ev=0; continue; }
341 */
342 }
343 }
344 ev = next_ev;
345 }
346 }
347 #endif /*HAS_POLL*/
348
349
350 /************************************************* SELECT */
351 #if defined(HAS_SELECT) && !PE_SYS_IO
352 #define PE_SYS_IO 1
353
354 static int Nfds;
355 static fd_set Rfds, Wfds, Efds;
356
pe_sys_sleep(NV left)357 static void pe_sys_sleep(NV left) {
358 struct timeval tm;
359 NV t0 = NVtime();
360 NV t1 = t0 + left;
361 int ret;
362 while (1) {
363 tm.tv_sec = left;
364 tm.tv_usec = (left - tm.tv_sec) * 1000000;
365 ret = select(0, 0, 0, 0, &tm);
366 if (ret < 0 && errno != EINTR && errno != EAGAIN)
367 croak("select(%.2f) got errno %d", left, errno);
368 left = t1 - NVtime();
369 if (left > IntervalEpsilon) {
370 if (ret==0) ++TimeoutTooEarly;
371 continue;
372 }
373 break;
374 }
375 }
376
pe_sys_io_add(pe_io * ev)377 static void pe_sys_io_add (pe_io *ev) {}
pe_sys_io_del(pe_io * ev)378 static void pe_sys_io_del (pe_io *ev) {}
379
pe_sys_multiplex(NV timeout)380 static void pe_sys_multiplex(NV timeout) {
381 struct timeval tm;
382 int ret;
383 fd_set rfds, wfds, efds;
384 pe_io *ev;
385
386 if (!IOWatch_OK) {
387 Nfds = -1;
388 FD_ZERO(&Rfds);
389 FD_ZERO(&Wfds);
390 FD_ZERO(&Efds);
391 ev = IOWatch.next->self;
392 while (ev) {
393 int fd = ev->fd;
394 if (fd >= 0) {
395 int bits=0;
396 if (ev->poll & PE_R) { FD_SET(fd, &Rfds); ++bits; }
397 if (ev->poll & PE_W) { FD_SET(fd, &Wfds); ++bits; }
398 if (ev->poll & PE_E) { FD_SET(fd, &Efds); ++bits; }
399 if (bits && fd > Nfds) Nfds = fd;
400 }
401 ev = ev->ioring.next->self;
402 }
403 IOWatch_OK = 1;
404 }
405
406 if (timeout < 0)
407 timeout = 0;
408 tm.tv_sec = timeout;
409 tm.tv_usec = (timeout - tm.tv_sec) * 1000000;
410 if (Nfds > -1) {
411 memcpy(&rfds, &Rfds, sizeof(fd_set));
412 memcpy(&wfds, &Wfds, sizeof(fd_set));
413 memcpy(&efds, &Efds, sizeof(fd_set));
414 ret = select(Nfds+1, &rfds, &wfds, &efds, &tm);
415 }
416 else
417 ret = select(0, 0, 0, 0, &tm);
418
419 if (ret < 0) {
420 if (errno == EINTR)
421 return;
422 if (errno == EBADF) {
423 STRLEN n_a;
424 ev = IOWatch.next->self;
425 while (ev) {
426 int fd = ev->fd;
427 struct stat buf;
428 if (fd >= 0 && PerlLIO_fstat(fd, &buf) < 0 && errno == EBADF) {
429 warn("Event: '%s' was unexpectedly closed",
430 SvPV(ev->base.desc, n_a));
431 pe_io_reset_handle((pe_watcher*) ev);
432 return;
433 }
434 ev = ev->ioring.next->self;
435 }
436 warn("select: couldn't find cause of EBADF");
437 return;
438 }
439 if (errno == EINVAL) {
440 warn("select: bad args %d %.2f", Nfds, timeout);
441 return;
442 }
443 warn("select got errno %d", errno);
444 return;
445 }
446 ev = IOWatch.next->self;
447 while (ev) {
448 pe_io *next_ev = (pe_io*) ev->ioring.next->self;
449 int fd = ev->fd;
450 if (fd >= 0) {
451 int got = 0;
452 if (FD_ISSET(fd, &rfds)) got |= PE_R;
453 if (FD_ISSET(fd, &wfds)) got |= PE_W;
454 if (FD_ISSET(fd, &efds)) got |= PE_E;
455 if (got) _queue_io(ev, got);
456 /*
457 Can only do this if fd-to-watcher is 1-to-1
458
459 if (--ret == 0) { ev=0; continue; }
460 */
461 }
462 ev = next_ev;
463 }
464 }
465 #endif /*HAS_SELECT*/
466