aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/atomic
diff options
context:
space:
mode:
authorChristian Cunningham <cc@localhost>2021-12-19 14:50:45 -0800
committerChristian Cunningham <cc@localhost>2021-12-19 14:50:45 -0800
commit43db8c57ebe496bea03d66e2ddd0aa6bc298738c (patch)
tree6a4a8bf25319d1ceb834ee2dd567089fd70c87bd /src/cpu/atomic
parent456580be4408869962cf28bb39d909fb5fcb6176 (diff)
Added atomic swap
Diffstat (limited to 'src/cpu/atomic')
-rw-r--r--src/cpu/atomic/swap.a.h32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/cpu/atomic/swap.a.h b/src/cpu/atomic/swap.a.h
new file mode 100644
index 0000000..63dd50b
--- /dev/null
+++ b/src/cpu/atomic/swap.a.h
@@ -0,0 +1,32 @@
+#ifndef CPU_ATOMIC_SWAP_A_H
+#define CPU_ATOMIC_SWAP_A_H
+
+/// https://stackoverflow.com/questions/16329123/use-of-strexeq-instead-of-strex-for-spinlock-implementation-in-arm
+
+static inline void atm_lock(unsigned long pid, unsigned long* addr) {
+ unsigned long tmp, current_lock_value;
+ asm volatile(
+"1: ldrex %0, [%3]\n"
+" cmp %0, #0\n"
+" wfene\n"
+" strexeq %1, %2, [%3]\n"
+" teq %1, #0\n"
+" bne 1b\n"
+" dmb"
+ : "=&r" (current_lock_value), "=&r" (tmp)
+ : "r" (pid), "r" (addr)
+ : "cc");
+}
+
+static inline void atm_unlock(unsigned long* addr) {
+ unsigned long cleared = 0;
+ asm volatile(
+" dmb\n"
+" str %0, [%1]\n"
+" dsb\n"
+" sev"
+ :: "r" (cleared), "r" (addr)
+ : "cc");
+}
+
+#endif