summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2007-05-04 12:58:42 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2007-05-04 12:58:42 +0000
commit202dbd708c78383337cb4e23012236006ec5b3d4 (patch)
tree5dc18dd001985fe3a0f32b1b5ced9bc1febfa373
parent44edd472c011431a2138ccc1a14a6a7b7d8d53e5 (diff)
Implement rw_cas for i386.
It uses a function pointer to choose between the 386 and 486 versions. The 386 version is not MP safe, but we're not expecting MP support for 386 cpus. miod@ ok (and prodding)
-rw-r--r--sys/arch/i386/i386/lock_machdep.c54
-rw-r--r--sys/arch/i386/include/lock.h7
2 files changed, 59 insertions, 2 deletions
diff --git a/sys/arch/i386/i386/lock_machdep.c b/sys/arch/i386/i386/lock_machdep.c
index 99e0bded4ac..3c00a13309e 100644
--- a/sys/arch/i386/i386/lock_machdep.c
+++ b/sys/arch/i386/i386/lock_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lock_machdep.c,v 1.3 2006/09/19 11:06:33 jsg Exp $ */
+/* $OpenBSD: lock_machdep.c,v 1.4 2007/05/04 12:58:41 art Exp $ */
/* $NetBSD: lock_machdep.c,v 1.1.2.3 2000/05/03 14:40:30 sommerfeld Exp $ */
/*-
@@ -50,6 +50,7 @@
#include <machine/atomic.h>
#include <machine/lock.h>
+#include <machine/cpufunc.h>
#include <ddb/db_output.h>
@@ -106,3 +107,54 @@ __cpu_simple_unlock(__cpu_simple_lock_t *lockp)
}
#endif
+
+int rw_cas_386(volatile unsigned long *, unsigned long, unsigned long);
+int rw_cas_486(volatile unsigned long *, unsigned long, unsigned long);
+int rw_cas_choose(volatile unsigned long *, unsigned long, unsigned long);
+
+int (*rw_cas_p)(volatile unsigned long *, unsigned long, unsigned long)
+ = rw_cas_choose;
+
+int
+rw_cas_choose(volatile unsigned long *p, unsigned long o, unsigned long n)
+{
+ if (cpu_class == CPUCLASS_386)
+ rw_cas_p = rw_cas_386;
+ else
+ rw_cas_p = rw_cas_486;
+
+ return (*rw_cas_p)(p, o, n);
+}
+
+int
+rw_cas_386(volatile unsigned long *p, unsigned long o, unsigned long n)
+{
+ u_int ef = read_eflags();
+
+ disable_intr();
+ if (*p != o) {
+ write_eflags(ef);
+ return (1);
+ }
+ *p = n;
+ write_eflags(ef);
+
+ return (0);
+}
+
+#ifdef MULTIPROCESSOR
+#define MPLOCK "lock "
+#else
+#define MPLOCK
+#endif
+
+int
+rw_cas_486(volatile unsigned long *p, unsigned long o, unsigned long n)
+{
+ int res;
+
+ __asm volatile(MPLOCK " cmpxchgl %2, %1" : "=a" (res), "=m" (*p)
+ : "r" (n), "a" (o), "m" (*p) : "memory");
+
+ return (res != o);
+}
diff --git a/sys/arch/i386/include/lock.h b/sys/arch/i386/include/lock.h
index fe0578a3139..172ed35fdf3 100644
--- a/sys/arch/i386/include/lock.h
+++ b/sys/arch/i386/include/lock.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lock.h,v 1.3 2006/03/13 18:42:16 mickey Exp $ */
+/* $OpenBSD: lock.h,v 1.4 2007/05/04 12:58:41 art Exp $ */
/* $NetBSD: lock.h,v 1.1.2.2 2000/05/03 14:40:55 sommerfeld Exp $ */
/*-
@@ -117,4 +117,9 @@ __cpu_simple_unlock(__cpu_simple_lock_t *lockp)
#endif /* !LOCKDEBUG */
+#ifdef _KERNEL
+extern int (*rw_cas_p)(volatile unsigned long *, unsigned long, unsigned long);
+#define rw_cas (*rw_cas_p)
+#endif
+
#endif /* _I386_LOCK_H_ */