patch-2.4.10 linux/arch/ppc/lib/locks.c
Next file: linux/arch/ppc/mm/4xx_mmu.c
Previous file: linux/arch/ppc/lib/checksum.S
Back to the patch index
Back to the overall index
- Lines: 265
- Date:
Tue Aug 28 06:58:33 2001
- Orig file:
v2.4.9/linux/arch/ppc/lib/locks.c
- Orig date:
Mon May 21 17:04:47 2001
diff -u --recursive --new-file v2.4.9/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.locks.c 1.8 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.locks.c 1.11 08/19/01 22:27:32 paulus
*/
/*
* Locks for smp ppc
@@ -16,29 +16,53 @@
#include <asm/system.h>
#include <asm/io.h>
-#define DEBUG_LOCKS 1
+#ifdef SPINLOCK_DEBUG
#undef INIT_STUCK
#define INIT_STUCK 200000000 /*0xffffffff*/
+/*
+ * Try to acquire a spinlock.
+ * Only does the stwcx. if the load returned 0 - the Programming
+ * Environments Manual suggests not doing unnecessary stcwx.'s
+ * since they may inhibit forward progress by other CPUs in getting
+ * a lock.
+ */
+static unsigned long __spin_trylock(volatile unsigned long *lock)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__ ("\n\
+1: lwarx %0,0,%1\n\
+ cmpwi 0,%0,0\n\
+ bne 2f\n\
+ stwcx. %2,0,%1\n\
+ bne- 1b\n\
+ isync\n\
+2:"
+ : "=&r"(ret)
+ : "r"(lock), "r"(1)
+ : "cr0", "memory");
+
+ return ret;
+}
+
void _spin_lock(spinlock_t *lock)
{
int cpu = smp_processor_id();
-#ifdef DEBUG_LOCKS
unsigned int stuck = INIT_STUCK;
-#endif /* DEBUG_LOCKS */
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);*/
+ while ((unsigned volatile long)lock->lock != 0) {
+ 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;
@@ -53,11 +77,8 @@
return 1;
}
-
-
void _spin_unlock(spinlock_t *lp)
{
-#ifdef DEBUG_LOCKS
if ( !lp->lock )
printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n",
lp, smp_processor_id(), __builtin_return_address(0),
@@ -66,13 +87,12 @@
printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n",
lp, smp_processor_id(), (int)lp->owner_cpu,
lp->owner_pc,lp->lock);
-#endif /* DEBUG_LOCKS */
lp->owner_pc = lp->owner_cpu = 0;
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.
@@ -80,14 +100,11 @@
*/
void _read_lock(rwlock_t *rw)
{
-#ifdef DEBUG_LOCKS
unsigned long stuck = INIT_STUCK;
int cpu = smp_processor_id();
-#endif /* DEBUG_LOCKS */
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 */
{
@@ -96,13 +113,11 @@
/* wait for the write lock to go away */
while ((signed long)((rw)->lock) < 0)
{
-#ifdef DEBUG_LOCKS
if(!--stuck)
{
printk("_read_lock(%p) CPU#%d\n", rw, cpu);
stuck = INIT_STUCK;
}
-#endif /* DEBUG_LOCKS */
}
/* try to get the read lock again */
goto again;
@@ -112,38 +127,30 @@
void _read_unlock(rwlock_t *rw)
{
-#ifdef DEBUG_LOCKS
if ( rw->lock == 0 )
printk("_read_unlock(): %s/%d (nip %08lX) lock %lx\n",
current->comm,current->pid,current->thread.regs->nip,
rw->lock);
-#endif /* DEBUG_LOCKS */
wmb();
atomic_dec((atomic_t *) &(rw)->lock);
- wmb();
}
void _write_lock(rwlock_t *rw)
{
-#ifdef DEBUG_LOCKS
unsigned long stuck = INIT_STUCK;
int cpu = smp_processor_id();
-#endif /* DEBUG_LOCKS */
again:
- wmb();
if ( test_and_set_bit(31,&(rw)->lock) ) /* someone has a write lock */
{
while ( (rw)->lock & (1<<31) ) /* wait for write lock */
{
-#ifdef DEBUG_LOCKS
if(!--stuck)
{
printk("write_lock(%p) CPU#%d lock %lx)\n",
rw, cpu,rw->lock);
stuck = INIT_STUCK;
}
-#endif /* DEBUG_LOCKS */
barrier();
}
goto again;
@@ -155,14 +162,12 @@
clear_bit(31,&(rw)->lock);
while ( (rw)->lock & ~(1<<31) )
{
-#ifdef DEBUG_LOCKS
if(!--stuck)
{
printk("write_lock(%p) 2 CPU#%d lock %lx)\n",
rw, cpu,rw->lock);
stuck = INIT_STUCK;
}
-#endif /* DEBUG_LOCKS */
barrier();
}
goto again;
@@ -172,79 +177,12 @@
void _write_unlock(rwlock_t *rw)
{
-#ifdef DEBUG_LOCKS
if ( !(rw->lock & (1<<31)) )
printk("_write_lock(): %s/%d (nip %08lX) lock %lx\n",
current->comm,current->pid,current->thread.regs->nip,
rw->lock);
-#endif /* DEBUG_LOCKS */
wmb();
clear_bit(31,&(rw)->lock);
- wmb();
-}
-
-void __lock_kernel(struct task_struct *task)
-{
-#ifdef DEBUG_LOCKS
- unsigned long stuck = INIT_STUCK;
-
- if ( (signed long)(task->lock_depth) < 0 )
- {
- printk("__lock_kernel(): %s/%d (nip %08lX) lock depth %x\n",
- task->comm,task->pid,task->thread.regs->nip,
- task->lock_depth);
- }
-#endif /* DEBUG_LOCKS */
-
- if (atomic_inc_return((atomic_t *) &task->lock_depth) != 1)
- return;
- /* mine! */
- 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 */
- }
-
- klock_info.akp = smp_processor_id();
- /* my kernel mode! mine!!! */
}
-void __unlock_kernel(struct task_struct *task)
-{
-#ifdef DEBUG_LOCKS
- if ((task->lock_depth == 0) || (klock_info.kernel_flag != KLOCK_HELD))
- {
- printk("__unlock_kernel(): %s/%d (nip %08lX) "
- "lock depth %x flags %lx\n",
- task->comm,task->pid,task->thread.regs->nip,
- task->lock_depth, klock_info.kernel_flag);
- klock_info.akp = NO_PROC_ID;
- klock_info.kernel_flag = 0;
- return;
- }
-#endif /* DEBUG_LOCKS */
- 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();
- }
-}
-
-void reacquire_kernel_lock(struct task_struct *task, int cpu,int depth)
-{
- if (depth)
- {
- __cli();
- __lock_kernel(task);
- task->lock_depth = depth;
- __sti();
- }
-}
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)