2 * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/lib/libc_r/uthread/uthread_select.c,v 1.16.2.5 2002/10/22 14:44:03 fjoe Exp $
39 #include <sys/param.h>
40 #include <sys/types.h>
42 #include <sys/fcntl.h>
44 #include "pthread_private.h"
47 _select(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds,
48 struct timeval * timeout)
50 struct pthread *curthread = _get_curthread();
52 int i, ret = 0, f_wait = 1;
53 int pfd_index, got_events = 0, fd_count = 0;
54 struct pthread_poll_data data;
56 if (numfds > _thread_dtablesize) {
57 numfds = _thread_dtablesize;
59 /* Check if a timeout was specified: */
61 if (timeout->tv_sec < 0 ||
62 timeout->tv_usec < 0 || timeout->tv_usec >= 1000000) {
67 /* Convert the timeval to a timespec: */
68 TIMEVAL_TO_TIMESPEC(timeout, &ts);
70 /* Set the wake up time: */
71 _thread_kern_set_timeout(&ts);
72 if (ts.tv_sec == 0 && ts.tv_nsec == 0)
76 _thread_kern_set_timeout(NULL);
79 /* Count the number of file descriptors to be polled: */
80 if (readfds || writefds || exceptfds) {
81 for (i = 0; i < numfds; i++) {
82 if ((readfds && FD_ISSET(i, readfds)) ||
83 (exceptfds && FD_ISSET(i, exceptfds)) ||
84 (writefds && FD_ISSET(i, writefds))) {
91 * Allocate memory for poll data if it hasn't already been
92 * allocated or if previously allocated memory is insufficient.
94 if ((curthread->poll_data.fds == NULL) ||
95 (curthread->poll_data.nfds < fd_count)) {
96 data.fds = (struct pollfd *) realloc(curthread->poll_data.fds,
97 sizeof(struct pollfd) * MAX(128, fd_count));
98 if (data.fds == NULL) {
104 * Note that the threads poll data always
105 * indicates what is allocated, not what is
106 * currently being polled.
108 curthread->poll_data.fds = data.fds;
109 curthread->poll_data.nfds = MAX(128, fd_count);
113 /* Setup the wait data. */
114 data.fds = curthread->poll_data.fds;
115 data.nfds = fd_count;
118 * Setup the array of pollfds. Optimize this by
119 * running the loop in reverse and stopping when
120 * the number of selected file descriptors is reached.
122 for (i = numfds - 1, pfd_index = fd_count - 1;
123 (i >= 0) && (pfd_index >= 0); i--) {
124 data.fds[pfd_index].events = 0;
125 if (readfds && FD_ISSET(i, readfds)) {
126 data.fds[pfd_index].events = POLLRDNORM;
128 if (exceptfds && FD_ISSET(i, exceptfds)) {
129 data.fds[pfd_index].events |= POLLRDBAND;
131 if (writefds && FD_ISSET(i, writefds)) {
132 data.fds[pfd_index].events |= POLLWRNORM;
134 if (data.fds[pfd_index].events != 0) {
136 * Set the file descriptor to be polled and
137 * clear revents in case of a timeout which
138 * leaves fds unchanged:
140 data.fds[pfd_index].fd = i;
141 data.fds[pfd_index].revents = 0;
145 if (((ret = __sys_poll(data.fds, data.nfds, 0)) == 0) &&
147 curthread->data.poll_data = &data;
148 curthread->interrupted = 0;
149 _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__);
150 if (curthread->interrupted) {
161 for (i = 0; i < fd_count; i++) {
163 * Check the results of the poll and clear
164 * this file descriptor from the fdset if
165 * the requested event wasn't ready.
169 * First check for invalid descriptor.
170 * If found, set errno and return -1.
172 if (data.fds[i].revents & POLLNVAL) {
178 if (readfds != NULL) {
179 if (FD_ISSET(data.fds[i].fd, readfds)) {
180 if ((data.fds[i].revents & (POLLIN
181 | POLLRDNORM | POLLERR
182 | POLLHUP | POLLNVAL)) != 0)
185 FD_CLR(data.fds[i].fd, readfds);
188 if (writefds != NULL) {
189 if (FD_ISSET(data.fds[i].fd, writefds)) {
190 if ((data.fds[i].revents & (POLLOUT
191 | POLLWRNORM | POLLWRBAND | POLLERR
192 | POLLHUP | POLLNVAL)) != 0)
195 FD_CLR(data.fds[i].fd,
199 if (exceptfds != NULL) {
200 if (FD_ISSET(data.fds[i].fd, exceptfds)) {
201 if (data.fds[i].revents & (POLLRDBAND |
205 FD_CLR(data.fds[i].fd,
219 select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
220 struct timeval *timeout)
224 _thread_enter_cancellation_point();
225 ret = _select(numfds, readfds, writefds, exceptfds, timeout);
226 _thread_leave_cancellation_point();