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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
//+private
package sync
when #config(ODIN_SYNC_RECURSIVE_MUTEX_USE_FUTEX, true) {
_Recursive_Mutex :: struct {
owner: Futex,
recursion: i32,
}
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
tid := Futex(current_thread_id())
for {
prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, 0, tid, .Acquire, .Acquire)
switch prev_owner {
case 0, tid:
m.impl.recursion += 1
// inside the lock
return
}
futex_wait(&m.impl.owner, u32(prev_owner))
}
}
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
m.impl.recursion -= 1
if m.impl.recursion != 0 {
return
}
atomic_exchange_explicit(&m.impl.owner, 0, .Release)
futex_signal(&m.impl.owner)
// outside the lock
}
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
tid := Futex(current_thread_id())
prev_owner := atomic_compare_exchange_strong_explicit(&m.impl.owner, 0, tid, .Acquire, .Acquire)
switch prev_owner {
case 0, tid:
m.impl.recursion += 1
// inside the lock
return true
}
return false
}
} else {
_Recursive_Mutex :: struct {
owner: int,
recursion: int,
mutex: Mutex,
}
_recursive_mutex_lock :: proc(m: ^Recursive_Mutex) {
tid := current_thread_id()
if tid != m.impl.owner {
mutex_lock(&m.impl.mutex)
}
// inside the lock
m.impl.owner = tid
m.impl.recursion += 1
}
_recursive_mutex_unlock :: proc(m: ^Recursive_Mutex) {
tid := current_thread_id()
assert(tid == m.impl.owner)
m.impl.recursion -= 1
recursion := m.impl.recursion
if recursion == 0 {
m.impl.owner = 0
}
if recursion == 0 {
mutex_unlock(&m.impl.mutex)
}
// outside the lock
}
_recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
tid := current_thread_id()
if m.impl.owner == tid {
return mutex_try_lock(&m.impl.mutex)
}
if !mutex_try_lock(&m.impl.mutex) {
return false
}
// inside the lock
m.impl.owner = tid
m.impl.recursion += 1
return true
}
}
when ODIN_OS != .Windows {
_RW_Mutex :: struct {
mutex: Atomic_RW_Mutex,
}
_rw_mutex_lock :: proc(rw: ^RW_Mutex) {
atomic_rw_mutex_lock(&rw.impl.mutex)
}
_rw_mutex_unlock :: proc(rw: ^RW_Mutex) {
atomic_rw_mutex_unlock(&rw.impl.mutex)
}
_rw_mutex_try_lock :: proc(rw: ^RW_Mutex) -> bool {
return atomic_rw_mutex_try_lock(&rw.impl.mutex)
}
_rw_mutex_shared_lock :: proc(rw: ^RW_Mutex) {
atomic_rw_mutex_shared_lock(&rw.impl.mutex)
}
_rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
atomic_rw_mutex_shared_unlock(&rw.impl.mutex)
}
_rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
return atomic_rw_mutex_try_shared_lock(&rw.impl.mutex)
}
}
|