A machine-independent spinlock implementation. It has the advantages of
authorJeffrey Hsu <hsu@dragonflybsd.org>
Sun, 28 Aug 2005 15:27:05 +0000 (15:27 +0000)
committerJeffrey Hsu <hsu@dragonflybsd.org>
Sun, 28 Aug 2005 15:27:05 +0000 (15:27 +0000)
  1.  being written in C except for the most low-level atomic swap primitive,
        which is universally supported on current processor architectures
  2.  having a very small inlined memory footprint for spin_lock(),
        with the slow-path defered to a subroutine call
  3.  only requiring a bus-locked operation for lock acquisition,
         and not requiring a bus-locked operation for lock release
  4.  doing a non-bus-locked check first in the spin loop to
        reduce bus contention
  5.  doing exponential backoff in the uncommon contested case, which
        Sun has found to reduce bus contention by a factor of 5 or more

Reviewed by: Matt Dillon

16 files changed:
sys/amd64/include/lock.h
sys/conf/files
sys/cpu/i386/include/atomic.h
sys/cpu/i386/include/cpufunc.h
sys/i386/i386/machdep.c
sys/i386/i386/mp_machdep.c
sys/i386/i386/spinlock.s
sys/i386/include/atomic.h
sys/i386/include/cpufunc.h
sys/i386/include/lock.h
sys/kern/kern_spinlock.c [new file with mode: 0644]
sys/platform/pc32/i386/machdep.c
sys/platform/pc32/i386/mp_machdep.c
sys/platform/pc32/i386/spinlock.s
sys/platform/pc32/include/lock.h
sys/sys/spinlock.h [new file with mode: 0644]

index 4379cb5..fd6c2b5 100644 (file)
@@ -22,7 +22,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/lock.h,v 1.11.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/amd64/include/Attic/lock.h,v 1.2 2004/06/28 02:57:11 drhodus Exp $
+ * $DragonFly: src/sys/amd64/include/Attic/lock.h,v 1.3 2005/08/28 15:27:05 hsu Exp $
  */
 
 #ifndef _MACHINE_LOCK_H_
  * Spinlock functions (UP and SMP).  Under UP a spinlock still serves
  * to disable/restore interrupts even if it doesn't spin.
  */
-struct spinlock {
+struct spinlock_deprecated {
        volatile int    opaque;
 };
 
-typedef struct spinlock *spinlock_t;
+typedef struct spinlock_deprecated *spinlock_t;
 
 void   mpintr_lock(void);      /* disables int / spinlock combo */
 void   mpintr_unlock(void);
@@ -146,15 +146,10 @@ void      clock_unlock(void);
 void   cons_lock(void);        /* disables int / spinlock combo */
 void   cons_unlock(void);
 
-extern struct spinlock smp_rv_spinlock;
+extern struct spinlock_deprecated smp_rv_spinlock;
 
-void   spin_lock(spinlock_t lock);
-void   spin_lock_np(spinlock_t lock);
-void   spin_unlock(spinlock_t lock);
-void   spin_unlock_np(spinlock_t lock);
-#if 0
-void   spin_lock_init(spinlock_t lock);
-#endif
+void   spin_lock_deprecated(spinlock_t);
+void   spin_unlock_deprecated(spinlock_t);
 
 /*
  * Inline version of spinlock routines -- overrides assembly.  Only unlock
index 370a2ea..24eb4c2 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $
-# $DragonFly: src/sys/conf/files,v 1.103 2005/08/27 20:23:05 joerg Exp $
+# $DragonFly: src/sys/conf/files,v 1.104 2005/08/28 15:27:05 hsu Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -523,6 +523,7 @@ kern/lwkt_msgport.c standard
 kern/lwkt_rwlock.c     standard
 kern/lwkt_serialize.c  standard
 kern/lwkt_caps.c       standard
+kern/kern_spinlock.c   standard
 kern/kern_synch.c      standard
 kern/kern_syscalls.c   standard
 kern/kern_sysctl.c     standard
index e386300..c7a8cfa 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/atomic.h,v 1.9.2.1 2000/07/07 00:38:47 obrien Exp $
- * $DragonFly: src/sys/cpu/i386/include/atomic.h,v 1.13 2005/05/26 09:10:08 dillon Exp $
+ * $DragonFly: src/sys/cpu/i386/include/atomic.h,v 1.14 2005/08/28 15:27:05 hsu Exp $
  */
 #ifndef _MACHINE_ATOMIC_H_
 #define _MACHINE_ATOMIC_H_
@@ -138,11 +138,20 @@ ATOMIC_ASM(subtract, long,  "subl %1,%0",  v)
 
 #if defined(KLD_MODULE)
 
+extern int atomic_swap_int(volatile int *addr, int value);
 extern int atomic_poll_acquire_int(volatile u_int *p);
 extern void atomic_poll_release_int(volatile u_int *p);
 
 #else
 
+static __inline int
+atomic_swap_int(volatile int *addr, int value)
+{
+       __asm __volatile("xchgl %0, %1" :
+           "=r" (value), "=m" (*addr) : "0" (value) : "memory");
+       return (value);
+}
+
 static __inline
 int
 atomic_poll_acquire_int(volatile u_int *p)
index b39a5d4..a27dd35 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.96.2.3 2002/04/28 22:50:54 dwmalone Exp $
- * $DragonFly: src/sys/cpu/i386/include/cpufunc.h,v 1.13 2005/06/03 23:57:31 dillon Exp $
+ * $DragonFly: src/sys/cpu/i386/include/cpufunc.h,v 1.14 2005/08/28 15:27:05 hsu Exp $
  */
 
 /*
@@ -179,7 +179,7 @@ cpu_lfence(void)
 }
 
 /*
- * cpu_lfence() ensures strong write ordering for writes issued prior
+ * cpu_sfence() ensures strong write ordering for writes issued prior
  * to the instruction verses writes issued afterwords.  Writes are
  * ordered on intel cpus so we do not actually have to do anything.
  */
@@ -369,6 +369,12 @@ cpu_invltlb(void)
 #endif
 }
 
