2 * Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifdef HAVE_SYS_SELECT_H
18 # include <sys/select.h>
27 #define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
31 #define howmany(x,y) (((x)+((y)-1))/(y))
35 * A minimal implementation of ppoll(2), built on top of pselect(2).
37 * Only supports POLLIN, POLLOUT and POLLPRI flags in pfd.events and
38 * revents. Notably POLLERR, POLLHUP and POLLNVAL are not supported.
40 * Supports pfd.fd = -1 meaning "unused" although it's not standard.
44 ppoll(struct pollfd
*fds
, nfds_t nfds
, const struct timespec
*tmoutp
,
45 const sigset_t
*sigmask
)
48 int saved_errno
, ret
, fd
, maxfd
= 0;
49 fd_set
*readfds
= NULL
, *writefds
= NULL
, *exceptfds
= NULL
;
52 for (i
= 0; i
< nfds
; i
++) {
54 if (fd
!= -1 && fd
>= FD_SETSIZE
) {
58 maxfd
= MAX(maxfd
, fd
);
61 nmemb
= howmany(maxfd
+ 1 , NFDBITS
);
62 if ((readfds
= calloc(nmemb
, sizeof(fd_mask
))) == NULL
||
63 (writefds
= calloc(nmemb
, sizeof(fd_mask
))) == NULL
||
64 (exceptfds
= calloc(nmemb
, sizeof(fd_mask
))) == NULL
) {
70 /* populate event bit vectors for the events we're interested in */
71 for (i
= 0; i
< nfds
; i
++) {
75 if (fds
[i
].events
& POLLIN
)
77 if (fds
[i
].events
& POLLOUT
)
79 if (fds
[i
].events
& POLLPRI
)
80 FD_SET(fd
, exceptfds
);
83 ret
= pselect(maxfd
+ 1, readfds
, writefds
, exceptfds
, tmoutp
, sigmask
);
86 /* scan through select results and set poll() flags */
87 for (i
= 0; i
< nfds
; i
++) {
92 if (FD_ISSET(fd
, readfds
))
93 fds
[i
].revents
|= POLLIN
;
94 if (FD_ISSET(fd
, writefds
))
95 fds
[i
].revents
|= POLLOUT
;
96 if (FD_ISSET(fd
, exceptfds
))
97 fds
[i
].revents
|= POLLPRI
;
111 poll(struct pollfd
*fds
, nfds_t nfds
, int timeout
)
113 struct timespec ts
, *tsp
= NULL
;
115 /* poll timeout is msec, ppoll is timespec (sec + nsec) */
117 ts
.tv_sec
= timeout
/ 1000;
118 ts
.tv_nsec
= (timeout
% 1000) * 1000000;
122 return ppoll(fds
, nfds
, tsp
, NULL
);