aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pk/atomic.h18
1 files changed, 8 insertions, 10 deletions
diff --git a/pk/atomic.h b/pk/atomic.h
index 37f43e5..e4610de 100644
--- a/pk/atomic.h
+++ b/pk/atomic.h
@@ -13,27 +13,25 @@
typedef struct { int lock; } spinlock_t;
#define SPINLOCK_INIT {0}
-#define mb() __sync_synchronize()
+#define mb() asm volatile ("fence" ::: "memory")
#define atomic_set(ptr, val) (*(volatile typeof(*(ptr)) *)(ptr) = val)
#define atomic_read(ptr) (*(volatile typeof(*(ptr)) *)(ptr))
#ifdef __riscv_atomic
# define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
+# define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
# define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
# define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)
#else
-# define atomic_add(ptr, inc) ({ \
+# define atomic_binop(ptr, inc, op) ({ \
long flags = disable_irqsave(); \
- typeof(*(ptr)) res = *(volatile typeof(*(ptr)) *)(ptr); \
- *(volatile typeof(ptr))(ptr) = res + (inc); \
- enable_irqrestore(flags); \
- res; })
-# define atomic_swap(ptr, swp) ({ \
- long flags = disable_irqsave(); \
- typeof(*(ptr)) res = *(volatile typeof(*(ptr)) *)(ptr); \
- *(volatile typeof(ptr))(ptr) = (swp); \
+ typeof(*(ptr)) res = atomic_read(ptr); \
+ atomic_set(ptr, op); \
enable_irqrestore(flags); \
res; })
+# define atomic_add(ptr, inc) atomic_binop(ptr, inc, res + (inc))
+# define atomic_or(ptr, inc) atomic_binop(ptr, inc, res | (inc))
+# define atomic_swap(ptr, inc) atomic_binop(ptr, inc, (inc))
# define atomic_cas(ptr, cmp, swp) ({ \
long flags = disable_irqsave(); \
typeof(*(ptr)) res = *(volatile typeof(*(ptr)) *)(ptr); \