summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2007-12-02 21:21:31 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2007-12-02 21:21:31 +0000
commit1650e61219b0f085938ffd3529b18f122e371efd (patch)
tree872abb896c319c905210f0d4c4a335069a857a7f /sys/arch
parent9ddcf1d8e7bdf80e4736afe986c5f0d16cb79111 (diff)
Provide a specific rw_cas() function for MP kernels, simulating a really
atomic compare-and-swap operation.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/m88k/include/lock.h7
-rw-r--r--sys/arch/m88k/m88k/m88k_machdep.c33
2 files changed, 38 insertions, 2 deletions
diff --git a/sys/arch/m88k/include/lock.h b/sys/arch/m88k/include/lock.h
index 13bfc2d0960..06eebcfaf2d 100644
--- a/sys/arch/m88k/include/lock.h
+++ b/sys/arch/m88k/include/lock.h
@@ -1,6 +1,6 @@
#ifndef _M88K_LOCK_H_
#define _M88K_LOCK_H_
-/* $OpenBSD: lock.h,v 1.5 2007/10/27 20:36:17 miod Exp $ */
+/* $OpenBSD: lock.h,v 1.6 2007/12/02 21:21:29 miod Exp $ */
/*
* Copyright (c) 2005, Miodrag Vallat.
@@ -81,4 +81,9 @@ __cpu_simple_unlock(__cpu_simple_lock_t *l)
*l = __SIMPLELOCK_UNLOCKED;
}
+#if defined(_KERNEL) && defined(MULTIPROCESSOR)
+int rw_cas_m88k(volatile unsigned long *, unsigned long, unsigned long);
+#define rw_cas rw_cas_m88k
+#endif
+
#endif /* _M88K_LOCK_H_ */
diff --git a/sys/arch/m88k/m88k/m88k_machdep.c b/sys/arch/m88k/m88k/m88k_machdep.c
index cf81fd6ad1e..1044d2e7f2a 100644
--- a/sys/arch/m88k/m88k/m88k_machdep.c
+++ b/sys/arch/m88k/m88k/m88k_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m88k_machdep.c,v 1.34 2007/11/22 05:42:50 miod Exp $ */
+/* $OpenBSD: m88k_machdep.c,v 1.35 2007/12/02 21:21:30 miod Exp $ */
/*
* Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
* Copyright (c) 1996 Nivas Madhur
@@ -502,4 +502,35 @@ cpu_emergency_disable()
/* NOTREACHED */
}
+/*
+ * Emulate a compare-and-swap instruction for rwlocks, by using a
+ * __cpu_simple_lock as a critical section.
+ *
+ * Since we are only competing against other processors for rwlocks,
+ * it is not necessary in this case to disable interrupts to prevent
+ * reentrancy on the same processor.
+ *
+ * Updates need to be done with xmem to ensure they are atomic.
+ */
+
+__cpu_simple_lock_t rw_cas_spinlock = __SIMPLELOCK_UNLOCKED;
+
+int
+rw_cas_m88k(volatile unsigned long *p, unsigned long o, unsigned long n)
+{
+ int rc = 0;
+
+ __cpu_simple_lock(&rw_cas_spinlock);
+
+ if (*p != o)
+ rc = 1;
+ /* atomic *p = n; */
+ __asm__ __volatile__
+ ("xmem %0, %2, r0" : "+r"(n), "+m"(*p) : "r"(p));
+
+ __cpu_simple_unlock(&rw_cas_spinlock);
+
+ return (rc);
+}
+
#endif /* MULTIPROCESSOR */