]> git.neil.brown.name Git - history.git/commitdiff
[SPARC64]: Implement debugging version of write_trylock().
authorDavid S. Miller <davem@nuts.davemloft.net>
Tue, 25 May 2004 07:01:13 +0000 (00:01 -0700)
committerDavid S. Miller <davem@nuts.davemloft.net>
Tue, 25 May 2004 07:01:13 +0000 (00:01 -0700)
arch/sparc64/lib/debuglocks.c
include/asm-sparc64/spinlock.h

index 341cce76b773237ec16c572fa442c14506b3dd50..8382964e49949d612c42f13d510acc823ce32086 100644 (file)
@@ -299,4 +299,61 @@ wlock_again:
        }
 }
 
+int _do_write_trylock (rwlock_t *rw, char *str)
+{
+       unsigned long caller, val;
+       int stuck = INIT_STUCK;
+       int cpu = smp_processor_id();
+       int shown = 0;
+
+       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)
+               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");
+
+               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);
+
+       return 1;
+}
+
 #endif /* CONFIG_SMP */
index ae06e2ffc3e2172402c86b605e06c1f6eadf3b14..10e5cf326dc23d53204e504fa3990ec23b78bab4 100644 (file)
@@ -144,6 +144,7 @@ extern void _do_read_lock(rwlock_t *rw, char *str);
 extern void _do_read_unlock(rwlock_t *rw, char *str);
 extern void _do_write_lock(rwlock_t *rw, char *str);
 extern void _do_write_unlock(rwlock_t *rw);
+extern int _do_write_trylock(rwlock_t *rw, char *str);
 
 #define _raw_read_lock(lock) \
 do {   unsigned long flags; \
@@ -173,6 +174,15 @@ do {       unsigned long flags; \
        local_irq_restore(flags); \
 } while(0)
 
+#define _raw_write_trylock(lock) \
+({     unsigned long flags; \
+       int val; \
+       local_irq_save(flags); \
+       val = _do_write_trylock(lock, "write_trylock"); \
+       local_irq_restore(flags); \
+       val; \
+})
+
 #endif /* CONFIG_DEBUG_SPINLOCK */
 
 #endif /* !(__ASSEMBLY__) */