Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / include / asm-parisc / spinlock.h
index 1ad3aaa..a93960e 100644 (file)
@@ -2,85 +2,85 @@
 #define __ASM_SPINLOCK_H
 
 #include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/spinlock_types.h>
 
-/* Note that PA-RISC has to use `1' to mean unlocked and `0' to mean locked
- * since it only has load-and-zero. Moreover, at least on some PA processors,
- * the semaphore address has to be 16-byte aligned.
- */
-
-#undef SPIN_LOCK_UNLOCKED
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { { 1, 1, 1, 1 } }
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-static inline int spin_is_locked(spinlock_t *x)
+static inline int __raw_spin_is_locked(raw_spinlock_t *x)
 {
        volatile unsigned int *a = __ldcw_align(x);
        return *a == 0;
 }
 
-#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock(lock) __raw_spin_lock_flags(lock, 0)
+#define __raw_spin_unlock_wait(x) \
+               do { cpu_relax(); } while (__raw_spin_is_locked(x))
 
-static inline void _raw_spin_lock(spinlock_t *x)
+static inline void __raw_spin_lock_flags(raw_spinlock_t *x,
+                                        unsigned long flags)
 {
-       volatile unsigned int *a = __ldcw_align(x);
+       volatile unsigned int *a;
+
+       mb();
+       a = __ldcw_align(x);
        while (__ldcw(a) == 0)
-               while (*a == 0);
+               while (*a == 0)
+                       if (flags & PSW_SM_I) {
+                               local_irq_enable();
+                               cpu_relax();
+                               local_irq_disable();
+                       } else
+                               cpu_relax();
+       mb();
 }
 
-static inline void _raw_spin_unlock(spinlock_t *x)
+static inline void __raw_spin_unlock(raw_spinlock_t *x)
 {
-       volatile unsigned int *a = __ldcw_align(x);
+       volatile unsigned int *a;
+       mb();
+       a = __ldcw_align(x);
        *a = 1;
+       mb();
 }
 
-static inline int _raw_spin_trylock(spinlock_t *x)
+static inline int __raw_spin_trylock(raw_spinlock_t *x)
 {
-       volatile unsigned int *a = __ldcw_align(x);
-       return __ldcw(a) != 0;
+       volatile unsigned int *a;
+       int ret;
+
+       mb();
+       a = __ldcw_align(x);
+        ret = __ldcw(a) != 0;
+       mb();
+
+       return ret;
 }
-       
+
 /*
  * Read-write spinlocks, allowing multiple readers
  * but only one writer.
  */
-typedef struct {
-       spinlock_t lock;
-       volatile int counter;
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { { { 1, 1, 1, 1 } }, 0 }
-
-#define rwlock_init(lp)        do { *(lp) = RW_LOCK_UNLOCKED; } while (0)
 
-#define rwlock_is_locked(lp) ((lp)->counter != 0)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
 /* read_lock, read_unlock are pretty straightforward.  Of course it somehow
  * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */
 
-static  __inline__ void _raw_read_lock(rwlock_t *rw)
+static  __inline__ void __raw_read_lock(raw_rwlock_t *rw)
 {
-       unsigned long flags;
-       local_irq_save(flags);
-       _raw_spin_lock(&rw->lock); 
+       __raw_spin_lock(&rw->lock);
 
        rw->counter++;
 
-       _raw_spin_unlock(&rw->lock);
-       local_irq_restore(flags);
+       __raw_spin_unlock(&rw->lock);
 }
 
-static  __inline__ void _raw_read_unlock(rwlock_t *rw)
+static  __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
 {
-       unsigned long flags;
-       local_irq_save(flags);
-       _raw_spin_lock(&rw->lock); 
+       __raw_spin_lock(&rw->lock);
 
        rw->counter--;
 
-       _raw_spin_unlock(&rw->lock);
-       local_irq_restore(flags);
+       __raw_spin_unlock(&rw->lock);
 }
 
 /* write_lock is less trivial.  We optimistically grab the lock and check
@@ -92,16 +92,17 @@ static  __inline__ void _raw_read_unlock(rwlock_t *rw)
  * writers) in interrupt handlers someone fucked up and we'd dead-lock
  * sooner or later anyway.   prumpf */
 
-static  __inline__ void _raw_write_lock(rwlock_t *rw)
+static  __inline__ void __raw_write_lock(raw_rwlock_t *rw)
 {
 retry:
-       _raw_spin_lock(&rw->lock);
+       __raw_spin_lock(&rw->lock);
 
        if(rw->counter != 0) {
                /* this basically never happens */
-               _raw_spin_unlock(&rw->lock);
+               __raw_spin_unlock(&rw->lock);
 
-               while(rw->counter != 0);
+               while (rw->counter != 0)
+                       cpu_relax();
 
                goto retry;
        }
@@ -112,20 +113,43 @@ retry:
 
 /* write_unlock is absolutely trivial - we don't have to wait for anything */
 
-static  __inline__ void _raw_write_unlock(rwlock_t *rw)
+static  __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
 {
        rw->counter = 0;
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
 }
 
-static __inline__ int is_read_locked(rwlock_t *rw)
+static  __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
 {
-       return rw->counter > 0;
+       __raw_spin_lock(&rw->lock);
+       if (rw->counter != 0) {
+               /* this basically never happens */
+               __raw_spin_unlock(&rw->lock);
+
+               return 0;
+       }
+
+       /* got it.  now leave without unlocking */
+       rw->counter = -1; /* remember we are locked */
+       return 1;
 }
 
-static __inline__ int is_write_locked(rwlock_t *rw)
+/*
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_read_can_lock(raw_rwlock_t *rw)
+{
+       return rw->counter >= 0;
+}
+
+/*
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+static __inline__ int __raw_write_can_lock(raw_rwlock_t *rw)
 {
-       return rw->counter < 0;
+       return !rw->counter;
 }
 
 #endif /* __ASM_SPINLOCK_H */