1 /* vi: set sw=4 ts=4: */
2 /*
3  * select() for uClibc
4  *
5  * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
6  *
7  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
8  */
9 
10 #include <sys/syscall.h>
11 #include <sys/select.h>
12 #include <cancel.h>
13 
14 #ifdef __NR__newselect
15 # undef __NR_select
16 # define __NR_select __NR__newselect
17 #endif
18 
19 #if !defined __NR_select && defined __NR_pselect6
20 # include <stdint.h>
21 # define USEC_PER_SEC 1000000L
22 #endif
23 
__NC(select)24 int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
25 		 struct timeval *timeout)
26 {
27 #ifdef __NR_select
28 	return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout);
29 #elif defined __NR_pselect6
30 	struct timespec _ts, *ts = 0;
31 	if (timeout) {
32 		uint32_t usec;
33 		_ts.tv_sec = timeout->tv_sec;
34 
35 		/* GNU extension: allow for timespec values where the sub-sec
36 		* field is equal to or more than 1 second.  The kernel will
37 		* reject this on us, so take care of the time shift ourself.
38 		* Some applications (like readline and linphone) do this.
39 		* See 'clarification on select() type calls and invalid timeouts'
40 		* on the POSIX general list for more information.
41 		*/
42 		usec = timeout->tv_usec;
43 		if (usec >= USEC_PER_SEC) {
44 			_ts.tv_sec += usec / USEC_PER_SEC;
45 			usec %= USEC_PER_SEC;
46 		}
47 		_ts.tv_nsec = usec * 1000;
48 
49 		ts = &_ts;
50 	}
51 	return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds, exceptfds, ts, 0);
52 #endif
53 }
54 /* we should guard it, but we need it in other files, so let it fail
55  * if we miss any of the syscalls */
56 #if 1 /*defined __NR_select || defined __NR_pselect6*/
57 CANCELLABLE_SYSCALL(int, select, (int n, fd_set *readfds, fd_set *writefds,
58 				  fd_set *exceptfds, struct timeval *timeout),
59 		    (n, readfds, writefds, exceptfds, timeout))
60 lt_libc_hidden(select)
61 #endif
62