sys_select.odin 3.2 KB

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