diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-05-01 15:30:16 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-05-01 15:30:16 +0100 |
| commit | 19bde275a3ea5f406b41d9b4895f8ba381684f25 (patch) | |
| tree | 6b21b36e8e393ba86f5cfd6744bf09034d2302db /core/atomics.odin | |
| parent | 634ee450f4546374e979ce3dab3cb73136a5ae43 (diff) | |
Add files in corev0.2.1
Diffstat (limited to 'core/atomics.odin')
| -rw-r--r-- | core/atomics.odin | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/core/atomics.odin b/core/atomics.odin new file mode 100644 index 000000000..ec7900f0d --- /dev/null +++ b/core/atomics.odin @@ -0,0 +1,100 @@ +// TODO(bill): Use assembly instead here to implement atomics +// Inline vs external file? + +#import win32 "sys/windows.odin" when ODIN_OS == "windows"; +_ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version + + +yield_thread :: proc() { win32.mm_pause(); } +mfence :: proc() { win32.ReadWriteBarrier(); } +sfence :: proc() { win32.WriteBarrier(); } +lfence :: proc() { win32.ReadBarrier(); } + + +load :: proc(a: ^i32) -> i32 { + return a^; +} +store :: proc(a: ^i32, value: i32) { + a^ = value; +} +compare_exchange :: proc(a: ^i32, expected, desired: i32) -> i32 { + return win32.InterlockedCompareExchange(a, desired, expected); +} +exchanged :: proc(a: ^i32, desired: i32) -> i32 { + return win32.InterlockedExchange(a, desired); +} +fetch_add :: proc(a: ^i32, operand: i32) -> i32 { + return win32.InterlockedExchangeAdd(a, operand); + +} +fetch_and :: proc(a: ^i32, operand: i32) -> i32 { + return win32.InterlockedAnd(a, operand); +} +fetch_or :: proc(a: ^i32, operand: i32) -> i32 { + return win32.InterlockedOr(a, operand); +} +spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default + old_value := compare_exchange(a, 1, 0); + counter := 0; + for old_value != 0 && (time_out < 0 || counter < time_out) { + counter++; + yield_thread(); + old_value = compare_exchange(a, 1, 0); + mfence(); + } + return old_value == 0; +} +spin_unlock :: proc(a: ^i32) { + store(a, 0); + mfence(); +} +try_acquire_lock :: proc(a: ^i32) -> bool { + yield_thread(); + old_value := compare_exchange(a, 1, 0); + mfence(); + return old_value == 0; +} + + +load :: proc(a: ^i64) -> i64 { + return a^; +} +store :: proc(a: ^i64, value: i64) { + a^ = value; +} +compare_exchange :: proc(a: ^i64, expected, desired: i64) -> i64 { + return win32.InterlockedCompareExchange64(a, desired, expected); +} +exchanged :: proc(a: ^i64, desired: i64) -> i64 { + return win32.InterlockedExchange64(a, desired); +} +fetch_add :: proc(a: ^i64, operand: i64) -> i64 { + return win32.InterlockedExchangeAdd64(a, operand); +} +fetch_and :: proc(a: ^i64, operand: i64) -> i64 { + return win32.InterlockedAnd64(a, operand); +} +fetch_or :: proc(a: ^i64, operand: i64) -> i64 { + return win32.InterlockedOr64(a, operand); +} +spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default + old_value := compare_exchange(a, 1, 0); + counter := 0; + for old_value != 0 && (time_out < 0 || counter < time_out) { + counter++; + yield_thread(); + old_value = compare_exchange(a, 1, 0); + mfence(); + } + return old_value == 0; +} +spin_unlock :: proc(a: ^i64) { + store(a, 0); + mfence(); +} +try_acquire_lock :: proc(a: ^i64) -> bool { + yield_thread(); + old_value := compare_exchange(a, 1, 0); + mfence(); + return old_value == 0; +} |