| /** | |
| * 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 c_long __fd_mask; | |
| 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 c_ulong __fd_mask; | |
| 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 c_ulong __fd_mask; | |
| 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; | |
| } | |
| 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 (OpenBSD) | |
| { | |
| private | |
| { | |
| alias uint __fd_mask; | |
| 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 c_ulong __fd_mask; | |
| 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 c_long fds_mask; | |
| 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 c_ulong __fd_mask; | |
| 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 ulong fd_mask; | |
| 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 c_long __fd_mask; | |
| 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)); | |
| } | |
| } |