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