]> git.ipfire.org Git - people/ms/gcc.git/blob - libphobos/libdruntime/core/sys/posix/sys/select.d
d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
[people/ms/gcc.git] / libphobos / libdruntime / core / sys / posix / sys / select.d
1 /**
2 * D header file for POSIX.
3 *
4 * Copyright: Copyright Sean Kelly 2005 - 2016.
5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors: Sean Kelly, Alex Rønne Petersen
7 * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
8 */
9 module core.sys.posix.sys.select;
10
11 import core.sys.posix.config;
12 public import core.stdc.time; // for timespec
13 public import core.sys.posix.sys.time; // for timeval
14 public import core.sys.posix.sys.types; // for time_t
15 public import core.sys.posix.signal; // for sigset_t
16
17 //debug=select; // uncomment to turn on debugging printf's
18
19 version (OSX)
20 version = Darwin;
21 else version (iOS)
22 version = Darwin;
23 else version (TVOS)
24 version = Darwin;
25 else version (WatchOS)
26 version = Darwin;
27
28 version (Posix):
29 extern (C) nothrow @nogc:
30
31 //
32 // Required
33 //
34 /*
35 NOTE: This module requires timeval from core.sys.posix.sys.time, but timeval
36 is supposedly an XOpen extension. As a result, this header will not
37 compile on platforms that are not XSI-compliant. This must be resolved
38 on a per-platform basis.
39
40 fd_set
41
42 void FD_CLR(int fd, fd_set* fdset);
43 int FD_ISSET(int fd, const(fd_set)* fdset);
44 void FD_SET(int fd, fd_set* fdset);
45 void FD_ZERO(fd_set* fdset);
46
47 FD_SETSIZE
48
49 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
50 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
51 */
52
53 version (CRuntime_Glibc)
54 {
55 private
56 {
57 alias c_long __fd_mask;
58 enum uint __NFDBITS = 8 * __fd_mask.sizeof;
59
60 extern (D) auto __FDELT( int d ) pure
61 {
62 return d / __NFDBITS;
63 }
64
65 extern (D) auto __FDMASK( int d ) pure
66 {
67 return cast(__fd_mask) 1 << ( d % __NFDBITS );
68 }
69 }
70
71 enum FD_SETSIZE = 1024;
72
73 struct fd_set
74 {
75 __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
76 }
77
78 extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
79 {
80 fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
81 }
82
83 extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
84 {
85 return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
86 }
87
88 extern (D) void FD_SET( int fd, fd_set* fdset ) pure
89 {
90 fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
91 }
92
93 extern (D) void FD_ZERO( fd_set* fdset ) pure
94 {
95 fdset.fds_bits[0 .. $] = 0;
96 }
97
98 /+
99 + GNU ASM Implementation
100 +
101 # define __FD_ZERO(fdsp) \
102 do { \
103 int __d0, __d1; \
104 __asm__ __volatile__ ("cld; rep; stosl" \
105 : "=c" (__d0), "=D" (__d1) \
106 : "a" (0), "0" (sizeof (fd_set) \
107 / sizeof (__fd_mask)), \
108 "1" (&__FDS_BITS (fdsp)[0]) \
109 : "memory"); \
110 } while (0)
111
112 # define __FD_SET(fd, fdsp) \
113 __asm__ __volatile__ ("btsl %1,%0" \
114 : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \
115 : "r" (((int) (fd)) % __NFDBITS) \
116 : "cc","memory")
117 # define __FD_CLR(fd, fdsp) \
118 __asm__ __volatile__ ("btrl %1,%0" \
119 : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \
120 : "r" (((int) (fd)) % __NFDBITS) \
121 : "cc","memory")
122 # define __FD_ISSET(fd, fdsp) \
123 (__extension__ \
124 ({register char __result; \
125 __asm__ __volatile__ ("btl %1,%2 ; setcb %b0" \
126 : "=q" (__result) \
127 : "r" (((int) (fd)) % __NFDBITS), \
128 "m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \
129 : "cc"); \
130 __result; }))
131 +/
132
133 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
134 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
135 }
136 else version (Darwin)
137 {
138 private
139 {
140 enum uint __DARWIN_NBBY = 8; /* bits in a byte */
141 enum uint __DARWIN_NFDBITS = (int.sizeof * __DARWIN_NBBY); /* bits per mask */
142 }
143
144 enum FD_SETSIZE = 1024;
145
146 struct fd_set
147 {
148 int[(FD_SETSIZE + (__DARWIN_NFDBITS - 1)) / __DARWIN_NFDBITS] fds_bits;
149 }
150
151 extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
152 {
153 fdset.fds_bits[fd / __DARWIN_NFDBITS] &= ~(1 << (fd % __DARWIN_NFDBITS));
154 }
155
156 extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
157 {
158 return (fdset.fds_bits[fd / __DARWIN_NFDBITS] & (1 << (fd % __DARWIN_NFDBITS))) != 0;
159 }
160
161 extern (D) void FD_SET( int fd, fd_set* fdset ) pure
162 {
163 fdset.fds_bits[fd / __DARWIN_NFDBITS] |= 1 << (fd % __DARWIN_NFDBITS);
164 }
165
166 extern (D) void FD_ZERO( fd_set* fdset ) pure
167 {
168 fdset.fds_bits[0 .. $] = 0;
169 }
170
171 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
172 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
173 }
174 else version (FreeBSD)
175 {
176 private
177 {
178 alias c_ulong __fd_mask;
179 enum _NFDBITS = __fd_mask.sizeof * 8;
180 }
181
182 enum uint FD_SETSIZE = 1024;
183
184 struct fd_set
185 {
186 __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
187 }
188
189 extern (D) __fd_mask __fdset_mask(uint n) pure
190 {
191 return cast(__fd_mask) 1 << (n % _NFDBITS);
192 }
193
194 extern (D) void FD_CLR( int n, fd_set* p ) pure
195 {
196 p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
197 }
198
199 extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
200 {
201 return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
202 }
203
204 extern (D) void FD_SET( int n, fd_set* p ) pure
205 {
206 p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
207 }
208
209 extern (D) void FD_ZERO( fd_set* p ) pure
210 {
211 fd_set *_p;
212 size_t _n;
213
214 _p = p;
215 _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
216 while (_n > 0)
217 _p.__fds_bits[--_n] = 0;
218 }
219
220 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
221 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
222 }
223 else version (NetBSD)
224 {
225 private
226 {
227 alias c_ulong __fd_mask;
228 enum _NFDBITS = __fd_mask.sizeof * 8;
229 }
230
231 enum uint FD_SETSIZE = 256;
232
233 struct fd_set
234 {
235 __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
236 }
237
238 extern (D) __fd_mask __fdset_mask(uint n) pure
239 {
240 return cast(__fd_mask) 1 << (n % _NFDBITS);
241 }
242
243 extern (D) void FD_CLR( int n, fd_set* p ) pure
244 {
245 p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
246 }
247
248 extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
249 {
250 return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
251 }
252
253 extern (D) void FD_SET( int n, fd_set* p ) pure
254 {
255 p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
256 }
257
258 extern (D) void FD_ZERO( fd_set* p ) pure
259 {
260 fd_set *_p;
261 size_t _n;
262
263 _p = p;
264 _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
265 while (_n > 0)
266 _p.__fds_bits[--_n] = 0;
267 }
268
269 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
270 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
271 }
272 else version (OpenBSD)
273 {
274 private
275 {
276 alias uint __fd_mask;
277 enum _NFDBITS = __fd_mask.sizeof * 8;
278 }
279
280 enum uint FD_SETSIZE = 1024;
281
282 struct fd_set
283 {
284 __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
285 }
286
287 extern (D) __fd_mask __fdset_mask(uint n) pure
288 {
289 return cast(__fd_mask) 1 << (n % _NFDBITS);
290 }
291
292 extern (D) void FD_CLR(int n, fd_set* p) pure
293 {
294 p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
295 }
296
297 extern (D) bool FD_ISSET(int n, const(fd_set)* p) pure
298 {
299 return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
300 }
301
302 extern (D) void FD_SET(int n, fd_set* p) pure
303 {
304 p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
305 }
306
307 extern (D) void FD_ZERO(fd_set* p) pure
308 {
309 fd_set *_p = p;
310 size_t _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
311
312 while (_n > 0)
313 _p.__fds_bits[--_n] = 0;
314 }
315
316 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
317 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
318 }
319 else version (DragonFlyBSD)
320 {
321 private
322 {
323 alias c_ulong __fd_mask;
324 enum _NFDBITS = __fd_mask.sizeof * 8;
325 }
326
327 enum uint FD_SETSIZE = 1024;
328
329 struct fd_set
330 {
331 __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
332 }
333
334 extern (D) __fd_mask __fdset_mask(uint n) pure
335 {
336 return cast(__fd_mask) 1 << (n % _NFDBITS);
337 }
338
339 extern (D) void FD_CLR( int n, fd_set* p ) pure
340 {
341 p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
342 }
343
344 extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
345 {
346 return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
347 }
348
349 extern (D) void FD_SET( int n, fd_set* p ) pure
350 {
351 p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
352 }
353
354 extern (D) void FD_ZERO( fd_set* p ) pure
355 {
356 fd_set *_p;
357 size_t _n;
358
359 _p = p;
360 _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
361 while (_n > 0)
362 _p.__fds_bits[--_n] = 0;
363 }
364
365 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
366 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
367 }
368 else version (Solaris)
369 {
370 private
371 {
372 alias c_long fds_mask;
373
374 enum _NBBY = 8;
375 enum FD_NFDBITS = fds_mask.sizeof * _NBBY;
376 }
377
378 version (D_LP64)
379 enum uint FD_SETSIZE = 65536;
380 else
381 enum uint FD_SETSIZE = 1024;
382
383 struct fd_set
384 {
385 c_long[(FD_SETSIZE + (FD_NFDBITS - 1)) / FD_NFDBITS] fds_bits;
386 }
387
388 extern (D) void FD_SET(int __n, fd_set* __p) pure
389 {
390 __p.fds_bits[__n / FD_NFDBITS] |= 1UL << (__n % FD_NFDBITS);
391 }
392
393 extern (D) void FD_CLR(int __n, fd_set* __p) pure
394 {
395 __p.fds_bits[__n / FD_NFDBITS] &= ~(1UL << (__n % FD_NFDBITS));
396 }
397
398 extern (D) bool FD_ISSET(int __n, const(fd_set)* __p) pure
399 {
400 return (__p.fds_bits[__n / FD_NFDBITS] & (1UL << (__n % FD_NFDBITS))) != 0;
401 }
402
403 extern (D) void FD_ZERO(fd_set* __p) pure
404 {
405 __p.fds_bits[0 .. $] = 0;
406 }
407
408 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
409 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
410 }
411 else version (CRuntime_Bionic)
412 {
413 private
414 {
415 alias c_ulong __fd_mask;
416 enum uint __NFDBITS = 8 * __fd_mask.sizeof;
417
418 extern (D) auto __FDELT( int d ) pure
419 {
420 return d / __NFDBITS;
421 }
422
423 extern (D) auto __FDMASK( int d ) pure
424 {
425 return cast(__fd_mask) 1 << ( d % __NFDBITS );
426 }
427 }
428
429 enum FD_SETSIZE = 1024;
430
431 struct fd_set
432 {
433 __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
434 }
435
436 // These functions are generated in assembly in bionic.
437 extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
438 {
439 fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
440 }
441
442 extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
443 {
444 return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
445 }
446
447 extern (D) void FD_SET( int fd, fd_set* fdset ) pure
448 {
449 fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
450 }
451
452 extern (D) void FD_ZERO( fd_set* fdset ) pure
453 {
454 fdset.fds_bits[0 .. $] = 0;
455 }
456
457 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
458 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
459 }
460 else version (CRuntime_Musl)
461 {
462 enum FD_SETSIZE = 1024;
463
464 alias ulong fd_mask;
465
466 private
467 {
468 enum uint __NFDBITS = 8 * fd_mask.sizeof;
469
470 extern (D) auto __FDELT( int d ) pure
471 {
472 return d / __NFDBITS;
473 }
474
475 extern (D) auto __FDMASK( int d ) pure
476 {
477 return cast(fd_mask) 1 << ( d % __NFDBITS );
478 }
479 }
480
481 struct fd_set {
482 ulong[FD_SETSIZE / 8 / long.sizeof] fds_bits;
483 }
484
485 extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
486 {
487 fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
488 }
489
490 extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
491 {
492 return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
493 }
494
495 extern (D) void FD_SET( int fd, fd_set* fdset ) pure
496 {
497 fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
498 }
499
500 extern (D) void FD_ZERO( fd_set* fdset ) pure
501 {
502 fdset.fds_bits[0 .. $] = 0;
503 }
504 pragma(mangle, muslRedirTime64Mangle!("pselect", "__pselect_time64"))
505 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
506 pragma(mangle, muslRedirTime64Mangle!("select", "__select_time64"))
507 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
508 }
509 else version (CRuntime_UClibc)
510 {
511 private
512 {
513 alias c_long __fd_mask;
514 enum uint __NFDBITS = 8 * __fd_mask.sizeof;
515
516 extern (D) auto __FDELT( int d ) pure
517 {
518 return d / __NFDBITS;
519 }
520
521 extern (D) auto __FDMASK( int d ) pure
522 {
523 return cast(__fd_mask) 1 << ( d % __NFDBITS );
524 }
525 }
526
527 enum FD_SETSIZE = 1024;
528
529 struct fd_set
530 {
531 __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits;
532 }
533
534 extern (D) void FD_CLR( int fd, fd_set* fdset ) pure
535 {
536 fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd );
537 }
538
539 extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure
540 {
541 return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0;
542 }
543
544 extern (D) void FD_SET( int fd, fd_set* fdset ) pure
545 {
546 fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd );
547 }
548
549 extern (D) void FD_ZERO( fd_set* fdset ) pure
550 {
551 fdset.fds_bits[0 .. $] = 0;
552 }
553
554 int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
555 int select(int, fd_set*, fd_set*, fd_set*, timeval*);
556 }
557 else
558 {
559 static assert(false, "Unsupported platform");
560 }
561
562 pure unittest
563 {
564 import core.stdc.stdio: printf;
565
566 debug(select) printf("core.sys.posix.sys.select unittest\n");
567
568 fd_set fd;
569
570 for (auto i = 0; i < FD_SETSIZE; i++)
571 {
572 assert(!FD_ISSET(i, &fd));
573 }
574
575 for (auto i = 0; i < FD_SETSIZE; i++)
576 {
577 if ((i & -i) == i)
578 FD_SET(i, &fd);
579 }
580
581 for (auto i = 0; i < FD_SETSIZE; i++)
582 {
583 if ((i & -i) == i)
584 assert(FD_ISSET(i, &fd));
585 else
586 assert(!FD_ISSET(i, &fd));
587 }
588
589 for (auto i = 0; i < FD_SETSIZE; i++)
590 {
591 if ((i & -i) == i)
592 FD_CLR(i, &fd);
593 else
594 FD_SET(i, &fd);
595 }
596
597 for (auto i = 0; i < FD_SETSIZE; i++)
598 {
599 if ((i & -i) == i)
600 assert(!FD_ISSET(i, &fd));
601 else
602 assert(FD_ISSET(i, &fd));
603 }
604
605 FD_ZERO(&fd);
606
607 for (auto i = 0; i < FD_SETSIZE; i++)
608 {
609 assert(!FD_ISSET(i, &fd));
610 }
611 }