aboutsummaryrefslogtreecommitdiff
path: root/core/sync_windows.odin
blob: 2035fc475af7cfc4050014cdc905d7a3e165a035 (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
import (
	win32 "sys/windows.odin" when ODIN_OS == "windows";
	"atomics.odin";
)

Semaphore :: struct {
	_handle: win32.Handle;
}

/*
Mutex :: struct {
	_semaphore: Semaphore;
	_counter:   i32;
	_owner:     i32;
	_recursion: i32;
}
*/

Mutex :: struct {
	_critical_section: win32.CriticalSection;
}

current_thread_id :: proc() -> i32 {
	return i32(win32.get_current_thread_id());
}

semaphore_init :: proc(s: ^Semaphore) {
	s._handle = win32.create_semaphore_a(nil, 0, 1<<31-1, nil);
}

semaphore_destroy :: proc(s: ^Semaphore) {
	win32.close_handle(s._handle);
}

semaphore_post :: proc(s: ^Semaphore, count: int) {
	win32.release_semaphore(s._handle, i32(count), nil);
}

semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); }

semaphore_wait :: proc(s: ^Semaphore) {
	win32.wait_for_single_object(s._handle, win32.INFINITE);
}


mutex_init :: proc(m: ^Mutex, spin_count := 0) {
	win32.initialize_critical_section_and_spin_count(&m._critical_section, u32(spin_count));
}

mutex_destroy :: proc(m: ^Mutex) {
	win32.delete_critical_section(&m._critical_section);
}

mutex_lock :: proc(m: ^Mutex) {
	win32.enter_critical_section(&m._critical_section);
}

mutex_try_lock :: proc(m: ^Mutex) -> bool {
	return win32.try_enter_critical_section(&m._critical_section) != 0;
}

mutex_unlock :: proc(m: ^Mutex) {
	win32.leave_critical_section(&m._critical_section);
}



/*
mutex_init :: proc(m: ^Mutex) {
	atomics.store(&m._counter, 0);
	atomics.store(&m._owner, current_thread_id());
	semaphore_init(&m._semaphore);
	m._recursion = 0;
}
mutex_destroy :: proc(m: ^Mutex) {
	semaphore_destroy(&m._semaphore);
}
mutex_lock :: proc(m: ^Mutex) {
	thread_id := current_thread_id();
	if atomics.fetch_add(&m._counter, 1) > 0 {
		if thread_id != atomics.load(&m._owner) {
			semaphore_wait(&m._semaphore);
		}
	}
	atomics.store(&m._owner, thread_id);
	m._recursion++;
}
mutex_try_lock :: proc(m: ^Mutex) -> bool {
	thread_id := current_thread_id();
	if atomics.load(&m._owner) == thread_id {
		atomics.fetch_add(&m._counter, 1);
	} else {
		expected: i32 = 0;
		if atomics.load(&m._counter) != 0 {
			return false;
		}
		if atomics.compare_exchange(&m._counter, expected, 1) == 0 {
			return false;
		}
		atomics.store(&m._owner, thread_id);
	}
	m._recursion++;
	return true;
}
mutex_unlock :: proc(m: ^Mutex) {
	recursion: i32;
	thread_id := current_thread_id();
	assert(thread_id == atomics.load(&m._owner));

	m._recursion--;
	recursion = m._recursion;
	if recursion == 0 {
		atomics.store(&m._owner, thread_id);
	}

	if atomics.fetch_add(&m._counter, -1) > 1 {
		if recursion == 0 {
			semaphore_release(&m._semaphore);
		}
	}
}
*/