+static __inline void
+cpu_nop(void)
+{
+       __asm __volatile("rep; nop");
+}
+
 #endif /* _KERNEL */
 
 static __inline u_short
index ae784c9..8965ce8 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
  * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $
- * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.76 2005/06/25 20:03:34 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.77 2005/08/28 15:27:05 hsu Exp $
  */
 
 #include "use_apm.h"
@@ -2726,31 +2726,31 @@ outb(u_int port, u_char data)
  */
 
 /* critical region around IO APIC, apic_imen */
-struct spinlock        imen_spinlock;
+struct spinlock_deprecated imen_spinlock;
 
 /* Make FAST_INTR() routines sequential */
-struct spinlock        fast_intr_spinlock;
+struct spinlock_deprecated fast_intr_spinlock;
 
 /* critical region for old style disable_intr/enable_intr */
-struct spinlock        mpintr_spinlock;
+struct spinlock_deprecated mpintr_spinlock;
 
 /* critical region around INTR() routines */
-struct spinlock        intr_spinlock;
+struct spinlock_deprecated intr_spinlock;
 
 /* lock region used by kernel profiling */
-struct spinlock        mcount_spinlock;
+struct spinlock_deprecated mcount_spinlock;
 
 /* locks com (tty) data/hardware accesses: a FASTINTR() */
-struct spinlock        com_spinlock;
+struct spinlock_deprecated com_spinlock;
 
 /* locks kernel printfs */
-struct spinlock        cons_spinlock;
+struct spinlock_deprecated cons_spinlock;
 
 /* lock regions around the clock hardware */
-struct spinlock        clock_spinlock;
+struct spinlock_deprecated clock_spinlock;
 
 /* lock around the MP rendezvous */
-struct spinlock smp_rv_spinlock;
+struct spinlock_deprecated smp_rv_spinlock;
 
 static void
 init_locks(void)
index f4812b4..8883372 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
- * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.36 2005/06/03 23:57:30 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.37 2005/08/28 15:27:05 hsu Exp $
  */
 
 #include "opt_cpu.h"
