Fix arch headers.
[linux-flexiantxendom0-3.2.10.git] / include / asm-ia64 / spinlock.h
index 2a40f54..96e298c 100644 (file)
@@ -22,26 +22,72 @@ typedef struct {
 #define SPIN_LOCK_UNLOCKED                     (spinlock_t) { 0 }
 #define spin_lock_init(x)                      ((x)->lock = 0)
 
-#define DEBUG_SPIN_LOCK        0
+#define NEW_LOCK
+#ifdef NEW_LOCK
 
-#if DEBUG_SPIN_LOCK
-
-#include <ia64intrin.h>
-
-#define _raw_spin_lock(x)                                                              \
-do {                                                                                   \
-       unsigned long _timeout = 1000000000;                                            \
-       volatile unsigned int _old = 0, _new = 1, *_ptr = &((x)->lock);                 \
-       do {                                                                            \
-               if (_timeout-- == 0) {                                                  \
-                       extern void dump_stack (void);                                  \
-                       printk("kernel DEADLOCK at %s:%d?\n", __FILE__, __LINE__);      \
-                       dump_stack();                                                   \
-               }                                                                       \
-       } while (__sync_val_compare_and_swap(_ptr, _old, _new) != _old);                \
-} while (0)
+/*
+ * Try to get the lock.  If we fail to get the lock, make a non-standard call to
+ * ia64_spinlock_contention().  We do not use a normal call because that would force all
+ * callers of spin_lock() to be non-leaf routines.  Instead, ia64_spinlock_contention() is
+ * carefully coded to touch only those registers that spin_lock() marks "clobbered".
+ */
 
+#define IA64_SPINLOCK_CLOBBERS "ar.pfs", "p14", "r28", "r29", "r30", "b6", "memory"
+
+static inline void
+_raw_spin_lock (spinlock_t *lock)
+{
+       register volatile unsigned int *ptr asm ("r31") = &lock->lock;
+
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4)
+# ifdef CONFIG_ITANIUM
+       /* don't use brl on Itanium... */
+       asm volatile ("{\n\t"
+                     "  mov ar.ccv = r0\n\t"
+                     "  mov r28 = ip\n\t"
+                     "  mov r30 = 1;;\n\t"
+                     "}\n\t"
+                     "cmpxchg4.acq r30 = [%1], r30, ar.ccv\n\t"
+                     "movl r29 = ia64_spinlock_contention_pre3_4;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "mov b6 = r29;;\n"
+                     "(p14) br.cond.spnt.many b6"
+                     : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# else
+       asm volatile ("{\n\t"
+                     "  mov ar.ccv = r0\n\t"
+                     "  mov r28 = ip\n\t"
+                     "  mov r30 = 1;;\n\t"
+                     "}\n\t"
+                     "cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n"
+                     "(p14) brl.cond.spnt.many ia64_spinlock_contention_pre3_4"
+                     : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# endif /* CONFIG_MCKINLEY */
 #else
+# ifdef CONFIG_ITANIUM
+       /* don't use brl on Itanium... */
+       /* mis-declare, so we get the entry-point, not it's function descriptor: */
+       asm volatile ("mov r30 = 1\n\t"
+                     "mov ar.ccv = r0;;\n\t"
+                     "cmpxchg4.acq r30 = [%0], r30, ar.ccv\n\t"
+                     "movl r29 = ia64_spinlock_contention;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "mov b6 = r29;;\n"
+                     "(p14) br.call.spnt.many b6 = b6"
+                     : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# else
+       asm volatile ("mov r30 = 1\n\t"
+                     "mov ar.ccv = r0;;\n\t"
+                     "cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "(p14) brl.call.spnt.many b6=ia64_spinlock_contention"
+                     : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
+# endif /* CONFIG_MCKINLEY */
+#endif
+}
+
+#else /* !NEW_LOCK */
 
 /*
  * Streamlined test_and_set_bit(0, (x)).  We use test-and-test-and-set
@@ -64,7 +110,7 @@ do {                                                                                 \
        ";;\n"                                                  \
        :: "r"(&(x)->lock) : "ar.ccv", "p7", "r2", "r29", "memory")
 
-#endif /* !DEBUG_SPIN_LOCK */
+#endif /* !NEW_LOCK */
 
 #define spin_is_locked(x)      ((x)->lock != 0)
 #define _raw_spin_unlock(x)    do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0)
@@ -72,43 +118,31 @@ do {                                                                                       \
 #define spin_unlock_wait(x)    do { barrier(); } while ((x)->lock)
 
 typedef struct {
-       volatile int read_counter:31;
-       volatile int write_lock:1;
+       volatile int read_counter       : 31;
+       volatile int write_lock         :  1;
 } rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
 
 #define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 #define rwlock_is_locked(x)    (*(volatile int *) (x) != 0)
 
-#define _raw_read_lock(rw)                                                     \
-do {                                                                           \
-       int __read_lock_tmp = 0;                                                \
-       __asm__ __volatile__ ("1:\tfetchadd4.acq %0 = [%1], 1\n"                \
-                             ";;\n"                                            \
-                             "tbit.nz p6,p0 = %0, 31\n"                        \
-                             "(p6) br.cond.sptk.few 2f\n"                      \
-                             ".section .text.lock,\"ax\"\n"                    \
-                             "2:\tfetchadd4.rel %0 = [%1], -1\n"               \
-                             ";;\n"                                            \
-                             "3:\tld4.acq %0 = [%1]\n"                         \
-                             ";;\n"                                            \
-                             "tbit.nz p6,p0 = %0, 31\n"                        \
-                             "(p6) br.cond.sptk.few 3b\n"                      \
-                             "br.cond.sptk.few 1b\n"                           \
-                             ";;\n"                                            \
-                             ".previous\n"                                     \
-                             : "=&r" (__read_lock_tmp)                         \
-                             : "r" (rw) : "p6", "memory");                     \
-} while(0)
+#define _raw_read_lock(rw)                                                             \
+do {                                                                                   \
+       rwlock_t *__read_lock_ptr = (rw);                                               \
+                                                                                       \
+       while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, "acq") < 0)) {        \
+               ia64_fetchadd(-1, (int *) __read_lock_ptr, "rel");                      \
+               while (*(volatile int *)__read_lock_ptr < 0)                            \
+                       barrier();                                                      \
+                                                                                       \
+       }                                                                               \
+} while (0)
 
-#define _raw_read_unlock(rw)                                                   \
-do {                                                                           \
-       int __read_unlock_tmp = 0;                                              \
-       __asm__ __volatile__ ("fetchadd4.rel %0 = [%1], -1\n"                   \
-                             : "=r" (__read_unlock_tmp)                        \
-                             : "r" (rw)                                        \
-                             : "memory");                                      \
-} while(0)
+#define _raw_read_unlock(rw)                                   \
+do {                                                           \
+       rwlock_t *__read_lock_ptr = (rw);                       \
+       ia64_fetchadd(-1, (int *) __read_lock_ptr, "rel");      \
+} while (0)
 
 #define _raw_write_lock(rw)                                                    \
 do {                                                                           \