patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / sparc64 / lib / debuglocks.c
index 341cce7..9e083e2 100644 (file)
@@ -55,7 +55,7 @@ void _do_spin_lock(spinlock_t *lock, char *str)
 {
        unsigned long caller, val;
        int stuck = INIT_STUCK;
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
        int shown = 0;
 
        GET_CALLER(caller);
@@ -80,12 +80,14 @@ again:
        lock->owner_cpu = cpu;
        current->thread.smp_lock_count++;
        current->thread.smp_lock_pc = ((unsigned int)caller);
+
+       put_cpu();
 }
 
 int _spin_trylock(spinlock_t *lock)
 {
        unsigned long val, caller;
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
 
        GET_CALLER(caller);
        __asm__ __volatile__("ldstub [%1], %0"
@@ -99,6 +101,9 @@ int _spin_trylock(spinlock_t *lock)
                current->thread.smp_lock_count++;
                current->thread.smp_lock_pc = ((unsigned int)caller);
        }
+
+       put_cpu();
+
        return val == 0;
 }
 
@@ -117,7 +122,7 @@ void _do_read_lock (rwlock_t *rw, char *str)
 {
        unsigned long caller, val;
        int stuck = INIT_STUCK;
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
        int shown = 0;
 
        GET_CALLER(caller);
@@ -148,13 +153,15 @@ wlock_again:
        rw->reader_pc[cpu] = ((unsigned int)caller);
        current->thread.smp_lock_count++;
        current->thread.smp_lock_pc = ((unsigned int)caller);
+
+       put_cpu();
 }
 
 void _do_read_unlock (rwlock_t *rw, char *str)
 {
        unsigned long caller, val;
        int stuck = INIT_STUCK;
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
        int shown = 0;
 
        GET_CALLER(caller);
@@ -181,13 +188,15 @@ runlock_again:
                }
                goto runlock_again;
        }
+
+       put_cpu();
 }
 
 void _do_write_lock (rwlock_t *rw, char *str)
 {
        unsigned long caller, val;
        int stuck = INIT_STUCK;
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
        int shown = 0;
 
        GET_CALLER(caller);
@@ -263,6 +272,8 @@ wlock_again:
        rw->writer_cpu = cpu;
        current->thread.smp_lock_count++;
        current->thread.smp_lock_pc = ((unsigned int)caller);
+
+       put_cpu();
 }
 
 void _do_write_unlock(rwlock_t *rw)
@@ -299,4 +310,65 @@ wlock_again:
        }
 }
 
+int _do_write_trylock (rwlock_t *rw, char *str)
+{
+       unsigned long caller, val;
+       int cpu = get_cpu();
+
+       GET_CALLER(caller);
+
+       /* Try to acuire the write bit.  */
+       __asm__ __volatile__(
+"      mov     1, %%g3\n"
+"      sllx    %%g3, 63, %%g3\n"
+"      ldx     [%0], %%g5\n"
+"      brlz,pn %%g5, 1f\n"
+"       or     %%g5, %%g3, %%g7\n"
+"      casx    [%0], %%g5, %%g7\n"
+"      membar  #StoreLoad | #StoreStore\n"
+"      ba,pt   %%xcc, 2f\n"
+"       sub    %%g5, %%g7, %0\n"
+"1:    mov     1, %0\n"
+"2:"   : "=r" (val)
+       : "0" (&(rw->lock))
+       : "g3", "g5", "g7", "memory");
+
+       if (val) {
+               put_cpu();
+               return 0;
+       }
+
+       if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
+               /* Readers still around, drop the write
+                * lock, return failure.
+                */
+               __asm__ __volatile__(
+"              mov     1, %%g3\n"
+"              sllx    %%g3, 63, %%g3\n"
+"1:            ldx     [%0], %%g5\n"
+"              andn    %%g5, %%g3, %%g7\n"
+"              casx    [%0], %%g5, %%g7\n"
+"              cmp     %%g5, %%g7\n"
+"              bne,pn  %%xcc, 1b\n"
+"               membar #StoreLoad | #StoreStore"
+               : /* no outputs */
+               : "r" (&(rw->lock))
+               : "g3", "g5", "g7", "cc", "memory");
+
+               put_cpu();
+
+               return 0;
+       }
+
+       /* We have it, say who we are. */
+       rw->writer_pc = ((unsigned int)caller);
+       rw->writer_cpu = cpu;
+       current->thread.smp_lock_count++;
+       current->thread.smp_lock_pc = ((unsigned int)caller);
+
+       put_cpu();
+
+       return 1;
+}
+
 #endif /* CONFIG_SMP */