Commit | Line | Data |
cf7fe8a2 |
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 |
35ef4773 |
38 | poll(struct pollfd *fds, unsigned long nfds, int timeout) |
cf7fe8a2 |
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 */ |