Major cleanup of the interrupt registration subsystem.
[dragonfly.git] / sys / cpu / i386 / include / atomic.h
index 32c046d..87f3dce 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.10 2005/05/24 20:58:38 dillon Exp $
+ * $DragonFly: src/sys/cpu/i386/include/atomic.h,v 1.15 2005/10/13 00:02:46 dillon 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)
@@ -169,6 +178,16 @@ atomic_poll_release_int(volatile u_int *p)
  *     bit 0-30        interrupt handler disabled bits (counter)
  *     bit 31          interrupt handler currently running bit (1 = run)
  *
+ * atomic_intr_cond_test(P)    Determine if the interlock is in an
+ *                             acquired state.  Returns 0 if it not
+ *                             acquired, non-zero if it is.
+ *
+ * atomic_intr_cond_try(P)
+ *                             Increment the request counter and attempt to
+ *                             set bit 31 to acquire the interlock.  If
+ *                             we are unable to set bit 31 the request
+ *                             counter is decremented and we return -1,
+ *                             otherwise we return 0.
  *
  * atomic_intr_cond_enter(P, func, arg)
  *                             Increment the request counter and attempt to
@@ -215,6 +234,8 @@ void atomic_intr_init(atomic_intr_t *p);
 int atomic_intr_handler_disable(atomic_intr_t *p);
 void atomic_intr_handler_enable(atomic_intr_t *p);
 int atomic_intr_handler_is_enabled(atomic_intr_t *p);
+int atomic_intr_cond_test(atomic_intr_t *p);
+int atomic_intr_cond_try(atomic_intr_t *p);
 void atomic_intr_cond_enter(atomic_intr_t *p, void (*func)(void *), void *arg);
 void atomic_intr_cond_exit(atomic_intr_t *p, void (*func)(void *), void *arg);
 
@@ -235,7 +256,7 @@ atomic_intr_handler_disable(atomic_intr_t *p)
 
        __asm __volatile(MPLOCKED "orl $0x40000000,%1; movl %1,%%eax; " \
                                  "andl $0x80000000,%%eax" \
-                                 : "=&a"(data) : "m"(*p));
+                                 : "=a"(data) , "+m"(*p));
        return(data);
 }
 
@@ -243,7 +264,7 @@ static __inline
 void
 atomic_intr_handler_enable(atomic_intr_t *p)
 {
-       __asm __volatile(MPLOCKED "andl $0xB0000000,%0" : "+m" (*p));
+       __asm __volatile(MPLOCKED "andl $0xBFFFFFFF,%0" : "+m" (*p));
 }
 
 static __inline
@@ -272,6 +293,36 @@ atomic_intr_cond_enter(atomic_intr_t *p, void (*func)(void *), void *arg)
                         : "ax", "cx", "dx");
 }
 
+/*
+ * Attempt to enter the interrupt condition variable.  Returns zero on
+ * success, 1 on failure.
+ */
+static __inline
+int
+atomic_intr_cond_try(atomic_intr_t *p)
+{
+       int ret;
+
+       __asm __volatile(MPLOCKED "incl %0; " \
+                        "1: ;" \
+                        "subl %%eax,%%eax; " \
+                        MPLOCKED "btsl $31,%0; jnc 2f; " \
+                        MPLOCKED "decl %0; " \
+                        "movl $1,%%eax;" \
+                        "2: ;" \
+                        : "+m" (*p), "=a"(ret) \
+                        : : "cx", "dx");
+       return (ret);
+}
+
+
+static __inline
+int
+atomic_intr_cond_test(atomic_intr_t *p)
+{
+       return((int)(*p & 0x80000000));
+}
+
 static __inline
 void
 atomic_intr_cond_exit(atomic_intr_t *p, void (*func)(void *), void *arg)