File Coverage

c/unix.c
Criterion Covered Total %
statement 80 101 79.2
branch 57 100 57.0
condition n/a
subroutine n/a
pod n/a
total 137 201 68.1


line stmt bran cond sub pod time code
1             #if defined(HAS_DEVPOLL)
2             #include
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              
17 24           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 24           }
32              
33 6           static int pe_sys_fileno(SV *sv, char *context) {
34             IO *io;
35             PerlIO *fp;
36            
37 6 50         if (!sv)
38 0           croak("Event %s: no filehandle available", context);
39 6 50         if (SvGMAGICAL(sv))
40 0           mg_get(sv);
41 6 100         if (SvIOK(sv)) /* maybe non-portable but nice for unixen */
42 1 50         return SvIV(sv);
43 5 50         if (SvROK(sv))
44 5           sv = SvRV(sv);
45 5 50         if (SvTYPE(sv) == SVt_PVGV) {
46 5 50         if (!(io=GvIO((GV*)sv)) || !(fp = IoIFP(io))) {
    50          
    0          
    50          
    50          
    50          
47 0           croak("Event '%s': GLOB(0x%x) isn't a valid IO", context, sv);
48             }
49 5           return PerlIO_fileno(fp);
50             }
51 0           sv_dump(sv);
52 0           croak("Event '%s': can't find fileno", context);
53 0           return -1;
54             }
55              
56 110216           static void _queue_io(pe_io *wa, int got) {
57             pe_ioevent *ev;
58 110216           got &= wa->poll;
59 110216 50         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 0           return;
65             }
66 110216           ev = (pe_ioevent*) (*wa->base.vtbl->new_event)((pe_watcher*) wa);
67 110216           ++ev->base.hits;
68 110216           ev->got |= got;
69 110216           queueEvent((pe_event*) ev);
70             }
71              
72             /************************************************* DEVPOLL */
73             #if defined(HAS_DEVPOLL) && !PE_SYS_IO
74             #define PE_SYS_IO 1
75              
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              
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              
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              
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              
240 1           static void pe_sys_sleep(NV left) {
241             int ret;
242 1           NV t0 = NVtime();
243 1           NV t1 = t0 + left;
244             while (1) {
245 1           ret = poll(0, 0, (int) (left * 1000)); /* hope zeroes okay */
246 1 50         if (ret < 0 && errno != EAGAIN && errno != EINTR)
    0          
    0          
247 0           croak("poll(%.2f) got errno %d", left, errno);
248 1           left = t1 - NVtime();
249 1 50         if (left > IntervalEpsilon) {
250 0 0         if (ret==0) ++TimeoutTooEarly;
251 0           continue;
252             }
253 1           break;
254 0           }
255 1           }
256              
257 5           static void pe_sys_io_add (pe_io *ev) {}
258 5           static void pe_sys_io_del (pe_io *ev) {}
259              
260 69428           static void pe_sys_multiplex(NV timeout) {
261             pe_io *ev;
262             int xx;
263             int ret;
264 69428 100         if (pollMax < IOWatchCount) {
265 3 50         if (Pollfd)
266 0           EvFree(9, Pollfd);
267 3           pollMax = IOWatchCount+5;
268 3 50         EvNew(9, Pollfd, pollMax, struct pollfd);
269 3           IOWatch_OK = 0;
270             }
271 69428 100         if (!IOWatch_OK) {
272 17           Nfds = 0;
273 17 100         if (Pollfd)
274 4 50         Zero(Pollfd, pollMax, struct pollfd);
275 17           ev = (pe_io*) IOWatch.next->self;
276 24 100         while (ev) {
277 7           int fd = ev->fd;
278 7           ev->xref = -1;
279             assert(fd >= 0); {
280 7           int bits=0;
281 7 100         if (ev->poll & PE_R) bits |= (POLLIN | POLLPRI);
282 7 100         if (ev->poll & PE_W) bits |= POLLOUT;
283 7 50         if (ev->poll & PE_E) bits |= (POLLRDBAND | POLLPRI);
284             assert(bits); {
285 7           int ok=0;;
286 11 100         for (xx = 0; xx < Nfds; xx++) {
287 4 50         if (Pollfd[xx].fd == fd) { ok=1; break; }
288             }
289 7 50         if (!ok) xx = Nfds++;
290 7           Pollfd[xx].fd = fd;
291 7           Pollfd[xx].events |= bits;
292 7           ev->xref = xx;
293             }
294             }
295 7           ev = (pe_io*) ev->ioring.next->self;
296             }
297 17           IOWatch_OK = 1;
298             }
299 179646 100         for (xx=0; xx < Nfds; xx++)
300 110218           Pollfd[xx].revents = 0; /* needed? XXX */
301 69428 100         if (timeout < 0)
302 16           timeout = 0;
303 69428           ret = poll(Pollfd, Nfds, (int) (timeout * 1000));
304            
305 69428 50         if (ret < 0) {
306 0 0         if (errno == EINTR || errno == EAGAIN)
    0          
307 0           return;
308 0 0         if (errno == EINVAL) {
309 0           warn("poll: bad args %d %.2f", Nfds, timeout);
310 0           return;
311             }
312 0           warn("poll got errno %d", errno);
313 0           return;
314             }
315 69428           ev = (pe_io*) IOWatch.next->self;
316 179646 100         while (ev) {
317 110218           pe_io *next_ev = (pe_io*) ev->ioring.next->self;
318             STRLEN n_a;
319 110218           int xref = ev->xref;
320 110218 50         if (xref >= 0) {
321 110218           int got = 0;
322 110218           int mask = Pollfd[xref].revents;
323 110218 100         if (mask & (POLLIN | POLLPRI | POLLHUP | POLLERR)) got |= PE_R;
324 110218 100         if (mask & (POLLOUT | POLLERR)) got |= PE_W;
325 110218 100         if (mask & (POLLRDBAND | POLLPRI | POLLHUP | POLLERR)) got |= PE_E;
326 110218 100         if (mask & POLLNVAL) {
327 1 50         warn("Event: '%s' was unexpectedly closed",
328 2           SvPV(ev->base.desc, n_a));
329 1           pe_io_reset_handle((pe_watcher*) ev);
330             } else {
331 110217 100         if ((mask & POLLHUP) && (ev->poll & PE_W) && (!(got & PE_W))
    50          
    0          
332 0 0         && (!(ev->poll & PE_R)) && (!(ev->poll & PE_E))) {
    0          
333             /* Must notify about POLLHUP _some_ way - Allen */
334 0           got |= PE_W;
335             }
336              
337 110217 100         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 110218           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              
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              
377             static void pe_sys_io_add (pe_io *ev) {}
378             static void pe_sys_io_del (pe_io *ev) {}
379              
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*/