thr_select.c revision 13546
113546Sjulian/* 213546Sjulian * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. 313546Sjulian * All rights reserved. 413546Sjulian * 513546Sjulian * Redistribution and use in source and binary forms, with or without 613546Sjulian * modification, are permitted provided that the following conditions 713546Sjulian * are met: 813546Sjulian * 1. Redistributions of source code must retain the above copyright 913546Sjulian * notice, this list of conditions and the following disclaimer. 1013546Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1113546Sjulian * notice, this list of conditions and the following disclaimer in the 1213546Sjulian * documentation and/or other materials provided with the distribution. 1313546Sjulian * 3. All advertising materials mentioning features or use of this software 1413546Sjulian * must display the following acknowledgement: 1513546Sjulian * This product includes software developed by John Birrell. 1613546Sjulian * 4. Neither the name of the author nor the names of any co-contributors 1713546Sjulian * may be used to endorse or promote products derived from this software 1813546Sjulian * without specific prior written permission. 1913546Sjulian * 2013546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 2113546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2213546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2313546Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2413546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2513546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2613546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2713546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2813546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2913546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3013546Sjulian * SUCH DAMAGE. 3113546Sjulian * 3213546Sjulian */ 3313546Sjulian#include <unistd.h> 3413546Sjulian#include <errno.h> 3513546Sjulian#include <string.h> 3613546Sjulian#include <sys/types.h> 3713546Sjulian#include <sys/time.h> 3813546Sjulian#ifdef _THREAD_SAFE 3913546Sjulian#include <pthread.h> 4013546Sjulian#include "pthread_private.h" 4113546Sjulian 4213546Sjulianint 4313546Sjulianselect(int numfds, fd_set * readfds, fd_set * writefds, 4413546Sjulian fd_set * exceptfds, struct timeval * timeout) 4513546Sjulian{ 4613546Sjulian fd_set read_locks, write_locks, rdwr_locks; 4713546Sjulian struct timespec ts; 4813546Sjulian struct timeval zero_timeout = {0, 0}; 4913546Sjulian int i, ret = 0, got_all_locks = 1; 5013546Sjulian struct pthread_select_data data; 5113546Sjulian 5213546Sjulian if (numfds > _thread_dtablesize) { 5313546Sjulian numfds = _thread_dtablesize; 5413546Sjulian } 5513546Sjulian /* Check if a timeout was specified: */ 5613546Sjulian if (timeout) { 5713546Sjulian /* Convert the timeval to a timespec: */ 5813546Sjulian TIMEVAL_TO_TIMESPEC(timeout, &ts); 5913546Sjulian 6013546Sjulian /* Set the wake up time: */ 6113546Sjulian _thread_kern_set_timeout(&ts); 6213546Sjulian } else { 6313546Sjulian /* Wait for ever: */ 6413546Sjulian _thread_kern_set_timeout(NULL); 6513546Sjulian } 6613546Sjulian 6713546Sjulian FD_ZERO(&read_locks); 6813546Sjulian FD_ZERO(&write_locks); 6913546Sjulian FD_ZERO(&rdwr_locks); 7013546Sjulian 7113546Sjulian /* lock readfds */ 7213546Sjulian if (readfds || writefds || exceptfds) { 7313546Sjulian for (i = 0; i < numfds; i++) { 7413546Sjulian if ((readfds && (FD_ISSET(i, readfds))) || (exceptfds && FD_ISSET(i, exceptfds))) { 7513546Sjulian if (writefds && FD_ISSET(i, writefds)) { 7613546Sjulian if ((ret = _thread_fd_lock(i, FD_RDWR, NULL, __FILE__, __LINE__)) != 0) { 7713546Sjulian got_all_locks = 0; 7813546Sjulian break; 7913546Sjulian } 8013546Sjulian FD_SET(i, &rdwr_locks); 8113546Sjulian } else { 8213546Sjulian if ((ret = _thread_fd_lock(i, FD_READ, NULL, __FILE__, __LINE__)) != 0) { 8313546Sjulian got_all_locks = 0; 8413546Sjulian break; 8513546Sjulian } 8613546Sjulian FD_SET(i, &read_locks); 8713546Sjulian } 8813546Sjulian } else { 8913546Sjulian if (writefds && FD_ISSET(i, writefds)) { 9013546Sjulian if ((ret = _thread_fd_lock(i, FD_WRITE, NULL, __FILE__, __LINE__)) != 0) { 9113546Sjulian got_all_locks = 0; 9213546Sjulian break; 9313546Sjulian } 9413546Sjulian FD_SET(i, &write_locks); 9513546Sjulian } 9613546Sjulian } 9713546Sjulian } 9813546Sjulian } 9913546Sjulian if (got_all_locks) { 10013546Sjulian data.nfds = numfds; 10113546Sjulian FD_ZERO(&data.readfds); 10213546Sjulian FD_ZERO(&data.writefds); 10313546Sjulian FD_ZERO(&data.exceptfds); 10413546Sjulian if (readfds != NULL) { 10513546Sjulian memcpy(&data.readfds, readfds, sizeof(data.readfds)); 10613546Sjulian } 10713546Sjulian if (writefds != NULL) { 10813546Sjulian memcpy(&data.writefds, writefds, sizeof(data.writefds)); 10913546Sjulian } 11013546Sjulian if (exceptfds != NULL) { 11113546Sjulian memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds)); 11213546Sjulian } 11313546Sjulian if ((ret = _thread_sys_select(data.nfds, &data.readfds, &data.writefds, &data.exceptfds, &zero_timeout)) == 0) { 11413546Sjulian data.nfds = numfds; 11513546Sjulian FD_ZERO(&data.readfds); 11613546Sjulian FD_ZERO(&data.writefds); 11713546Sjulian FD_ZERO(&data.exceptfds); 11813546Sjulian if (readfds != NULL) { 11913546Sjulian memcpy(&data.readfds, readfds, sizeof(data.readfds)); 12013546Sjulian } 12113546Sjulian if (writefds != NULL) { 12213546Sjulian memcpy(&data.writefds, writefds, sizeof(data.writefds)); 12313546Sjulian } 12413546Sjulian if (exceptfds != NULL) { 12513546Sjulian memcpy(&data.exceptfds, exceptfds, sizeof(data.exceptfds)); 12613546Sjulian } 12713546Sjulian _thread_run->data.select_data = &data; 12813546Sjulian _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); 12913546Sjulian ret = data.nfds; 13013546Sjulian } 13113546Sjulian } 13213546Sjulian /* clean up the locks */ 13313546Sjulian for (i = 0; i < numfds; i++) 13413546Sjulian if (FD_ISSET(i, &read_locks)) 13513546Sjulian _thread_fd_unlock(i, FD_READ); 13613546Sjulian for (i = 0; i < numfds; i++) 13713546Sjulian if (FD_ISSET(i, &rdwr_locks)) 13813546Sjulian _thread_fd_unlock(i, FD_RDWR); 13913546Sjulian for (i = 0; i < numfds; i++) 14013546Sjulian if (FD_ISSET(i, &write_locks)) 14113546Sjulian _thread_fd_unlock(i, FD_WRITE); 14213546Sjulian 14313546Sjulian if (ret > 0) { 14413546Sjulian if (readfds != NULL) { 14513546Sjulian FD_ZERO(readfds); 14613546Sjulian for (i = 0; i < numfds; i++) { 14713546Sjulian if (FD_ISSET(i, &data.readfds)) { 14813546Sjulian FD_SET(i, readfds); 14913546Sjulian } 15013546Sjulian } 15113546Sjulian } 15213546Sjulian if (writefds != NULL) { 15313546Sjulian FD_ZERO(writefds); 15413546Sjulian for (i = 0; i < numfds; i++) { 15513546Sjulian if (FD_ISSET(i, &data.writefds)) { 15613546Sjulian FD_SET(i, writefds); 15713546Sjulian } 15813546Sjulian } 15913546Sjulian } 16013546Sjulian if (exceptfds != NULL) { 16113546Sjulian FD_ZERO(exceptfds); 16213546Sjulian for (i = 0; i < numfds; i++) { 16313546Sjulian if (FD_ISSET(i, &data.exceptfds)) { 16413546Sjulian FD_SET(i, exceptfds); 16513546Sjulian } 16613546Sjulian } 16713546Sjulian } 16813546Sjulian } else { 16913546Sjulian if (exceptfds != NULL) 17013546Sjulian FD_ZERO(exceptfds); 17113546Sjulian if (writefds != NULL) 17213546Sjulian FD_ZERO(writefds); 17313546Sjulian if (readfds != NULL) 17413546Sjulian FD_ZERO(readfds); 17513546Sjulian } 17613546Sjulian 17713546Sjulian return (ret); 17813546Sjulian} 17913546Sjulian#endif 180