futex_darwin.odin 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. //+private
  2. //+build darwin
  3. package sync
  4. import "core:c"
  5. import "core:time"
  6. foreign import System "System.framework"
  7. foreign System {
  8. __ulock_wait :: proc "c" (operation: u32, addr: rawptr, value: u64, timeout_us: u32) -> c.int ---
  9. __ulock_wait2 :: proc "c" (operation: u32, addr: rawptr, value: u64, timeout_ns: u64, value2: u64) -> c.int ---
  10. __ulock_wake :: proc "c" (operation: u32, addr: rawptr, wake_value: u64) -> c.int ---
  11. }
  12. UL_COMPARE_AND_WAIT :: 1
  13. ULF_WAKE_ALL :: 0x00000100
  14. ULF_NO_ERRNO :: 0x01000000
  15. ENOENT :: -2
  16. EINTR :: -4
  17. EFAULT :: -14
  18. ETIMEDOUT :: -60
  19. _futex_wait :: proc(f: ^Futex, expected: u32) -> bool {
  20. return _futex_wait_with_timeout(f, expected, 0)
  21. }
  22. _futex_wait_with_timeout :: proc(f: ^Futex, expected: u32, duration: time.Duration) -> bool {
  23. timeout_ns := u64(duration)
  24. s := __ulock_wait2(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, u64(expected), timeout_ns, 0)
  25. if s >= 0 {
  26. return true
  27. }
  28. switch s {
  29. case EINTR, EFAULT:
  30. return true
  31. case ETIMEDOUT:
  32. return false
  33. case:
  34. panic("futex_wait failure")
  35. }
  36. return true
  37. }
  38. _futex_signal :: proc(f: ^Futex) {
  39. loop: for {
  40. s := __ulock_wake(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO, f, 0)
  41. if s >= 0 {
  42. return
  43. }
  44. switch s {
  45. case EINTR, EFAULT:
  46. continue loop
  47. case ENOENT:
  48. return
  49. case:
  50. panic("futex_wake_single failure")
  51. }
  52. }
  53. }
  54. _futex_broadcast :: proc(f: ^Futex) {
  55. loop: for {
  56. s := __ulock_wake(UL_COMPARE_AND_WAIT | ULF_NO_ERRNO | ULF_WAKE_ALL, f, 0)
  57. if s >= 0 {
  58. return
  59. }
  60. switch s {
  61. case EINTR, EFAULT:
  62. continue loop
  63. case ENOENT:
  64. return
  65. case:
  66. panic("futex_wake_all failure")
  67. }
  68. }
  69. }