Ultrix mmap tidbit.
[p5sagit/p5-mst-13.2.git] / ext / IO / poll.c
1 /*
2  * poll.c
3  *
4  * Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
5  * This program is free software; you can redistribute it and/or
6  * modify it under the same terms as Perl itself.
7  *
8  * For systems that do not have the poll() system call (for example Linux)
9  * try to emulate it as closely as possible using select()
10  *
11  */
12
13 #include "EXTERN.h"
14 #include "perl.h"
15 #include "poll.h"
16 #ifdef I_SYS_TIME
17 # include <sys/time.h>
18 #endif
19 #ifdef I_TIME
20 # include <time.h>
21 #endif
22 #include <sys/types.h>
23 #if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
24 #  include <sys/socket.h>
25 #endif
26 #include <sys/stat.h>
27 #include <errno.h>
28
29 #ifdef EMULATE_POLL_WITH_SELECT
30
31 # define POLL_CAN_READ  (POLLIN | POLLRDNORM )
32 # define POLL_CAN_WRITE (POLLOUT | POLLWRNORM | POLLWRBAND )
33 # define POLL_HAS_EXCP  (POLLRDBAND | POLLPRI )
34
35 # define POLL_EVENTS_MASK (POLL_CAN_READ | POLL_CAN_WRITE | POLL_HAS_EXCP)
36
37 int
38 poll(struct pollfd *fds, unsigned long nfds, int timeout)
39 {
40     int i,err;
41     fd_set rfd,wfd,efd,ifd;
42     struct timeval timebuf;
43     struct timeval *tbuf = (struct timeval *)0;
44     int n = 0;
45     int count;
46
47     FD_ZERO(&ifd);
48
49 again:
50
51     FD_ZERO(&rfd);
52     FD_ZERO(&wfd);
53     FD_ZERO(&efd);
54
55     for(i = 0 ; i < nfds ; i++) {
56         int events = fds[i].events;
57         int fd = fds[i].fd;
58
59         fds[i].revents = 0;
60
61         if(fd < 0 || FD_ISSET(fd, &ifd))
62             continue;
63
64         if(fd > n)
65             n = fd;
66
67         if(events & POLL_CAN_READ)
68             FD_SET(fd, &rfd);
69
70         if(events & POLL_CAN_WRITE)
71             FD_SET(fd, &wfd);
72
73         if(events & POLL_HAS_EXCP)
74             FD_SET(fd, &efd);
75     }
76
77     if(timeout >= 0) {
78         timebuf.tv_sec = timeout / 1000;
79         timebuf.tv_usec = (timeout % 1000) * 1000;
80         tbuf = &timebuf;
81     }
82
83     err = select(n+1,&rfd,&wfd,&efd,tbuf);
84
85     if(err < 0) {
86 #ifdef HAS_FSTAT
87         if(errno == EBADF) {
88             for(i = 0 ; i < nfds ; i++) {
89                 struct stat buf;
90                 if((fstat(fds[i].fd,&buf) < 0) && (errno == EBADF)) {
91                     FD_SET(fds[i].fd, &ifd);
92                     goto again;
93                 }
94             }
95         }
96 #endif /* HAS_FSTAT */
97         return err;
98     }
99
100     count = 0;
101
102     for(i = 0 ; i < nfds ; i++) {
103         int revents = (fds[i].events & POLL_EVENTS_MASK);
104         int fd = fds[i].fd;
105
106         if(fd < 0)
107             continue;
108
109         if(FD_ISSET(fd, &ifd))
110             revents = POLLNVAL;
111         else {
112             if(!FD_ISSET(fd, &rfd))
113                 revents &= ~POLL_CAN_READ;
114
115             if(!FD_ISSET(fd, &wfd))
116                 revents &= ~POLL_CAN_WRITE;
117
118             if(!FD_ISSET(fd, &efd))
119                 revents &= ~POLL_HAS_EXCP;
120         }
121
122         if((fds[i].revents = revents) != 0)
123             count++;
124     }
125
126     return count; 
127 }
128
129 #endif /* EMULATE_POLL_WITH_SELECT */