sys_select.odin 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #+build linux, darwin, netbsd, openbsd, freebsd
  2. package posix
  3. import "base:intrinsics"
  4. import "core:c"
  5. when ODIN_OS == .Darwin {
  6. foreign import lib "system:System.framework"
  7. } else {
  8. foreign import lib "system:c"
  9. }
  10. // sys/select.h - select types
  11. foreign lib {
  12. /*
  13. Examines the file descriptor sets to see whether some of their descriptors are ready for writing,
  14. or have an exceptional condition pending, respectively.
  15. Returns: -1 (setting errno) on failure, total amount of bits set in the bit masks otherwise
  16. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html ]]
  17. */
  18. @(link_name=LPSELECT)
  19. pselect :: proc(
  20. nfds: c.int,
  21. readfds: ^fd_set,
  22. writefds: ^fd_set,
  23. errorfds: ^fd_set,
  24. timeout: ^timespec,
  25. sigmask: ^sigset_t,
  26. ) -> c.int ---
  27. /*
  28. Equivalent to pselect() except a more specific timeout resolution (nanoseconds),
  29. does not have a signal mask, and may modify the timeout.
  30. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html ]]
  31. */
  32. @(link_name=LSELECT)
  33. select :: proc(
  34. nfds: c.int,
  35. readfds: ^fd_set,
  36. writefds: ^fd_set,
  37. errorfds: ^fd_set,
  38. timeout: ^timeval,
  39. ) -> c.int ---
  40. }
  41. when ODIN_OS == .NetBSD {
  42. LPSELECT :: "__pselect50"
  43. LSELECT :: "__select50"
  44. } else {
  45. LPSELECT :: "pselect"
  46. LSELECT :: "select"
  47. }
  48. when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
  49. suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long)
  50. timeval :: struct {
  51. tv_sec: time_t, /* [PSX] seconds */
  52. tv_usec: suseconds_t, /* [PSX] microseconds */
  53. }
  54. // Maximum number of file descriptors in the fd_set structure.
  55. FD_SETSIZE :: #config(POSIX_FD_SETSIZE, 256 when ODIN_OS == .NetBSD else 1024)
  56. @(private)
  57. __NFDBITS :: size_of(c.int32_t) * 8
  58. // NOTE: this seems correct for FreeBSD but they do use a set backed by the long type themselves (thus the align change).
  59. @(private)
  60. ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t)
  61. fd_set :: struct #align(ALIGN) {
  62. fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
  63. }
  64. @(private)
  65. __check_fd_set :: #force_inline proc "contextless" (_a: FD, _b: rawptr) -> bool {
  66. if _a < 0 {
  67. set_errno(.EINVAL)
  68. }
  69. if _a >= FD_SETSIZE {
  70. set_errno(.EINVAL)
  71. }
  72. return true
  73. }
  74. FD_CLR :: #force_inline proc "contextless" (_fd: FD, _p: ^fd_set) {
  75. if __check_fd_set(_fd, _p) {
  76. _p.fds_bits[cast(c.ulong)_fd / __NFDBITS] &= ~cast(c.int32_t)((cast(c.ulong)1) << (cast(c.ulong)_fd % __NFDBITS))
  77. }
  78. }
  79. FD_ISSET :: #force_inline proc "contextless" (_fd: FD, _p: ^fd_set) -> bool {
  80. if __check_fd_set(_fd, _p) {
  81. return bool(_p.fds_bits[cast(c.ulong)_fd / __NFDBITS] & cast(c.int32_t)((cast(c.ulong)1) << (cast(c.ulong)_fd % __NFDBITS)))
  82. }
  83. return false
  84. }
  85. FD_SET :: #force_inline proc "contextless" (_fd: FD, _p: ^fd_set) {
  86. if __check_fd_set(_fd, _p) {
  87. _p.fds_bits[cast(c.ulong)_fd / __NFDBITS] |= cast(c.int32_t)((cast(c.ulong)1) << (cast(c.ulong)_fd % __NFDBITS))
  88. }
  89. }
  90. FD_ZERO :: #force_inline proc "contextless" (_p: ^fd_set) {
  91. intrinsics.mem_zero(_p, size_of(fd_set))
  92. }
  93. }