gingerBill 4 years ago
parent
commit
98ad912509
1 changed files with 62 additions and 1 deletions
  1. 62 1
      core/sync/sync.odin

+ 62 - 1
core/sync/sync.odin

@@ -1,6 +1,7 @@
 package sync
 
-import "core:intrinsics"
+import "intrinsics"
+import "core:runtime"
 
 cpu_relax :: inline proc "contextless" () {
 	intrinsics.cpu_relax();
@@ -61,3 +62,63 @@ benaphore_unlock :: proc(b: ^Benaphore) {
 		semaphore_post(&b.sema);
 	}
 }
+
+Recursive_Benaphore :: struct {
+	counter:   int,
+	owner:     int,
+	recursion: int,
+	sema: Semaphore,
+}
+
+recursive_benaphore_init :: proc(b: ^Recursive_Benaphore) {
+	intrinsics.atomic_store(&b.counter, 0);
+	semaphore_init(&b.sema);
+}
+
+recursive_benaphore_destroy :: proc(b: ^Recursive_Benaphore) {
+	semaphore_destroy(&b.sema);
+}
+
+recursive_benaphore_lock :: proc(b: ^Recursive_Benaphore) {
+	tid := runtime.current_thread_id();
+	if intrinsics.atomic_add_acq(&b.counter, 1) > 1 {
+		if tid != b.owner {
+			semaphore_wait_for(&b.sema);
+		}
+	}
+	// inside the lock
+	b.owner = tid;
+	b.recursion += 1;
+}
+
+recursive_benaphore_try_lock :: proc(b: ^Recursive_Benaphore) -> bool {
+	tid := runtime.current_thread_id();
+	if b.owner == tid {
+		intrinsics.atomic_add_acq(&b.counter, 1);
+	} else {
+		v, _ := intrinsics.atomic_cxchg_acq(&b.counter, 1, 0);
+		if v != 0 {
+			return false;
+		}
+		// inside the lock
+		b.owner = tid;
+	}
+	b.recursion += 1;
+	return true;
+}
+
+recursive_benaphore_unlock :: proc(b: ^Recursive_Benaphore) {
+	tid := runtime.current_thread_id();
+	assert(tid == b.owner);
+	b.recursion -= 1;
+	recursion := b.recursion;
+	if recursion == 0 {
+		b.owner = 0;
+	}
+	if intrinsics.atomic_sub_rel(&b.counter, 1) > 0 {
+		if recursion == 0 {
+			semaphore_post(&b.sema);
+		}
+	}
+	// outside the lock
+}