blob: 5152d0fe17d0771eff6d11f92cfdec35f795580f [file]
/**
* 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));
}
}