From af00e218a8e9c7c38adad7d1646445c06afffba4 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 28 Sep 2021 00:14:14 +0200 Subject: [PATCH] riscv: implement 32-bit atomic operations This is necessary to support the ESP32-C3, which lacks the A (atomic) extension and thus requires these 32-bit atomic operations. With this commit, flashing ./testdata/atomic.go to the ESP32-C3 works correctly and produces the expected output on the serial console. --- src/runtime/arch_tinygoriscv.go | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/runtime/arch_tinygoriscv.go b/src/runtime/arch_tinygoriscv.go index 3dcbcec2..d7b0fee2 100644 --- a/src/runtime/arch_tinygoriscv.go +++ b/src/runtime/arch_tinygoriscv.go @@ -18,6 +18,53 @@ func getCurrentStackPointer() uintptr { // supported RISC-V chips have a single hart, we can simply disable interrupts // to get the same behavior. +//export __atomic_load_4 +func __atomic_load_4(ptr *uint32, ordering int32) uint32 { + mask := riscv.DisableInterrupts() + value := *ptr + riscv.EnableInterrupts(mask) + return value +} + +//export __atomic_store_4 +func __atomic_store_4(ptr *uint32, value uint32, ordering int32) { + mask := riscv.DisableInterrupts() + *ptr = value + riscv.EnableInterrupts(mask) +} + +//export __atomic_exchange_4 +func __atomic_exchange_4(ptr *uint32, value uint32, ordering int32) uint32 { + mask := riscv.DisableInterrupts() + oldValue := *ptr + *ptr = value + riscv.EnableInterrupts(mask) + return oldValue +} + +//export __atomic_compare_exchange_4 +func __atomic_compare_exchange_4(ptr, expected *uint32, desired uint32, success_ordering, failure_ordering int32) bool { + mask := riscv.DisableInterrupts() + oldValue := *ptr + success := oldValue == *expected + if success { + *ptr = desired + } else { + *expected = oldValue + } + riscv.EnableInterrupts(mask) + return success +} + +//export __atomic_fetch_add_4 +func __atomic_fetch_add_4(ptr *uint32, value uint32, ordering int32) uint32 { + mask := riscv.DisableInterrupts() + oldValue := *ptr + *ptr = oldValue + value + riscv.EnableInterrupts(mask) + return oldValue +} + //export __atomic_load_8 func __atomic_load_8(ptr *uint64, ordering int32) uint64 { mask := riscv.DisableInterrupts()