aboutsummaryrefslogtreecommitdiff
path: root/core/sync/futex_linux.odin
blob: 2f4b5af7220ef0ed5f665a16d789b3bd49bbed4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#+private
#+build linux
package sync

import "core:time"
import "core:sys/linux"

_futex_wait :: proc "contextless" (futex: ^Futex, expected: u32) -> bool {
	errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected)
	if errno == .ETIMEDOUT {
		return false
	}
	#partial switch errno {
	case .NONE, .EINTR, .EAGAIN:
		return true
	case:
		// TODO(flysand): More descriptive panic messages based on the vlaue of `errno`
		panic_contextless("futex_wait failure")
	}
}

_futex_wait_with_timeout :: proc "contextless" (futex: ^Futex, expected: u32, duration: time.Duration) -> bool {
	if duration <= 0 {
		return false
	}
	errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAIT, {.PRIVATE}, expected, &linux.Time_Spec{
		time_sec  = cast(uint)(duration/1e9),
		time_nsec = cast(uint)(duration%1e9),
	})
	if errno == .ETIMEDOUT {
		return false
	}
	#partial switch errno {
	case .NONE, .EINTR, .EAGAIN:
		return true
	case:
		panic_contextless("futex_wait_with_timeout failure")
	}
}

_futex_signal :: proc "contextless" (futex: ^Futex) {
	_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, 1)
	#partial switch errno {
	case .NONE:
		return
	case:
		panic_contextless("futex_wake_single failure")
	}
}

_futex_broadcast :: proc "contextless" (futex: ^Futex)  {
	_, errno := linux.futex(cast(^linux.Futex) futex, linux.FUTEX_WAKE, {.PRIVATE}, max(i32))
	#partial switch errno {
	case .NONE:
		return
	case:
		panic_contextless("_futex_wake_all failure")
	}
}