futex_openbsd.odin 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. //+private
  2. //+build openbsd
  3. package sync
  4. import "core:c"
  5. import "core:time"
  6. FUTEX_WAIT :: 1
  7. FUTEX_WAKE :: 2
  8. FUTEX_PRIVATE_FLAG :: 128
  9. FUTEX_WAIT_PRIVATE :: (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
  10. FUTEX_WAKE_PRIVATE :: (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
  11. ETIMEDOUT :: 60
  12. foreign import libc "system:c"
  13. foreign libc {
  14. @(link_name="futex")
  15. _unix_futex :: proc "c" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> c.int ---
  16. @(link_name="__errno") __errno :: proc() -> ^int ---
  17. }
  18. _futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
  19. res := _unix_futex(f, FUTEX_WAIT_PRIVATE, expected, nil)
  20. if res != -1 {
  21. return true
  22. }
  23. if __errno()^ == ETIMEDOUT {
  24. return false
  25. }
  26. _panic("futex_wait failure")
  27. }
  28. _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, duration: time.Duration) -> bool {
  29. if duration <= 0 {
  30. return false
  31. }
  32. timespec_t :: struct {
  33. tv_sec: c.long,
  34. tv_nsec: c.long,
  35. }
  36. res := _unix_futex(f, FUTEX_WAIT_PRIVATE, expected, &timespec_t{
  37. tv_sec = (c.long)(duration/1e9),
  38. tv_nsec = (c.long)(duration%1e9),
  39. })
  40. if res != -1 {
  41. return true
  42. }
  43. if __errno()^ == ETIMEDOUT {
  44. return false
  45. }
  46. _panic("futex_wait_with_timeout failure")
  47. }
  48. _futex_signal :: proc "contextless" (f: ^Futex) {
  49. res := _unix_futex(f, FUTEX_WAKE_PRIVATE, 1, nil)
  50. if res == -1 {
  51. _panic("futex_wake_single failure")
  52. }
  53. }
  54. _futex_broadcast :: proc "contextless" (f: ^Futex) {
  55. res := _unix_futex(f, FUTEX_WAKE_PRIVATE, u32(max(i32)), nil)
  56. if res == -1 {
  57. _panic("_futex_wake_all failure")
  58. }
  59. }