aboutsummaryrefslogtreecommitdiff
path: root/core/sync/primitives_internal.odin
blob: de9aca99112ff780571c2913634b21db866ce8bb (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
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)
	}

}