use package core.intrinsics.atomics
+// `lock` has two states: 0, and 1.
+// 0 means unlocked
+// 1 means locked
+//
+// To lock it:
+// Try to store 1 if the value was already 0
+// Otherwise, if it was already 1, wait until it goes to 0.
+//
+// To unlock it:
+// Atomically set it to 0.
+// Notify at most 1 other thread about this change.
+
Mutex :: struct {
lock : i32;
// owner : Thread_Id;
mutex_lock :: (m: ^Mutex) {
while __atomic_cmpxchg(^m.lock, 0, 1) == 1 {
- __atomic_wait(^m.lock, 0);
+ __atomic_wait(^m.lock, 1);
}
}
--- /dev/null
+package core.sync
+
+use package core.intrinsics.atomics
+
+Semaphore :: struct {
+ mutex : Mutex;
+ counter : i32;
+}
+
+semaphore_init :: (s: ^Semaphore, value: i32) {
+ s.counter = value;
+
+ mutex_init(^s.mutex);
+}
+
+semaphore_post :: (s: ^Semaphore) {
+ scoped_mutex(^s.mutex);
+ s.counter += 1;
+ __atomic_notify(^s.counter, maximum = 1);
+}
+
+semaphore_wait :: (s: ^Semaphore) {
+ while true {
+ mutex_lock(^s.mutex);
+ if s.counter > 0 {
+ s.counter -= 1;
+
+ mutex_unlock(^s.mutex);
+ return;
+
+ } else {
+ mutex_unlock(^s.mutex);
+
+ __atomic_wait(^s.counter, 0);
+ }
+ }
+}
\ No newline at end of file