@@ -2503,7 +2503,7 @@ smp_rendezvous(void (* setup_func)(void *),
               void *arg)
 {
        /* obtain rendezvous lock.  This disables interrupts */
-       spin_lock(&smp_rv_spinlock);    /* XXX sleep here? NOWAIT flag? */
+       spin_lock_deprecated(&smp_rv_spinlock); /* XXX sleep here? NOWAIT flag? */
 
        /* set static function pointers */
        smp_rv_setup_func = setup_func;
@@ -2529,7 +2529,7 @@ smp_rendezvous(void (* setup_func)(void *),
        smp_rendezvous_action();
 
        /* release lock */
-       spin_unlock(&smp_rv_spinlock);
+       spin_unlock_deprecated(&smp_rv_spinlock);
 }
 
 void
index e8191ba..5cb6f11 100644 (file)
@@ -22,7 +22,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/simplelock.s,v 1.11.2.2 2003/02/04 20:55:28 jhb Exp $
- * $DragonFly: src/sys/i386/i386/Attic/spinlock.s,v 1.1 2003/07/06 21:23:48 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/spinlock.s,v 1.2 2005/08/28 15:27:05 hsu Exp $
  */
 
 #include <machine/asmacros.h>                  /* miscellaneous macros */
  *
  * NOTE: for UP the spinlock routines still disable/restore interrupts
  */
-ENTRY(spin_lock)
+ENTRY(spin_lock_deprecated)
        movl    4(%esp),%edx
        SPIN_LOCK((%edx))               /* note: %eax, %ecx tromped */
        ret
 
-ENTRY(spin_unlock)
+ENTRY(spin_unlock_deprecated)
        movl    4(%esp),%edx
        SPIN_UNLOCK((%edx))             /* note: %eax, %ecx tromped */
        ret
index 8f3f989..664ec83 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/atomic.h,v 1.9.2.1 2000/07/07 00:38:47 obrien Exp $
- * $DragonFly: src/sys/i386/include/Attic/atomic.h,v 1.13 2005/05/26 09:10:08 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/atomic.h,v 1.14 2005/08/28 15:27:05 hsu Exp $
  */
 #ifndef _MACHINE_ATOMIC_H_
 #define _MACHINE_ATOMIC_H_
@@ -138,11 +138,20 @@ ATOMIC_ASM(subtract, long,  "subl %1,%0",  v)
 
 #if defined(KLD_MODULE)
 
+extern int atomic_swap_int(volatile int *addr, int value);
 extern int atomic_poll_acquire_int(volatile u_int *p);
 extern void atomic_poll_release_int(volatile u_int *p);
 
 #else
 
+static __inline int
+atomic_swap_int(volatile int *addr, int value)
+{
+       __asm __volatile("xchgl %0, %1" :
+           "=r" (value), "=m" (*addr) : "0" (value) : "memory");
+       return (value);
+}
+
 static __inline
 int
 atomic_poll_acquire_int(volatile u_int *p)
index 292f121..ba06dd8 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.96.2.3 2002/04/28 22:50:54 dwmalone Exp $
- * $DragonFly: src/sys/i386/include/Attic/cpufunc.h,v 1.13 2005/06/03 23:57:31 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/cpufunc.h,v 1.14 2005/08/28 15:27:05 hsu Exp $
  */
 
 /*
@@ -179,7 +179,7 @@ cpu_lfence(void)
 }
 
 /*
- * cpu_lfence() ensures strong write ordering for writes issued prior
+ * cpu_sfence() ensures strong write ordering for writes issued prior
  * to the instruction verses writes issued afterwords.  Writes are
  * ordered on intel cpus so we do not actually have to do anything.
  */
@@ -369,6 +369,12 @@ cpu_invltlb(void)
 #endif
 }
 
+static __inline void
+cpu_nop(void)
+{
+       __asm __volatile("rep; nop");
+}
+
 #endif /* _KERNEL */
 
 static __inline u_short
index 450b056..b8a2f3a 100644 (file)
@@ -32,7 +32,7 @@
  * SUCH DAMAGE.
  * 
  * $FreeBSD: src/sys/i386/include/lock.h,v 1.11.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/i386/include/Attic/lock.h,v 1.11 2005/07/19 19:08:04 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/lock.h,v 1.12 2005/08/28 15:27:05 hsu Exp $
  */
 
 #ifndef _MACHINE_LOCK_H_
  * Spinlock functions (UP and SMP).  Under UP a spinlock still serves
  * to disable/restore interrupts even if it doesn't spin.
  */
-struct spinlock {
+struct spinlock_deprecated {
        volatile int    opaque;
 };
 
-typedef struct spinlock *spinlock_t;
+typedef struct spinlock_deprecated *spinlock_t;
 
 void   mpintr_lock(void);      /* disables int / spinlock combo */
 void   mpintr_unlock(void);
@@ -157,15 +157,10 @@ void      clock_unlock(void);
 void   cons_lock(void);        /* disables int / spinlock combo */
 void   cons_unlock(void);
 
-extern struct spinlock smp_rv_spinlock;
+extern struct spinlock_deprecated smp_rv_spinlock;
 
-void   spin_lock(spinlock_t lock);
-void   spin_lock_np(spinlock_t lock);
-void   spin_unlock(spinlock_t lock);
-void   spin_unlock_np(spinlock_t lock);
-#if 0
-void   spin_lock_init(spinlock_t lock);
-#endif
+void   spin_lock_deprecated(spinlock_t lock);
+void   spin_unlock_deprecated(spinlock_t lock);
 
 /*
  * Inline version of spinlock routines -- overrides assembly.  Only unlock
diff --git a/sys/kern/kern_spinlock.c b/sys/kern/kern_spinlock.c
new file mode 100644 (file)
index 0000000..d18cbef
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005 Jeffrey M. Hsu.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Jeffrey M. Hsu.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/kern/kern_spinlock.c,v 1.1 2005/08/28 15:27:05 hsu Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <machine/atomic.h>
+#include <sys/spinlock.h>
+
+#define        BACKOFF_INITIAL 1
+#define        BACKOFF_LIMIT   256
+
+#ifdef SMP
+
+void
+spin_lock_contested(struct spinlock *mtx)
+{
+       int i, backoff = BACKOFF_INITIAL;
+
+       do {
+               /* exponential backoff to reduce contention */
+               for (i = 0; i < backoff; i++)
+                       cpu_nop();
+               if (backoff < BACKOFF_LIMIT)
+                       backoff <<= 1;
+               /* do non-bus-locked check first */
+       } while (mtx->lock != 0 || atomic_swap_int(&mtx->lock, 1) != 0);
+}
+
+#endif
index a2e04c5..e89aed5 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
  * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $
- * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.76 2005/06/25 20:03:34 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.77 2005/08/28 15:27:05 hsu Exp $
  */
 
 #include "use_apm.h"
@@ -2726,31 +2726,31 @@ outb(u_int port, u_char data)
  */
 
 /* critical region around IO APIC, apic_imen */
-struct spinlock        imen_spinlock;
+struct spinlock_deprecated imen_spinlock;
 
 /* Make FAST_INTR() routines sequential */
-struct spinlock        fast_intr_spinlock;
+struct spinlock_deprecated fast_intr_spinlock;
 
 /* critical region for old style disable_intr/enable_intr */
-struct spinlock        mpintr_spinlock;
+struct spinlock_deprecated mpintr_spinlock;
 
 /* critical region around INTR() routines */
-struct spinlock        intr_spinlock;
+struct spinlock_deprecated intr_spinlock;
 
 /* lock region used by kernel profiling */
-struct spinlock        mcount_spinlock;
+struct spinlock_deprecated mcount_spinlock;
 
 /* locks com (tty) data/hardware accesses: a FASTINTR() */
-struct spinlock        com_spinlock;
+struct spinlock_deprecated com_spinlock;
 
 /* locks kernel printfs */
-struct spinlock        cons_spinlock;
+struct spinlock_deprecated cons_spinlock;
 
 /* lock regions around the clock hardware */
-struct spinlock        clock_spinlock;
+struct spinlock_deprecated clock_spinlock;
 
 /* lock around the MP rendezvous */
-struct spinlock smp_rv_spinlock;
+struct spinlock_deprecated smp_rv_spinlock;
 
 static void
 init_locks(void)
index 299dab1..3493dff 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
- * $DragonFly: src/sys/platform/pc32/i386/mp_machdep.c,v 1.36 2005/06/03 23:57:30 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/mp_machdep.c,v 1.37 2005/08/28 15:27:05 hsu Exp $
  */
 
 #include "opt_cpu.h"
