summaryrefslogtreecommitdiffstats
path: root/arch/ppc/lib/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/lib/locks.c')
-rw-r--r--arch/ppc/lib/locks.c91
1 files changed, 43 insertions, 48 deletions
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
index 2d2a2d8c0..699c13fad 100644
--- a/arch/ppc/lib/locks.c
+++ b/arch/ppc/lib/locks.c
@@ -1,5 +1,5 @@
/*
- * $Id: locks.c,v 1.21 1998/12/28 10:28:53 paulus Exp $
+ * $Id: locks.c,v 1.23 1999/02/12 07:06:32 cort Exp $
*
* Locks for smp ppc
*
@@ -26,24 +26,18 @@ void _spin_lock(spinlock_t *lock)
#ifdef DEBUG_LOCKS
unsigned int stuck = INIT_STUCK;
#endif /* DEBUG_LOCKS */
- /* try expensive atomic load/store to get lock */
- while((unsigned long )xchg_u32((void *)&lock->lock,0xffffffff)) {
- /* try cheap load until it's free */
- while(lock->lock) {
+ while (__spin_trylock(&lock->lock)) {
#ifdef DEBUG_LOCKS
- if(!--stuck)
- {
- printk("_spin_lock(%p) CPU#%d NIP %p"
- " holder: cpu %ld pc %08lX\n",
- lock, cpu, __builtin_return_address(0),
- lock->owner_cpu,lock->owner_pc);
- stuck = INIT_STUCK;
- /* steal the lock */
- /*xchg_u32((void *)&lock->lock,0);*/
- }
-#endif /* DEBUG_LOCKS */
- barrier();
+ if(!--stuck) {
+ printk("_spin_lock(%p) CPU#%d NIP %p"
+ " holder: cpu %ld pc %08lX\n",
+ lock, cpu, __builtin_return_address(0),
+ lock->owner_cpu,lock->owner_pc);
+ stuck = INIT_STUCK;
+ /* steal the lock */
+ /*xchg_u32((void *)&lock->lock,0);*/
}
+#endif /* DEBUG_LOCKS */
}
lock->owner_pc = (unsigned long)__builtin_return_address(0);
lock->owner_cpu = cpu;
@@ -51,15 +45,11 @@ void _spin_lock(spinlock_t *lock)
int spin_trylock(spinlock_t *lock)
{
- unsigned long result;
-
- result = (unsigned long )xchg_u32((void *)&lock->lock,0xffffffff);
- if ( !result )
- {
- lock->owner_cpu = smp_processor_id();
- lock->owner_pc = (unsigned long)__builtin_return_address(0);
- }
- return (result == 0);
+ if (__spin_trylock(&lock->lock))
+ return 0;
+ lock->owner_cpu = smp_processor_id();
+ lock->owner_pc = (unsigned long)__builtin_return_address(0);
+ return 1;
}
@@ -76,11 +66,11 @@ void _spin_unlock(spinlock_t *lp)
lp->owner_pc,lp->lock);
#endif /* DEBUG_LOCKS */
lp->owner_pc = lp->owner_cpu = 0;
- eieio(); /* actually I believe eieio only orders */
- lp->lock = 0; /* non-cacheable accesses (on 604 at least) */
- eieio(); /* - paulus. */
+ wmb();
+ lp->lock = 0;
+ wmb();
}
-
+
/*
* Just like x86, implement read-write locks as a 32-bit counter
* with the high bit (sign) being the "write" bit.
@@ -95,6 +85,7 @@ void _read_lock(rwlock_t *rw)
again:
/* get our read lock in there */
+ wmb();
atomic_inc((atomic_t *) &(rw)->lock);
if ( (signed long)((rw)->lock) < 0) /* someone has a write lock */
{
@@ -114,6 +105,7 @@ again:
/* try to get the read lock again */
goto again;
}
+ wmb();
}
void _read_unlock(rwlock_t *rw)
@@ -124,7 +116,9 @@ void _read_unlock(rwlock_t *rw)
current->comm,current->pid,current->tss.regs->nip,
rw->lock);
#endif /* DEBUG_LOCKS */
+ wmb();
atomic_dec((atomic_t *) &(rw)->lock);
+ wmb();
}
void _write_lock(rwlock_t *rw)
@@ -134,7 +128,8 @@ void _write_lock(rwlock_t *rw)
int cpu = smp_processor_id();
#endif /* DEBUG_LOCKS */
-again:
+again:
+ wmb();
if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */
{
while ( (rw)->lock & (1<<31) ) /* wait for write lock */
@@ -170,6 +165,7 @@ again:
}
goto again;
}
+ wmb();
}
void _write_unlock(rwlock_t *rw)
@@ -180,7 +176,9 @@ void _write_unlock(rwlock_t *rw)
current->comm,current->pid,current->tss.regs->nip,
rw->lock);
#endif /* DEBUG_LOCKS */
+ wmb();
clear_bit(31,&(rw)->lock);
+ wmb();
}
void __lock_kernel(struct task_struct *task)
@@ -196,24 +194,18 @@ void __lock_kernel(struct task_struct *task)
}
#endif /* DEBUG_LOCKS */
- if ( atomic_inc_return((atomic_t *) &task->lock_depth) != 1 )
+ if (atomic_inc_return((atomic_t *) &task->lock_depth) != 1)
return;
/* mine! */
- while ( xchg_u32( (void *)&klock_info.kernel_flag, KLOCK_HELD) )
- {
- /* try cheap load until it's free */
- while(klock_info.kernel_flag) {
+ while (__spin_trylock(&klock_info.kernel_flag)) {
#ifdef DEBUG_LOCKS
- if(!--stuck)
- {
- printk("_lock_kernel() CPU#%d NIP %p\n",
- smp_processor_id(),
- __builtin_return_address(0));
- stuck = INIT_STUCK;
- }
-#endif /* DEBUG_LOCKS */
- barrier();
+ if(!--stuck) {
+ printk("_lock_kernel() CPU#%d NIP %p\n",
+ smp_processor_id(),
+ __builtin_return_address(0));
+ stuck = INIT_STUCK;
}
+#endif /* DEBUG_LOCKS */
}
klock_info.akp = smp_processor_id();
@@ -223,7 +215,7 @@ void __lock_kernel(struct task_struct *task)
void __unlock_kernel(struct task_struct *task)
{
#ifdef DEBUG_LOCKS
- if ( (task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD) )
+ if ((task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD))
{
printk("__unlock_kernel(): %s/%d (nip %08lX) "
"lock depth %x flags %lx\n",
@@ -234,10 +226,13 @@ void __unlock_kernel(struct task_struct *task)
return;
}
#endif /* DEBUG_LOCKS */
- if ( atomic_dec_and_test((atomic_t *) &task->lock_depth) )
+ if (atomic_dec_and_test((atomic_t *) &task->lock_depth))
{
+ wmb();
klock_info.akp = NO_PROC_ID;
+ wmb();
klock_info.kernel_flag = KLOCK_CLEAR;
+ wmb();
}
}
@@ -249,5 +244,5 @@ void reacquire_kernel_lock(struct task_struct *task, int cpu,int depth)
__lock_kernel(task);
task->lock_depth = depth;
__sti();
- }
+ }
}