1 /**
2  * D header file for POSIX.
3  *
4  * Copyright: Public Domain
5  * License:   Public Domain
6  * Authors:   Sean Kelly
7  * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
8  */
9 module tango.stdc.posix.sys.select;
10 
11 private import tango.stdc.posix.config;
12 public import tango.stdc.time;            // for timespec
13 public import tango.stdc.posix.sys.time;  // for timeval
14 public import tango.stdc.posix.sys.types; // for time_t
15 public import tango.stdc.posix.signal;    // for sigset_t
16 
17 extern (C):
18 
19 //
20 // Required
21 //
22 /*
23 NOTE: This module requires timeval from tango.stdc.posix.sys.time, but timeval
24       is supposedly an XOpen extension.  As a result, this header will not
25       compile on platforms that are not XSI-compliant.  This must be resolved
26       on a per-platform basis.
27 
28 fd_set
29 
30 void FD_CLR(int fd, fd_set* fdset);
31 int FD_ISSET(int fd, fd_set* fdset);
32 void FD_SET(int fd, fd_set* fdset);
33 void FD_ZERO(fd_set* fdset);
34 
35 FD_SETSIZE
36 
37 int  pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
38 int  select(int, fd_set*, fd_set*, fd_set*, timeval*);
39 */
40 
41 version( linux )
42 {
43     private
44     {
45         alias c_long __fd_mask;
46         const int __NFDBITS = 8 * __fd_mask.sizeof;
47 
48         extern (D) int __FDELT( int d )
49         {
50             return d / __NFDBITS;
51         }
52 
53         extern (D) int __FDMASK( int d )
54         {
55             return cast(__fd_mask) (1 << ( d % __NFDBITS ));
56         }
57     }
58 
59     const FD_SETSIZE = 1024;
60 
61     struct fd_set
62     {
63         __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
64     }
65 
66     extern (D) void FD_CLR( int fd, fd_set* fdset )
67     {
68         fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
69     }
70 
71     extern (D) int  FD_ISSET( int fd, fd_set* fdset )
72     {
73         return cast(int)(fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd ));
74     }
75 
76     extern (D) void FD_SET( int fd, fd_set* fdset )
77     {
78         fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
79     }
80 
81     extern (D) void FD_ZERO( fd_set* fdset )
82     {
83         fdset.fds_bits[0 .. $] = 0;
84     }
85 
86     /+
87      + GNU ASM Implementation
88      +
89     # define __FD_ZERO(fdsp) \
90       do {                                        \
91         int __d0, __d1;                               \
92         __asm__ __volatile__ ("cld; rep; stosl"                   \
93                   : "=c" (__d0), "=D" (__d1)                  \
94                   : "a" (0), "0" (sizeof (fd_set)             \
95                           / sizeof (__fd_mask)),          \
96                     "1" (&__FDS_BITS (fdsp)[0])               \
97                   : "memory");                        \
98       } while (0)
99 
100     # define __FD_SET(fd, fdsp) \
101       __asm__ __volatile__ ("btsl %1,%0"                          \
102                 : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)])          \
103                 : "r" (((int) (fd)) % __NFDBITS)              \
104                 : "cc","memory")
105     # define __FD_CLR(fd, fdsp) \
106       __asm__ __volatile__ ("btrl %1,%0"                          \
107                 : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)])          \
108                 : "r" (((int) (fd)) % __NFDBITS)              \
109                 : "cc","memory")
110     # define __FD_ISSET(fd, fdsp) \
111       (__extension__                                  \
112        ({register char __result;                              \
113          __asm__ __volatile__ ("btl %1,%2 ; setcb %b0"                \
114                    : "=q" (__result)                      \
115                    : "r" (((int) (fd)) % __NFDBITS),              \
116                      "m" (__FDS_BITS (fdsp)[__FDELT (fd)])        \
117                    : "cc");                       \
118          __result; }))
119      +/
120 
121     int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
122     int select(int, fd_set*, fd_set*, fd_set*, timeval*);
123 }
124 else version(OSX)
125 {
126     private
127     {
128         const uint __DARWIN_NBBY = 8;                               /* bits in a byte */
129         const uint __DARWIN_NFDBITS = (int.sizeof * __DARWIN_NBBY); /* bits per mask */
130 
131         alias uint __fd_mask;
132         const __NFDBITS = 8 * __fd_mask.sizeof;
133 
134         extern (D) int __FDELT( int d )
135         {
136             return d / cast(int)__NFDBITS;
137         }
138 
139         extern (D) __fd_mask __FDMASK( int d )
140         {
141             return cast(__fd_mask) 1 << ( d % __NFDBITS );
142         }
143     }
144 
145     const FD_SETSIZE = 1024;
146 
147     struct fd_set
148     {
149         int[(((FD_SETSIZE) + ((__DARWIN_NFDBITS) - 1)) / (__DARWIN_NFDBITS))] fds_bits;
150     }
151     
152     extern (D) void FD_CLR( int fd, fd_set* fdset )
153     {
154         fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
155     }
156 
157     extern (D) int  FD_ISSET( int fd, fd_set* fdset )
158     {
159         return cast(int) (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd ));
160     }
161 
162     extern (D) void FD_SET( int fd, fd_set* fdset )
163     {
164         fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
165     }
166 
167     extern (D) void FD_ZERO( fd_set* fdset )
168     {
169         fdset.fds_bits[0 .. $] = 0;
170     }
171     
172 }
173 else version( FreeBSD )
174 {
175 	private
176 	{
177 		const uint FD_SETSIZE = 1024;
178         alias c_long __fd_mask;
179         const _NFDBITS = 8 * __fd_mask.sizeof;
180 
181         extern (D) int __FDELT( int d )
182         {
183             return cast(int) (d / _NFDBITS);
184         }
185 
186         extern (D) __fd_mask __FDMASK( int d )
187         {
188             return cast(__fd_mask) 1 << ( d % _NFDBITS );
189         }
190 	}
191 	struct fd_set
192 	{
193 		c_ulong[((FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS)] fds_bits;
194 	}
195     extern (D) void FD_CLR( int fd, fd_set* fdset )
196     {
197         fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
198     }
199 
200     extern (D) int  FD_ISSET( int fd, fd_set* fdset )
201     {
202         return cast(int) (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd ));
203     }
204 
205     extern (D) void FD_SET( int fd, fd_set* fdset )
206     {
207         fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
208     }
209 
210     extern (D) void FD_ZERO( fd_set* fdset )
211     {
212         fdset.fds_bits[0 .. $] = 0;
213     }
214 }
215 else version( solaris )
216 {
217 	private
218     {
219         alias c_long __fd_mask;
220 		const NBBY = 8;
221         const FD_NFDBITS = __fd_mask.sizeof * NBBY;	/* bits per mask */
222 	
223         extern (D) int __FDELT( int d )
224         {
225             return d / FD_NFDBITS;
226         }
227 
228         extern (D) __fd_mask __FDMASK( int d )
229         {
230             return cast(__fd_mask) 1 << ( d % FD_NFDBITS );
231         }
232     }
233 	
234 	version (X86_64)	const FD_SETSIZE = 65536;
235 	else				const FD_SETSIZE = 1024;
236 	
237     struct fd_set
238     {
239 		__fd_mask[( FD_SETSIZE + FD_NFDBITS - 1 ) / FD_NFDBITS] fds_bits;
240     }
241 	
242 	extern (D) void FD_CLR( int fd, fd_set* fdset )
243     {
244 	    fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
245     }
246 
247     extern (D) int  FD_ISSET( int fd, fd_set* fdset )
248     {
249         return fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd );
250     }
251 
252     extern (D) void FD_SET( int fd, fd_set* fdset )
253     {
254         fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
255     }
256 
257     extern (D) void FD_ZERO( fd_set* fdset )
258     {
259         fdset.fds_bits[0 .. $] = 0;
260     }
261 }