diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2007-05-04 12:58:42 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2007-05-04 12:58:42 +0000 |
commit | 202dbd708c78383337cb4e23012236006ec5b3d4 (patch) | |
tree | 5dc18dd001985fe3a0f32b1b5ced9bc1febfa373 /sys | |
parent | 44edd472c011431a2138ccc1a14a6a7b7d8d53e5 (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)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/i386/i386/lock_machdep.c | 54 | ||||
-rw-r--r-- | sys/arch/i386/include/lock.h | 7 |
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_ */ |