futex_netbsd.odin 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. //+private
  2. package sync
  3. import "base:intrinsics"
  4. import "core:time"
  5. import "core:c"
  6. import "core:sys/unix"
  7. foreign import libc "system:c"
  8. FUTEX_PRIVATE_FLAG :: 128
  9. FUTEX_WAIT_PRIVATE :: 0 | FUTEX_PRIVATE_FLAG
  10. FUTEX_WAKE_PRIVATE :: 1 | FUTEX_PRIVATE_FLAG
  11. EINTR :: 4 /* Interrupted system call */
  12. EAGAIN :: 35 /* Resource temporarily unavailable */
  13. ETIMEDOUT :: 60 /* Operation timed out */
  14. Time_Spec :: struct {
  15. time_sec: uint,
  16. time_nsec: uint,
  17. }
  18. get_last_error :: proc "contextless" () -> int {
  19. foreign libc {
  20. __errno :: proc() -> ^c.int ---
  21. }
  22. return int(__errno()^)
  23. }
  24. _futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
  25. if error, ok := intrinsics.syscall_bsd(unix.SYS___futex, uintptr(futex), FUTEX_WAIT_PRIVATE, uintptr(expected), 0, 0, 0); !ok {
  26. switch error {
  27. case EINTR, EAGAIN:
  28. return true
  29. case:
  30. _panic("futex_wait failure")
  31. }
  32. }
  33. return true
  34. }
  35. _futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, duration: time.Duration) -> bool {
  36. if duration <= 0 {
  37. return false
  38. }
  39. if error, ok := intrinsics.syscall_bsd(unix.SYS___futex, uintptr(futex), FUTEX_WAIT_PRIVATE, uintptr(expected), cast(uintptr) &Time_Spec{
  40. time_sec = cast(uint)(duration / 1e9),
  41. time_nsec = cast(uint)(duration % 1e9),
  42. }, 0, 0); !ok {
  43. switch error {
  44. case EINTR, EAGAIN:
  45. return true
  46. case ETIMEDOUT:
  47. return false
  48. case:
  49. _panic("futex_wait_with_timeout failure")
  50. }
  51. }
  52. return true
  53. }
  54. _futex_signal :: proc "contextless" (futex: ^Futex) {
  55. if _, ok := intrinsics.syscall_bsd(unix.SYS___futex, uintptr(futex), FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); !ok {
  56. _panic("futex_wake_single failure")
  57. }
  58. }
  59. _futex_broadcast :: proc "contextless" (futex: ^Futex) {
  60. if _, ok := intrinsics.syscall_bsd(unix.SYS___futex, uintptr(futex), FUTEX_WAKE_PRIVATE, uintptr(max(i32)), 0, 0, 0); !ok {
  61. _panic("_futex_wake_all failure")
  62. }
  63. }