X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2Flib%2Flocks.c;h=694163d696d886244b6ea769ab8b19abed8b65a0;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=0eaffa9b59aefbcfdf7093bd34e917f8ec634517;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c index 0eaffa9b5..694163d69 100644 --- a/arch/ppc/lib/locks.c +++ b/arch/ppc/lib/locks.c @@ -91,44 +91,57 @@ void _raw_spin_unlock(spinlock_t *lp) } EXPORT_SYMBOL(_raw_spin_unlock); - /* - * Just like x86, implement read-write locks as a 32-bit counter - * with the high bit (sign) being the "write" bit. - * -- Cort + * For rwlocks, zero is unlocked, -1 is write-locked, + * positive is read-locked. */ -void _raw_read_lock(rwlock_t *rw) +static __inline__ int __read_trylock(rwlock_t *rw) { - unsigned long stuck = INIT_STUCK; - int cpu = smp_processor_id(); + signed int tmp; + + __asm__ __volatile__( +"2: lwarx %0,0,%1 # __read_trylock\n\ + addic. %0,%0,1\n\ + ble- 1f\n" + PPC405_ERR77(0,%1) +" stwcx. %0,0,%1\n\ + bne- 2b\n\ + isync\n\ +1:" + : "=&r"(tmp) + : "r"(&rw->lock) + : "cr0", "memory"); -again: - /* get our read lock in there */ - atomic_inc((atomic_t *) &(rw)->lock); - if ( (signed long)((rw)->lock) < 0) /* someone has a write lock */ - { - /* turn off our read lock */ - atomic_dec((atomic_t *) &(rw)->lock); - /* wait for the write lock to go away */ - while ((signed long)((rw)->lock) < 0) - { - if(!--stuck) - { - printk("_read_lock(%p) CPU#%d\n", rw, cpu); + return tmp; +} + +int _raw_read_trylock(rwlock_t *rw) +{ + return __read_trylock(rw) > 0; +} +EXPORT_SYMBOL(_raw_read_trylock); + +void _raw_read_lock(rwlock_t *rw) +{ + unsigned int stuck; + + while (__read_trylock(rw) <= 0) { + stuck = INIT_STUCK; + while (!read_can_lock(rw)) { + if (--stuck == 0) { + printk("_read_lock(%p) CPU#%d lock %d\n", + rw, _smp_processor_id(), rw->lock); stuck = INIT_STUCK; } } - /* try to get the read lock again */ - goto again; } - wmb(); } EXPORT_SYMBOL(_raw_read_lock); void _raw_read_unlock(rwlock_t *rw) { if ( rw->lock == 0 ) - printk("_read_unlock(): %s/%d (nip %08lX) lock %lx\n", + printk("_read_unlock(): %s/%d (nip %08lX) lock %d\n", current->comm,current->pid,current->thread.regs->nip, rw->lock); wmb(); @@ -138,40 +151,17 @@ EXPORT_SYMBOL(_raw_read_unlock); void _raw_write_lock(rwlock_t *rw) { - unsigned long stuck = INIT_STUCK; - int cpu = smp_processor_id(); - -again: - if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */ - { - while ( (rw)->lock & (1<<31) ) /* wait for write lock */ - { - if(!--stuck) - { - printk("write_lock(%p) CPU#%d lock %lx)\n", - rw, cpu,rw->lock); - stuck = INIT_STUCK; - } - barrier(); - } - goto again; - } - - if ( (rw)->lock & ~(1<<31)) /* someone has a read lock */ - { - /* clear our write lock and wait for reads to go away */ - clear_bit(31,&(rw)->lock); - while ( (rw)->lock & ~(1<<31) ) - { - if(!--stuck) - { - printk("write_lock(%p) 2 CPU#%d lock %lx)\n", - rw, cpu,rw->lock); + unsigned int stuck; + + while (cmpxchg(&rw->lock, 0, -1) != 0) { + stuck = INIT_STUCK; + while (!write_can_lock(rw)) { + if (--stuck == 0) { + printk("write_lock(%p) CPU#%d lock %d)\n", + rw, _smp_processor_id(), rw->lock); stuck = INIT_STUCK; } - barrier(); } - goto again; } wmb(); } @@ -179,14 +169,8 @@ EXPORT_SYMBOL(_raw_write_lock); int _raw_write_trylock(rwlock_t *rw) { - if (test_and_set_bit(31, &(rw)->lock)) /* someone has a write lock */ + if (cmpxchg(&rw->lock, 0, -1) != 0) return 0; - - if ((rw)->lock & ~(1<<31)) { /* someone has a read lock */ - /* clear our write lock and wait for reads to go away */ - clear_bit(31,&(rw)->lock); - return 0; - } wmb(); return 1; } @@ -194,12 +178,12 @@ EXPORT_SYMBOL(_raw_write_trylock); void _raw_write_unlock(rwlock_t *rw) { - if ( !(rw->lock & (1<<31)) ) - printk("_write_lock(): %s/%d (nip %08lX) lock %lx\n", + if (rw->lock >= 0) + printk("_write_lock(): %s/%d (nip %08lX) lock %d\n", current->comm,current->pid,current->thread.regs->nip, rw->lock); wmb(); - clear_bit(31,&(rw)->lock); + rw->lock = 0; } EXPORT_SYMBOL(_raw_write_unlock);