@@ -2503,7 +2503,7 @@ smp_rendezvous(void (* setup_func)(void *),
               void *arg)
 {
        /* obtain rendezvous lock.  This disables interrupts */
-       spin_lock(&smp_rv_spinlock);    /* XXX sleep here? NOWAIT flag? */
+       spin_lock_deprecated(&smp_rv_spinlock); /* XXX sleep here? NOWAIT flag? */
 
        /* set static function pointers */
        smp_rv_setup_func = setup_func;
@@ -2529,7 +2529,7 @@ smp_rendezvous(void (* setup_func)(void *),
        smp_rendezvous_action();
 
        /* release lock */
-       spin_unlock(&smp_rv_spinlock);
+       spin_unlock_deprecated(&smp_rv_spinlock);
 }
 
 void
index 8046c99..866915f 100644 (file)
@@ -22,7 +22,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/simplelock.s,v 1.11.2.2 2003/02/04 20:55:28 jhb Exp $
- * $DragonFly: src/sys/platform/pc32/i386/spinlock.s,v 1.1 2003/07/06 21:23:48 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/spinlock.s,v 1.2 2005/08/28 15:27:05 hsu Exp $
  */
 
 #include <machine/asmacros.h>                  /* miscellaneous macros */
  *
  * NOTE: for UP the spinlock routines still disable/restore interrupts
  */
-ENTRY(spin_lock)
+ENTRY(spin_lock_deprecated)
        movl    4(%esp),%edx
        SPIN_LOCK((%edx))               /* note: %eax, %ecx tromped */
        ret
 
-ENTRY(spin_unlock)
+ENTRY(spin_unlock_deprecated)
        movl    4(%esp),%edx
        SPIN_UNLOCK((%edx))             /* note: %eax, %ecx tromped */
        ret
index dfd932b..8297185 100644 (file)
@@ -32,7 +32,7 @@
  * SUCH DAMAGE.
  * 
  * $FreeBSD: src/sys/i386/include/lock.h,v 1.11.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/platform/pc32/include/lock.h,v 1.11 2005/07/19 19:08:04 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/include/lock.h,v 1.12 2005/08/28 15:27:05 hsu Exp $
  */
 
 #ifndef _MACHINE_LOCK_H_
  * Spinlock functions (UP and SMP).  Under UP a spinlock still serves
  * to disable/restore interrupts even if it doesn't spin.
  */
-struct spinlock {
+struct spinlock_deprecated {
        volatile int    opaque;
 };
 
-typedef struct spinlock *spinlock_t;
+typedef struct spinlock_deprecated *spinlock_t;
 
 void   mpintr_lock(void);      /* disables int / spinlock combo */
 void   mpintr_unlock(void);
@@ -157,15 +157,10 @@ void      clock_unlock(void);
 void   cons_lock(void);        /* disables int / spinlock combo */
 void   cons_unlock(void);
 
-extern struct spinlock smp_rv_spinlock;
+extern struct spinlock_deprecated smp_rv_spinlock;
 
-void   spin_lock(spinlock_t lock);
-void   spin_lock_np(spinlock_t lock);
-void   spin_unlock(spinlock_t lock);
-void   spin_unlock_np(spinlock_t lock);
-#if 0
-void   spin_lock_init(spinlock_t lock);
-#endif
+void   spin_lock_deprecated(spinlock_t lock);
+void   spin_unlock_deprecated(spinlock_t lock);
 
 /*
  * Inline version of spinlock routines -- overrides assembly.  Only unlock
diff --git a/sys/sys/spinlock.h b/sys/sys/spinlock.h
new file mode 100644 (file)
index 0000000..899c9f3
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005 Jeffrey M. Hsu.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Jeffrey M. Hsu.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/sys/spinlock.h,v 1.1 2005/08/28 15:27:05 hsu Exp $
+ */
+
+#ifndef _SPINLOCK_H_
+#define _SPINLOCK_H_
+
+#ifdef _KERNEL
+#include <sys/thread2.h>
+#include <machine/atomic.h>
+#include <machine/cpufunc.h>
+#endif
+
+#ifdef SMP
+
+struct spinlock {
+       volatile int lock;      /* 0 = unlocked, 1 = locked */
+};
+
+static __inline boolean_t
+spin_trylock(struct spinlock *mtx)
+{
+       if (atomic_swap_int(&mtx->lock, 1) == 0)
+               return (TRUE);
+       return (FALSE);
+}
+
+extern void spin_lock_contested(struct spinlock *mtx);
+
+static __inline void
+spin_lock(struct spinlock *mtx)
+{
+       if (atomic_swap_int(&mtx->lock, 1) != 0)
+               spin_lock_contested(mtx);       /* slow path */
+}
+
+static __inline void
+spin_unlock(struct spinlock *mtx)
+{
+       cpu_sfence();
+       mtx->lock = 0;          /* non-bus-locked lock release */
+}
+
+static __inline boolean_t
+spin_is_locked(struct spinlock *mtx)
+{
+       return (mtx->lock);
+}
+
+static __inline void
+spin_init(struct spinlock *mtx)
+{
+        mtx->lock = 0;
+}
+
+#else  /* SMP */
+
+/*
+ * Non-MP case optimized at compile-time.
+ */
+
+struct spinlock {
+#ifndef __GNUC__                       /* GCC allows 0-sized structures */
+       volatile int lock;
+#endif
+};
+
+static __inline boolean_t
+spin_trylock(struct spinlock *mtx)
+{
+       return (TRUE);
+}
+
+static __inline boolean_t
+spin_is_locked(struct spinlock *mtx)
+{
+       return (FALSE);
+}
+
+static __inline void   spin_lock(struct spinlock *mtx) { }
+static __inline void   spin_unlock(struct spinlock *mtx) { }
+static __inline void   spin_init(struct spinlock *mtx) { }
+
+#endif /* SMP */
+
+static __inline void
+spin_lock_crit(struct spinlock *mtx)
+{
+       crit_enter();
+       spin_lock(mtx);
+}
+
+static __inline void
+spin_unlock_crit(struct spinlock *mtx)
+{
+       spin_unlock(mtx);
+       crit_exit();
+}
+
+#endif