10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51778Sraf * Common Development and Distribution License (the "License"). 61778Sraf * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211778Sraf 220Sstevel@tonic-gate /* 23*6515Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 300Sstevel@tonic-gate /* All Rights Reserved */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate /* 330Sstevel@tonic-gate * Emulation of select() system call using poll() system call. 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * Assumptions: 360Sstevel@tonic-gate * polling for input only is most common. 370Sstevel@tonic-gate * polling for exceptional conditions is very rare. 380Sstevel@tonic-gate * 390Sstevel@tonic-gate * Note that is it not feasible to emulate all error conditions, 400Sstevel@tonic-gate * in particular conditions that would return EFAULT are far too 410Sstevel@tonic-gate * difficult to check for in a library routine. 420Sstevel@tonic-gate * 430Sstevel@tonic-gate */ 440Sstevel@tonic-gate 450Sstevel@tonic-gate #pragma weak pselect = _pselect 460Sstevel@tonic-gate #pragma weak select = _select 470Sstevel@tonic-gate 480Sstevel@tonic-gate #include "synonyms.h" 490Sstevel@tonic-gate #include <values.h> 50*6515Sraf #include <pthread.h> 510Sstevel@tonic-gate #include <errno.h> 520Sstevel@tonic-gate #include <sys/time.h> 530Sstevel@tonic-gate #include <sys/types.h> 540Sstevel@tonic-gate #include <sys/select.h> 550Sstevel@tonic-gate #include <sys/poll.h> 560Sstevel@tonic-gate #include <alloca.h> 570Sstevel@tonic-gate #include "libc.h" 580Sstevel@tonic-gate 590Sstevel@tonic-gate int 600Sstevel@tonic-gate pselect(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, 610Sstevel@tonic-gate const timespec_t *tsp, const sigset_t *sigmask) 620Sstevel@tonic-gate { 630Sstevel@tonic-gate long *in, *out, *ex; 640Sstevel@tonic-gate ulong_t m; /* bit mask */ 650Sstevel@tonic-gate int j; /* loop counter */ 660Sstevel@tonic-gate ulong_t b; /* bits to test */ 670Sstevel@tonic-gate int n, rv; 680Sstevel@tonic-gate struct pollfd *pfd; 690Sstevel@tonic-gate struct pollfd *p; 700Sstevel@tonic-gate int lastj = -1; 710Sstevel@tonic-gate 720Sstevel@tonic-gate /* "zero" is read-only, it could go in the text segment */ 730Sstevel@tonic-gate static fd_set zero = { 0 }; 740Sstevel@tonic-gate 750Sstevel@tonic-gate /* 760Sstevel@tonic-gate * Check for invalid conditions at outset. 770Sstevel@tonic-gate * Required for spec1170. 780Sstevel@tonic-gate * SUSV3: We must behave as a cancellation point even if we fail early. 790Sstevel@tonic-gate */ 800Sstevel@tonic-gate if (nfds < 0 || nfds > FD_SETSIZE) { 81*6515Sraf pthread_testcancel(); 820Sstevel@tonic-gate errno = EINVAL; 830Sstevel@tonic-gate return (-1); 840Sstevel@tonic-gate } 850Sstevel@tonic-gate p = pfd = (struct pollfd *)alloca(nfds * sizeof (struct pollfd)); 860Sstevel@tonic-gate 870Sstevel@tonic-gate if (tsp != NULL) { 880Sstevel@tonic-gate /* check timespec validity */ 890Sstevel@tonic-gate if (tsp->tv_nsec < 0 || tsp->tv_nsec >= NANOSEC || 900Sstevel@tonic-gate tsp->tv_sec < 0) { 91*6515Sraf pthread_testcancel(); 920Sstevel@tonic-gate errno = EINVAL; 930Sstevel@tonic-gate return (-1); 940Sstevel@tonic-gate } 950Sstevel@tonic-gate } 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* 980Sstevel@tonic-gate * If any input args are null, point them at the null array. 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate if (in0 == NULL) 1010Sstevel@tonic-gate in0 = &zero; 1020Sstevel@tonic-gate if (out0 == NULL) 1030Sstevel@tonic-gate out0 = &zero; 1040Sstevel@tonic-gate if (ex0 == NULL) 1050Sstevel@tonic-gate ex0 = &zero; 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* 1080Sstevel@tonic-gate * For each fd, if any bits are set convert them into 1090Sstevel@tonic-gate * the appropriate pollfd struct. 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate in = (long *)in0->fds_bits; 1120Sstevel@tonic-gate out = (long *)out0->fds_bits; 1130Sstevel@tonic-gate ex = (long *)ex0->fds_bits; 1140Sstevel@tonic-gate for (n = 0; n < nfds; n += NFDBITS) { 1150Sstevel@tonic-gate b = (ulong_t)(*in | *out | *ex); 1160Sstevel@tonic-gate for (j = 0, m = 1; b != 0; j++, b >>= 1, m <<= 1) { 1170Sstevel@tonic-gate if (b & 1) { 1180Sstevel@tonic-gate p->fd = n + j; 1190Sstevel@tonic-gate if (p->fd >= nfds) 1200Sstevel@tonic-gate goto done; 1210Sstevel@tonic-gate p->events = 0; 1220Sstevel@tonic-gate if (*in & m) 1230Sstevel@tonic-gate p->events |= POLLRDNORM; 1240Sstevel@tonic-gate if (*out & m) 1250Sstevel@tonic-gate p->events |= POLLWRNORM; 1260Sstevel@tonic-gate if (*ex & m) 1270Sstevel@tonic-gate p->events |= POLLRDBAND; 1280Sstevel@tonic-gate p++; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate in++; 1320Sstevel@tonic-gate out++; 1330Sstevel@tonic-gate ex++; 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate done: 1360Sstevel@tonic-gate /* 1370Sstevel@tonic-gate * Now do the poll. 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate n = (int)(p - pfd); /* number of pollfd's */ 1400Sstevel@tonic-gate do { 1410Sstevel@tonic-gate rv = _pollsys(pfd, (nfds_t)n, tsp, sigmask); 1420Sstevel@tonic-gate } while (rv < 0 && errno == EAGAIN); 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate if (rv < 0) /* no need to set bit masks */ 1450Sstevel@tonic-gate return (rv); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate if (rv == 0) { 1480Sstevel@tonic-gate /* 1490Sstevel@tonic-gate * Clear out bit masks, just in case. 1500Sstevel@tonic-gate * On the assumption that usually only 1510Sstevel@tonic-gate * one bit mask is set, use three loops. 1520Sstevel@tonic-gate */ 1530Sstevel@tonic-gate if (in0 != &zero) { 1540Sstevel@tonic-gate in = (long *)in0->fds_bits; 1550Sstevel@tonic-gate for (n = 0; n < nfds; n += NFDBITS) 1560Sstevel@tonic-gate *in++ = 0; 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate if (out0 != &zero) { 1590Sstevel@tonic-gate out = (long *)out0->fds_bits; 1600Sstevel@tonic-gate for (n = 0; n < nfds; n += NFDBITS) 1610Sstevel@tonic-gate *out++ = 0; 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate if (ex0 != &zero) { 1640Sstevel@tonic-gate ex = (long *)ex0->fds_bits; 1650Sstevel@tonic-gate for (n = 0; n < nfds; n += NFDBITS) 1660Sstevel@tonic-gate *ex++ = 0; 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate return (0); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * Check for EINVAL error case first to avoid changing any bits 1730Sstevel@tonic-gate * if we're going to return an error. 1740Sstevel@tonic-gate */ 1750Sstevel@tonic-gate for (p = pfd, j = n; j-- > 0; p++) { 1760Sstevel@tonic-gate /* 1770Sstevel@tonic-gate * select will return EBADF immediately if any fd's 1780Sstevel@tonic-gate * are bad. poll will complete the poll on the 1790Sstevel@tonic-gate * rest of the fd's and include the error indication 1800Sstevel@tonic-gate * in the returned bits. This is a rare case so we 1810Sstevel@tonic-gate * accept this difference and return the error after 1820Sstevel@tonic-gate * doing more work than select would've done. 1830Sstevel@tonic-gate */ 1840Sstevel@tonic-gate if (p->revents & POLLNVAL) { 1850Sstevel@tonic-gate errno = EBADF; 1860Sstevel@tonic-gate return (-1); 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * We would like to make POLLHUP available to select, 1900Sstevel@tonic-gate * checking to see if we have pending data to be read. 1910Sstevel@tonic-gate * BUT until we figure out how not to break Xsun's 1920Sstevel@tonic-gate * dependencies on select's existing features... 1930Sstevel@tonic-gate * This is what we _thought_ would work ... sigh! 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate /* 1960Sstevel@tonic-gate * if ((p->revents & POLLHUP) && 1970Sstevel@tonic-gate * !(p->revents & (POLLRDNORM|POLLRDBAND))) { 1980Sstevel@tonic-gate * errno = EINTR; 1990Sstevel@tonic-gate * return (-1); 2000Sstevel@tonic-gate * } 2010Sstevel@tonic-gate */ 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate /* 2050Sstevel@tonic-gate * Convert results of poll back into bits 2060Sstevel@tonic-gate * in the argument arrays. 2070Sstevel@tonic-gate * 2080Sstevel@tonic-gate * We assume POLLRDNORM, POLLWRNORM, and POLLRDBAND will only be set 2090Sstevel@tonic-gate * on return from poll if they were set on input, thus we don't 2100Sstevel@tonic-gate * worry about accidentally setting the corresponding bits in the 2110Sstevel@tonic-gate * zero array if the input bit masks were null. 2120Sstevel@tonic-gate * 2130Sstevel@tonic-gate * Must return number of bits set, not number of ready descriptors 2140Sstevel@tonic-gate * (as the man page says, and as poll() does). 2150Sstevel@tonic-gate */ 2160Sstevel@tonic-gate rv = 0; 2170Sstevel@tonic-gate for (p = pfd; n-- > 0; p++) { 2180Sstevel@tonic-gate j = (int)(p->fd / NFDBITS); 2190Sstevel@tonic-gate /* have we moved into another word of the bit mask yet? */ 2200Sstevel@tonic-gate if (j != lastj) { 2210Sstevel@tonic-gate /* clear all output bits to start with */ 2220Sstevel@tonic-gate in = (long *)&in0->fds_bits[j]; 2230Sstevel@tonic-gate out = (long *)&out0->fds_bits[j]; 2240Sstevel@tonic-gate ex = (long *)&ex0->fds_bits[j]; 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * In case we made "zero" read-only (e.g., with 2270Sstevel@tonic-gate * cc -R), avoid actually storing into it. 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate if (in0 != &zero) 2300Sstevel@tonic-gate *in = 0; 2310Sstevel@tonic-gate if (out0 != &zero) 2320Sstevel@tonic-gate *out = 0; 2330Sstevel@tonic-gate if (ex0 != &zero) 2340Sstevel@tonic-gate *ex = 0; 2350Sstevel@tonic-gate lastj = j; 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate if (p->revents) { 2380Sstevel@tonic-gate m = 1L << (p->fd % NFDBITS); 2390Sstevel@tonic-gate if (p->revents & POLLRDNORM) { 2400Sstevel@tonic-gate *in |= m; 2410Sstevel@tonic-gate rv++; 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate if (p->revents & POLLWRNORM) { 2440Sstevel@tonic-gate *out |= m; 2450Sstevel@tonic-gate rv++; 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate if (p->revents & POLLRDBAND) { 2480Sstevel@tonic-gate *ex |= m; 2490Sstevel@tonic-gate rv++; 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate /* 2520Sstevel@tonic-gate * Only set this bit on return if we asked about 2530Sstevel@tonic-gate * input conditions. 2540Sstevel@tonic-gate */ 2550Sstevel@tonic-gate if ((p->revents & (POLLHUP|POLLERR)) && 2560Sstevel@tonic-gate (p->events & POLLRDNORM)) { 2570Sstevel@tonic-gate if ((*in & m) == 0) 2580Sstevel@tonic-gate rv++; /* wasn't already set */ 2590Sstevel@tonic-gate *in |= m; 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate /* 2620Sstevel@tonic-gate * Only set this bit on return if we asked about 2630Sstevel@tonic-gate * output conditions. 2640Sstevel@tonic-gate */ 2650Sstevel@tonic-gate if ((p->revents & (POLLHUP|POLLERR)) && 2660Sstevel@tonic-gate (p->events & POLLWRNORM)) { 2670Sstevel@tonic-gate if ((*out & m) == 0) 2680Sstevel@tonic-gate rv++; /* wasn't already set */ 2690Sstevel@tonic-gate *out |= m; 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate /* 2720Sstevel@tonic-gate * Only set this bit on return if we asked about 2730Sstevel@tonic-gate * output conditions. 2740Sstevel@tonic-gate */ 2750Sstevel@tonic-gate if ((p->revents & (POLLHUP|POLLERR)) && 2760Sstevel@tonic-gate (p->events & POLLRDBAND)) { 2770Sstevel@tonic-gate if ((*ex & m) == 0) 2780Sstevel@tonic-gate rv++; /* wasn't already set */ 2790Sstevel@tonic-gate *ex |= m; 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate return (rv); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate int 2870Sstevel@tonic-gate select(int nfds, fd_set *in0, fd_set *out0, fd_set *ex0, struct timeval *tv) 2880Sstevel@tonic-gate { 2890Sstevel@tonic-gate timespec_t ts; 2900Sstevel@tonic-gate timespec_t *tsp; 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate if (tv == NULL) 2930Sstevel@tonic-gate tsp = NULL; 2940Sstevel@tonic-gate else { 2950Sstevel@tonic-gate /* check timeval validity */ 2960Sstevel@tonic-gate if (tv->tv_usec < 0 || tv->tv_usec >= MICROSEC) { 2970Sstevel@tonic-gate errno = EINVAL; 2980Sstevel@tonic-gate return (-1); 2990Sstevel@tonic-gate } 3001778Sraf /* 3011778Sraf * Convert timeval to timespec. 3021778Sraf * To preserve compatibility with past behavior, 3031778Sraf * when select was built upon poll(2), which has a 3041778Sraf * minimum non-zero timeout of 1 millisecond, force 3051778Sraf * a minimum non-zero timeout of 500 microseconds. 3061778Sraf */ 3070Sstevel@tonic-gate ts.tv_sec = tv->tv_sec; 3080Sstevel@tonic-gate ts.tv_nsec = tv->tv_usec * 1000; 3091778Sraf if (ts.tv_nsec != 0 && ts.tv_nsec < 500000) 3101778Sraf ts.tv_nsec = 500000; 3110Sstevel@tonic-gate tsp = &ts; 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate return (pselect(nfds, in0, out0, ex0, tsp, NULL)); 3150Sstevel@tonic-gate } 316