2 * Copyright (c) 2005, 2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #if defined(__LP64__) && (defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050))
25 #undef __DARWIN_NON_CANCELABLE
26 #define __DARWIN_NON_CANCELABLE 0
27 #endif /* __LP64__ && (VARIANT_CANCELABLE || VARIANT_PRE1050) */
29 #if defined(VARIANT_DARWIN_EXTSN)
30 #define _DARWIN_C_SOURCE
31 #define _DARWIN_UNLIMITED_SELECT
34 #include <sys/select.h>
36 #include <sys/signal.h>
39 #if defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050)
40 #if !defined(VARIANT_DARWIN_EXTSN)
41 extern int __select(int, fd_set
* __restrict
, fd_set
* __restrict
,
42 fd_set
* __restrict
, struct timeval
* __restrict
);
44 int __pselect(int, fd_set
* __restrict
, fd_set
* __restrict
,
45 fd_set
* __restrict
, const struct timespec
* __restrict
, const sigset_t
* __restrict
);
46 #else /* !VARIANT_CANCELABLE && !VARIANT_PRE1050 */
47 #if !defined(VARIANT_DARWIN_EXTSN)
48 int __select_nocancel(int, fd_set
* __restrict
, fd_set
* __restrict
,
49 fd_set
* __restrict
, struct timeval
* __restrict
);
51 int __pselect_nocancel(int, fd_set
* __restrict
, fd_set
* __restrict
,
52 fd_set
* __restrict
, const struct timespec
* __restrict
, const sigset_t
* __restrict
);
53 #endif /* VARIANT_CANCELABLE || VARIANT_PRE1050 */
55 #if !defined(VARIANT_DARWIN_EXTSN)
57 * select() implementation for 1050 and legacy (cancelable and non-cancelable)
58 * variants. The darwin extension variants (both cancelable & non-cancelable) are
59 * mapped directly to the syscall stub.
62 select(int nfds
, fd_set
* __restrict readfds
, fd_set
* __restrict writefds
,
63 fd_set
* __restrict exceptfds
, struct timeval
* __restrict
64 #if defined(VARIANT_LEGACY) || defined(VARIANT_PRE1050)
66 #else /* !VARIANT_LEGACY && !VARIANT_PRE1050 */
68 #endif /* VARIANT_LEGACY || VARIANT_PRE1050 */
71 #if defined(VARIANT_LEGACY) || defined(VARIANT_PRE1050)
72 struct timeval tb
, *timeout
;
75 * Legacy select behavior is minimum 10 msec when tv_usec is non-zero
77 if (intimeout
&& intimeout
->tv_sec
== 0 && intimeout
->tv_usec
> 0 && intimeout
->tv_usec
< 10000) {
84 #else /* !VARIANT_LEGACY && !VARIANT_PRE1050 */
85 if (nfds
> FD_SETSIZE
) {
91 #if defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050)
92 return __select(nfds
, readfds
, writefds
, exceptfds
, timeout
);
93 #else /* !VARIANT_CANCELABLE && !VARIANT_PRE1050 */
94 return __select_nocancel(nfds
, readfds
, writefds
, exceptfds
, timeout
);
95 #endif /* VARIANT_CANCELABLE || VARIANT_PRE1050 */
97 #endif /* !defined(VARIANT_DARWIN_EXTSN) */
101 * User-space emulation of pselect() syscall for B&I
102 * TODO: remove when B&I move to xnu with native pselect()
104 extern int __pthread_sigmask(int, const sigset_t
*, sigset_t
*);
106 _pselect_emulated(int count
, fd_set
* __restrict rfds
, fd_set
* __restrict wfds
,
107 fd_set
* __restrict efds
, const struct timespec
* __restrict timo
,
108 const sigset_t
* __restrict mask
)
111 struct timeval tvtimo
, *tvp
;
115 tvtimo
.tv_sec
= timo
->tv_sec
;
116 tvtimo
.tv_usec
= (__darwin_suseconds_t
)(timo
->tv_nsec
/ 1000);
123 rv
= __pthread_sigmask(SIG_SETMASK
, mask
, &omask
);
128 rv
= select(count
, rfds
, wfds
, efds
, tvp
);
131 __pthread_sigmask(SIG_SETMASK
, &omask
, (sigset_t
*)0);
139 * pselect() implementation for all variants. Unlike select(), we implement the
140 * darwin extension variants here to catch cases where xnu doesn't implement
141 * pselect and we need to emulate.
144 pselect(int nfds
, fd_set
* __restrict readfds
, fd_set
* __restrict writefds
,
145 fd_set
* __restrict exceptfds
, const struct timespec
* __restrict
146 #if defined(VARIANT_LEGACY) || defined(VARIANT_PRE1050)
148 #else /* !VARIANT_LEGACY && !VARIANT_PRE1050 */
150 #endif /* VARIANT_LEGACY || VARIANT_PRE1050 */
151 const sigset_t
* __restrict sigmask
)
154 #if defined(VARIANT_LEGACY) || defined(VARIANT_PRE1050)
156 const struct timespec
*timeout
;
159 * Legacy select behavior is minimum 10 msec when tv_usec is non-zero
161 if (intimeout
&& intimeout
->tv_sec
== 0 && intimeout
->tv_nsec
> 0 && intimeout
->tv_nsec
< 10000000L) {
163 tb
.tv_nsec
= 10000000L;
168 #elif defined(VARIANT_DARWIN_EXTSN)
171 if (nfds
> FD_SETSIZE
) {
177 #if defined(VARIANT_CANCELABLE) || defined(VARIANT_PRE1050)
178 ret
= __pselect(nfds
, readfds
, writefds
, exceptfds
, timeout
, sigmask
);
179 #else /* !VARIANT_CANCELABLE && !VARIANT_PRE1050 */
180 ret
= __pselect_nocancel(nfds
, readfds
, writefds
, exceptfds
, timeout
, sigmask
);
181 #endif /* VARIANT_CANCELABLE || VARIANT_PRE1050 */
183 if (ret
== -1 && errno
== ENOSYS
) {
184 ret
= _pselect_emulated(nfds
, readfds
, writefds
, exceptfds
, timeout
, sigmask
);