mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-06 13:07:59 +00:00
96 lines
1.9 KiB
Odin
96 lines
1.9 KiB
Odin
import {
|
|
win32 "sys/windows.odin" when ODIN_OS == "windows";
|
|
"atomic.odin";
|
|
}
|
|
|
|
type {
|
|
Semaphore struct {
|
|
handle win32.HANDLE;
|
|
}
|
|
|
|
Mutex struct {
|
|
semaphore Semaphore;
|
|
counter i32;
|
|
owner i32;
|
|
recursion i32;
|
|
}
|
|
}
|
|
|
|
proc current_thread_id() -> i32 {
|
|
return win32.GetCurrentThreadId() as i32;
|
|
}
|
|
|
|
proc semaphore_init(s ^Semaphore) {
|
|
s.handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil);
|
|
}
|
|
|
|
proc semaphore_destroy(s ^Semaphore) {
|
|
win32.CloseHandle(s.handle);
|
|
}
|
|
|
|
proc semaphore_post(s ^Semaphore, count int) {
|
|
win32.ReleaseSemaphore(s.handle, count as i32, nil);
|
|
}
|
|
|
|
proc semaphore_release(s ^Semaphore) #inline { semaphore_post(s, 1); }
|
|
|
|
proc semaphore_wait(s ^Semaphore) {
|
|
win32.WaitForSingleObject(s.handle, win32.INFINITE);
|
|
}
|
|
|
|
|
|
proc mutex_init(m ^Mutex) {
|
|
atomic.store32(^m.counter, 0);
|
|
atomic.store32(^m.owner, current_thread_id());
|
|
semaphore_init(^m.semaphore);
|
|
m.recursion = 0;
|
|
}
|
|
proc mutex_destroy(m ^Mutex) {
|
|
semaphore_destroy(^m.semaphore);
|
|
}
|
|
proc mutex_lock(m ^Mutex) {
|
|
var thread_id = current_thread_id();
|
|
if atomic.fetch_add32(^m.counter, 1) > 0 {
|
|
if thread_id != atomic.load32(^m.owner) {
|
|
semaphore_wait(^m.semaphore);
|
|
}
|
|
}
|
|
atomic.store32(^m.owner, thread_id);
|
|
m.recursion++;
|
|
}
|
|
proc mutex_try_lock(m ^Mutex) -> bool {
|
|
var thread_id = current_thread_id();
|
|
if atomic.load32(^m.owner) == thread_id {
|
|
atomic.fetch_add32(^m.counter, 1);
|
|
} else {
|
|
var expected i32 = 0;
|
|
if atomic.load32(^m.counter) != 0 {
|
|
return false;
|
|
}
|
|
if atomic.compare_exchange32(^m.counter, expected, 1) == 0 {
|
|
return false;
|
|
}
|
|
atomic.store32(^m.owner, thread_id);
|
|
}
|
|
m.recursion++;
|
|
return true;
|
|
}
|
|
proc mutex_unlock(m ^Mutex) {
|
|
var recursion i32;
|
|
var thread_id = current_thread_id();
|
|
assert(thread_id == atomic.load32(^m.owner));
|
|
|
|
m.recursion--;
|
|
recursion = m.recursion;
|
|
if recursion == 0 {
|
|
atomic.store32(^m.owner, thread_id);
|
|
}
|
|
|
|
if atomic.fetch_add32(^m.counter, -1) > 1 {
|
|
if recursion == 0 {
|
|
semaphore_release(^m.semaphore);
|
|
}
|
|
}
|
|
}
|
|
|