| /** |
| * D header file for POSIX. |
| * |
| * Copyright: Copyright Sean Kelly 2005 - 2016. |
| * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). |
| * Authors: Sean Kelly, Alex Rønne Petersen |
| * Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition |
| */ |
| module core.sys.posix.sys.select; |
| |
| import core.sys.posix.config; |
| public import core.stdc.time; // for timespec |
| public import core.sys.posix.sys.time; // for timeval |
| public import core.sys.posix.sys.types; // for time_t |
| public import core.sys.posix.signal; // for sigset_t |
| |
| //debug=select; // uncomment to turn on debugging printf's |
| |
| version (OSX) |
| version = Darwin; |
| else version (iOS) |
| version = Darwin; |
| else version (TVOS) |
| version = Darwin; |
| else version (WatchOS) |
| version = Darwin; |
| |
| version (Posix): |
| extern (C) nothrow @nogc: |
| |
| // |
| // Required |
| // |
| /* |
| NOTE: This module requires timeval from core.sys.posix.sys.time, but timeval |
| is supposedly an XOpen extension. As a result, this header will not |
| compile on platforms that are not XSI-compliant. This must be resolved |
| on a per-platform basis. |
| |
| fd_set |
| |
| void FD_CLR(int fd, fd_set* fdset); |
| int FD_ISSET(int fd, const(fd_set)* fdset); |
| void FD_SET(int fd, fd_set* fdset); |
| void FD_ZERO(fd_set* fdset); |
| |
| FD_SETSIZE |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| */ |
| |
| version (CRuntime_Glibc) |
| { |
| private |
| { |
| alias __fd_mask = c_long; |
| enum uint __NFDBITS = 8 * __fd_mask.sizeof; |
| |
| extern (D) auto __FDELT()( int d ) pure |
| { |
| return d / __NFDBITS; |
| } |
| |
| extern (D) auto __FDMASK()( int d ) pure |
| { |
| return cast(__fd_mask) 1 << ( d % __NFDBITS ); |
| } |
| } |
| |
| enum FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits; |
| } |
| |
| extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); |
| } |
| |
| extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure |
| { |
| return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; |
| } |
| |
| extern (D) void FD_SET()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* fdset ) pure |
| { |
| fdset.fds_bits[0 .. $] = 0; |
| } |
| |
| /+ |
| + GNU ASM Implementation |
| + |
| # define __FD_ZERO(fdsp) \ |
| do { \ |
| int __d0, __d1; \ |
| __asm__ __volatile__ ("cld; rep; stosl" \ |
| : "=c" (__d0), "=D" (__d1) \ |
| : "a" (0), "0" (sizeof (fd_set) \ |
| / sizeof (__fd_mask)), \ |
| "1" (&__FDS_BITS (fdsp)[0]) \ |
| : "memory"); \ |
| } while (0) |
| |
| # define __FD_SET(fd, fdsp) \ |
| __asm__ __volatile__ ("btsl %1,%0" \ |
| : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ |
| : "r" (((int) (fd)) % __NFDBITS) \ |
| : "cc","memory") |
| # define __FD_CLR(fd, fdsp) \ |
| __asm__ __volatile__ ("btrl %1,%0" \ |
| : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ |
| : "r" (((int) (fd)) % __NFDBITS) \ |
| : "cc","memory") |
| # define __FD_ISSET(fd, fdsp) \ |
| (__extension__ \ |
| ({register char __result; \ |
| __asm__ __volatile__ ("btl %1,%2 ; setcb %b0" \ |
| : "=q" (__result) \ |
| : "r" (((int) (fd)) % __NFDBITS), \ |
| "m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ |
| : "cc"); \ |
| __result; })) |
| +/ |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (Darwin) |
| { |
| private |
| { |
| enum uint __DARWIN_NBBY = 8; /* bits in a byte */ |
| enum uint __DARWIN_NFDBITS = (int.sizeof * __DARWIN_NBBY); /* bits per mask */ |
| } |
| |
| enum FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| int[(FD_SETSIZE + (__DARWIN_NFDBITS - 1)) / __DARWIN_NFDBITS] fds_bits; |
| } |
| |
| extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[fd / __DARWIN_NFDBITS] &= ~(1 << (fd % __DARWIN_NFDBITS)); |
| } |
| |
| extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure |
| { |
| return (fdset.fds_bits[fd / __DARWIN_NFDBITS] & (1 << (fd % __DARWIN_NFDBITS))) != 0; |
| } |
| |
| extern (D) void FD_SET()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[fd / __DARWIN_NFDBITS] |= 1 << (fd % __DARWIN_NFDBITS); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* fdset ) pure |
| { |
| fdset.fds_bits[0 .. $] = 0; |
| } |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (FreeBSD) |
| { |
| private |
| { |
| alias __fd_mask = c_ulong; |
| enum _NFDBITS = __fd_mask.sizeof * 8; |
| } |
| |
| enum uint FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits; |
| deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; |
| } |
| |
| extern (D) __fd_mask __fdset_mask()(uint n) pure |
| { |
| return cast(__fd_mask) 1 << (n % _NFDBITS); |
| } |
| |
| extern (D) void FD_CLR()( int n, fd_set* p ) pure |
| { |
| p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); |
| } |
| |
| extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure |
| { |
| return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; |
| } |
| |
| extern (D) void FD_SET()( int n, fd_set* p ) pure |
| { |
| p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* p ) pure |
| { |
| fd_set *_p; |
| size_t _n; |
| |
| _p = p; |
| _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS; |
| while (_n > 0) |
| _p.fds_bits[--_n] = 0; |
| } |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (NetBSD) |
| { |
| private |
| { |
| alias __fd_mask = c_ulong; |
| enum _NFDBITS = __fd_mask.sizeof * 8; |
| } |
| |
| enum uint FD_SETSIZE = 256; |
| |
| struct fd_set |
| { |
| __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits; |
| deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; |
| } |
| |
| extern (D) __fd_mask __fdset_mask()(uint n) pure |
| { |
| return cast(__fd_mask) 1 << (n % _NFDBITS); |
| } |
| |
| extern (D) void FD_CLR()( int n, fd_set* p ) pure |
| { |
| p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); |
| } |
| |
| extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure |
| { |
| return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; |
| } |
| |
| extern (D) void FD_SET()( int n, fd_set* p ) pure |
| { |
| p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* p ) pure |
| { |
| fd_set *_p; |
| size_t _n; |
| |
| _p = p; |
| _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS; |
| while (_n > 0) |
| _p.fds_bits[--_n] = 0; |
| } |
| |
| pragma(mangle, "__pselect50") |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| pragma(mangle, "__select50") |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (OpenBSD) |
| { |
| private |
| { |
| alias __fd_mask = uint; |
| enum _NFDBITS = __fd_mask.sizeof * 8; |
| } |
| |
| enum uint FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits; |
| deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; |
| } |
| |
| extern (D) __fd_mask __fdset_mask()(uint n) pure |
| { |
| return cast(__fd_mask) 1 << (n % _NFDBITS); |
| } |
| |
| extern (D) void FD_CLR()(int n, fd_set* p) pure |
| { |
| p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); |
| } |
| |
| extern (D) bool FD_ISSET()(int n, const(fd_set)* p) pure |
| { |
| return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; |
| } |
| |
| extern (D) void FD_SET()(int n, fd_set* p) pure |
| { |
| p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); |
| } |
| |
| extern (D) void FD_ZERO()(fd_set* p) pure |
| { |
| fd_set *_p = p; |
| size_t _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS; |
| |
| while (_n > 0) |
| _p.fds_bits[--_n] = 0; |
| } |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (DragonFlyBSD) |
| { |
| private |
| { |
| alias __fd_mask = c_ulong; |
| enum _NFDBITS = __fd_mask.sizeof * 8; |
| } |
| |
| enum uint FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits; |
| deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; |
| } |
| |
| extern (D) __fd_mask __fdset_mask()(uint n) pure |
| { |
| return cast(__fd_mask) 1 << (n % _NFDBITS); |
| } |
| |
| extern (D) void FD_CLR()( int n, fd_set* p ) pure |
| { |
| p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); |
| } |
| |
| extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure |
| { |
| return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; |
| } |
| |
| extern (D) void FD_SET()( int n, fd_set* p ) pure |
| { |
| p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* p ) pure |
| { |
| fd_set *_p; |
| size_t _n; |
| |
| _p = p; |
| _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS; |
| while (_n > 0) |
| _p.fds_bits[--_n] = 0; |
| } |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (Solaris) |
| { |
| private |
| { |
| alias fds_mask = c_long; |
| |
| enum _NBBY = 8; |
| enum FD_NFDBITS = fds_mask.sizeof * _NBBY; |
| } |
| |
| version (D_LP64) |
| enum uint FD_SETSIZE = 65536; |
| else |
| enum uint FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| c_long[(FD_SETSIZE + (FD_NFDBITS - 1)) / FD_NFDBITS] fds_bits; |
| } |
| |
| extern (D) void FD_SET()(int __n, fd_set* __p) pure |
| { |
| __p.fds_bits[__n / FD_NFDBITS] |= 1UL << (__n % FD_NFDBITS); |
| } |
| |
| extern (D) void FD_CLR()(int __n, fd_set* __p) pure |
| { |
| __p.fds_bits[__n / FD_NFDBITS] &= ~(1UL << (__n % FD_NFDBITS)); |
| } |
| |
| extern (D) bool FD_ISSET()(int __n, const(fd_set)* __p) pure |
| { |
| return (__p.fds_bits[__n / FD_NFDBITS] & (1UL << (__n % FD_NFDBITS))) != 0; |
| } |
| |
| extern (D) void FD_ZERO()(fd_set* __p) pure |
| { |
| __p.fds_bits[0 .. $] = 0; |
| } |
| |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| } |
| else version (CRuntime_Bionic) |
| { |
| private |
| { |
| alias __fd_mask = c_ulong; |
| enum uint __NFDBITS = 8 * __fd_mask.sizeof; |
| |
| extern (D) auto __FDELT()( int d ) pure |
| { |
| return d / __NFDBITS; |
| } |
| |
| extern (D) auto __FDMASK()( int d ) pure |
| { |
| return cast(__fd_mask) 1 << ( d % __NFDBITS ); |
| } |
| } |
| |
| enum FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits; |
| } |
| |
| // These functions are generated in assembly in bionic. |
| extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); |
| } |
| |
| extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure |
| { |
| return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; |
| } |
| |
| extern (D) void FD_SET()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* fdset ) pure |
| { |
| fdset.fds_bits[0 .. $] = 0; |
| } |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (CRuntime_Musl) |
| { |
| enum FD_SETSIZE = 1024; |
| |
| alias fd_mask = ulong; |
| |
| private |
| { |
| enum uint __NFDBITS = 8 * fd_mask.sizeof; |
| |
| extern (D) auto __FDELT()( int d ) pure |
| { |
| return d / __NFDBITS; |
| } |
| |
| extern (D) auto __FDMASK()( int d ) pure |
| { |
| return cast(fd_mask) 1 << ( d % __NFDBITS ); |
| } |
| } |
| |
| struct fd_set { |
| ulong[FD_SETSIZE / 8 / long.sizeof] fds_bits; |
| } |
| |
| extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); |
| } |
| |
| extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure |
| { |
| return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; |
| } |
| |
| extern (D) void FD_SET()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* fdset ) pure |
| { |
| fdset.fds_bits[0 .. $] = 0; |
| } |
| pragma(mangle, muslRedirTime64Mangle!("pselect", "__pselect_time64")) |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| pragma(mangle, muslRedirTime64Mangle!("select", "__select_time64")) |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else version (CRuntime_UClibc) |
| { |
| private |
| { |
| alias __fd_mask = c_long; |
| enum uint __NFDBITS = 8 * __fd_mask.sizeof; |
| |
| extern (D) auto __FDELT()( int d ) pure |
| { |
| return d / __NFDBITS; |
| } |
| |
| extern (D) auto __FDMASK()( int d ) pure |
| { |
| return cast(__fd_mask) 1 << ( d % __NFDBITS ); |
| } |
| } |
| |
| enum FD_SETSIZE = 1024; |
| |
| struct fd_set |
| { |
| __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits; |
| } |
| |
| extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); |
| } |
| |
| extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure |
| { |
| return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; |
| } |
| |
| extern (D) void FD_SET()( int fd, fd_set* fdset ) pure |
| { |
| fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); |
| } |
| |
| extern (D) void FD_ZERO()( fd_set* fdset ) pure |
| { |
| fdset.fds_bits[0 .. $] = 0; |
| } |
| |
| int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*); |
| int select(int, fd_set*, fd_set*, fd_set*, timeval*); |
| } |
| else |
| { |
| static assert(false, "Unsupported platform"); |
| } |
| |
| pure unittest |
| { |
| import core.stdc.stdio: printf; |
| |
| debug(select) printf("core.sys.posix.sys.select unittest\n"); |
| |
| fd_set fd; |
| |
| for (auto i = 0; i < FD_SETSIZE; i++) |
| { |
| assert(!FD_ISSET(i, &fd)); |
| } |
| |
| for (auto i = 0; i < FD_SETSIZE; i++) |
| { |
| if ((i & -i) == i) |
| FD_SET(i, &fd); |
| } |
| |
| for (auto i = 0; i < FD_SETSIZE; i++) |
| { |
| if ((i & -i) == i) |
| assert(FD_ISSET(i, &fd)); |
| else |
| assert(!FD_ISSET(i, &fd)); |
| } |
| |
| for (auto i = 0; i < FD_SETSIZE; i++) |
| { |
| if ((i & -i) == i) |
| FD_CLR(i, &fd); |
| else |
| FD_SET(i, &fd); |
| } |
| |
| for (auto i = 0; i < FD_SETSIZE; i++) |
| { |
| if ((i & -i) == i) |
| assert(!FD_ISSET(i, &fd)); |
| else |
| assert(FD_ISSET(i, &fd)); |
| } |
| |
| FD_ZERO(&fd); |
| |
| for (auto i = 0; i < FD_SETSIZE; i++) |
| { |
| assert(!FD_ISSET(i, &fd)); |
| } |
| } |