To prevent GCC clobbering one of the inputs and
to make this cross arch compatible, we use C11 atomics.
The packed struct containing a lock is unpacked to fix alignment.

---
 i386/i386/irq.c  |  2 +-
 i386/i386/lock.h | 26 +++++++++++---------------
 kern/lock.h      |  4 ++--
 3 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/i386/i386/irq.c b/i386/i386/irq.c
index ea10e179..8b89b70d 100644
--- a/i386/i386/irq.c
+++ b/i386/i386/irq.c
@@ -39,7 +39,7 @@ struct nested_irq {
   simple_lock_irq_data_t irq_lock; /* Protects ndisabled */
   int32_t ndisabled;
   uint32_t unused[14];
-} __attribute__((packed)) nested_irqs[NINTR];
+} nested_irqs[NINTR];
 
 void
 init_irqs (void)
diff --git a/i386/i386/lock.h b/i386/i386/lock.h
index 0384536a..c086e9b5 100644
--- a/i386/i386/lock.h
+++ b/i386/i386/lock.h
@@ -33,11 +33,11 @@
        {.lock_data = 0}
 
 #if NCPUS > 1
+#include <stdatomic.h>
 #include <i386/smp.h>
 
 /*
- *     All of the locking routines are built from calls on
- *     a locked-exchange operation.  Values of the lock are
+ *     Values of the lock are
  *     0 for unlocked, 1 for locked.
  */
 
@@ -47,31 +47,27 @@
  *     The code here depends on the GNU C compiler.
  */
 
-#define        _simple_lock_xchg_(lock, new_val) \
-({     natural_t _old_val_; \
-       asm volatile("xchg %0, %2" \
-                   : "=r" (_old_val_) \
-                   : "0" ((natural_t)(new_val)), "m" (*(lock)) : "memory" \
-                   ); \
-       _old_val_; \
-    })
-
 #define        simple_lock_init(l) \
        ((l)->lock_data = 0)
 
 #define        _simple_lock(l) \
     ({ \
-       while(_simple_lock_xchg_(l, 1)) \
-           while (*(volatile natural_t *)&(l)->lock_data) \
+       for (;;) { \
+           if (!atomic_exchange_explicit(&(l)->lock_data, 1, 
__ATOMIC_ACQUIRE)) \
+               break;  \
+           while (atomic_load_explicit(&(l)->lock_data, __ATOMIC_RELAXED)) \
                cpu_pause(); \
+       } \
        0; \
     })
 
 #define        _simple_unlock(l) \
-       (_simple_lock_xchg_(l, 0))
+       atomic_store_explicit(&(l)->lock_data, 0, __ATOMIC_RELEASE)
 
 #define        _simple_lock_try(l) \
-       (!_simple_lock_xchg_(l, 1))
+       (!atomic_load_explicit(&(l)->lock_data, __ATOMIC_RELAXED) && \
+        !atomic_exchange_explicit(&(l)->lock_data, 1, __ATOMIC_ACQUIRE))
+
 
 /*
  *     General bit-lock routines.
diff --git a/kern/lock.h b/kern/lock.h
index 74f2e26e..38111ed0 100644
--- a/kern/lock.h
+++ b/kern/lock.h
@@ -58,6 +58,7 @@
  * MACH_LDEBUG is set.
  */
 
+#include <stdatomic.h>
 #include <machine/lock.h>/*XXX*/
 #if NCPUS > 1
 #if MACH_LOCK_MON == 0
@@ -76,9 +77,8 @@
 /*
  *     A simple spin lock.
  */
-
 struct slock {
-       volatile natural_t lock_data;   /* in general 1 bit is sufficient */
+       atomic_uint lock_data;  /* in general 1 bit is sufficient */
        struct {} is_a_simple_lock;
 };
 
-- 
2.45.2



Reply via email to