2 * $Id: locks.c,v 1.24 1999/08/03 19:16:47 cort Exp $ 6 * Written by Cort Dougan (cort@cs.nmt.edu) 10 #include <linux/kernel.h> 11 #include <linux/sched.h> 12 #include <linux/delay.h> 13 #include <linux/spinlock.h> 14 #include <asm/processor.h> 15 #include <asm/system.h> 21 #define INIT_STUCK 200000000/*0xffffffff*/ 23 void_spin_lock(spinlock_t
*lock
) 25 int cpu
=smp_processor_id(); 27 unsigned int stuck
= INIT_STUCK
; 28 #endif/* DEBUG_LOCKS */ 29 while(__spin_trylock(&lock
->lock
)) { 32 printk("_spin_lock(%p) CPU#%d NIP %p" 33 " holder: cpu %ld pc %08lX\n", 34 lock
, cpu
,__builtin_return_address(0), 35 lock
->owner_cpu
,lock
->owner_pc
); 38 /*xchg_u32((void *)&lock->lock,0);*/ 40 #endif/* DEBUG_LOCKS */ 42 lock
->owner_pc
= (unsigned long)__builtin_return_address(0); 43 lock
->owner_cpu
= cpu
; 46 intspin_trylock(spinlock_t
*lock
) 48 if(__spin_trylock(&lock
->lock
)) 50 lock
->owner_cpu
=smp_processor_id(); 51 lock
->owner_pc
= (unsigned long)__builtin_return_address(0); 57 void_spin_unlock(spinlock_t
*lp
) 61 printk("_spin_unlock(%p): no lock cpu %d %s/%d\n", lp
, 62 smp_processor_id(),current
->comm
,current
->pid
); 63 if( lp
->owner_cpu
!=smp_processor_id() ) 64 printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n", 65 lp
,smp_processor_id(), (int)lp
->owner_cpu
, 66 lp
->owner_pc
,lp
->lock
); 67 #endif/* DEBUG_LOCKS */ 68 lp
->owner_pc
= lp
->owner_cpu
=0; 75 * Just like x86, implement read-write locks as a 32-bit counter 76 * with the high bit (sign) being the "write" bit. 79 void_read_lock(rwlock_t
*rw
) 82 unsigned long stuck
= INIT_STUCK
; 83 int cpu
=smp_processor_id(); 84 #endif/* DEBUG_LOCKS */ 87 /* get our read lock in there */ 89 atomic_inc((atomic_t
*) &(rw
)->lock
); 90 if( (signed long)((rw
)->lock
) <0)/* someone has a write lock */ 92 /* turn off our read lock */ 93 atomic_dec((atomic_t
*) &(rw
)->lock
); 94 /* wait for the write lock to go away */ 95 while((signed long)((rw
)->lock
) <0) 100 printk("_read_lock(%p) CPU#%d\n", rw
, cpu
); 103 #endif/* DEBUG_LOCKS */ 105 /* try to get the read lock again */ 111 void_read_unlock(rwlock_t
*rw
) 115 printk("_read_unlock(): %s/%d (nip %08lX) lock %lx\n", 116 current
->comm
,current
->pid
,current
->thread
.regs
->nip
, 118 #endif/* DEBUG_LOCKS */ 120 atomic_dec((atomic_t
*) &(rw
)->lock
); 124 void_write_lock(rwlock_t
*rw
) 127 unsigned long stuck
= INIT_STUCK
; 128 int cpu
=smp_processor_id(); 129 #endif/* DEBUG_LOCKS */ 133 if(test_and_set_bit(31,&(rw
)->lock
) )/* someone has a write lock */ 135 while( (rw
)->lock
& (1<<31) )/* wait for write lock */ 140 printk("write_lock(%p) CPU#%d lock %lx)\n", 144 #endif/* DEBUG_LOCKS */ 150 if( (rw
)->lock
& ~(1<<31))/* someone has a read lock */ 152 /* clear our write lock and wait for reads to go away */ 153 clear_bit(31,&(rw
)->lock
); 154 while( (rw
)->lock
& ~(1<<31) ) 159 printk("write_lock(%p) 2 CPU#%d lock %lx)\n", 163 #endif/* DEBUG_LOCKS */ 171 void_write_unlock(rwlock_t
*rw
) 174 if( !(rw
->lock
& (1<<31)) ) 175 printk("_write_lock(): %s/%d (nip %08lX) lock %lx\n", 176 current
->comm
,current
->pid
,current
->thread
.regs
->nip
, 178 #endif/* DEBUG_LOCKS */ 180 clear_bit(31,&(rw
)->lock
); 184 void__lock_kernel(struct task_struct
*task
) 187 unsigned long stuck
= INIT_STUCK
; 189 if( (signed long)(task
->lock_depth
) <0) 191 printk("__lock_kernel(): %s/%d (nip %08lX) lock depth %x\n", 192 task
->comm
,task
->pid
,task
->thread
.regs
->nip
, 195 #endif/* DEBUG_LOCKS */ 197 if(atomic_inc_return((atomic_t
*) &task
->lock_depth
) !=1) 200 while(__spin_trylock(&klock_info
.kernel_flag
)) { 203 printk("_lock_kernel() CPU#%d NIP %p\n", 205 __builtin_return_address(0)); 208 #endif/* DEBUG_LOCKS */ 211 klock_info
.akp
=smp_processor_id(); 212 /* my kernel mode! mine!!! */ 215 void__unlock_kernel(struct task_struct
*task
) 218 if((task
->lock_depth
==0) || (klock_info
.kernel_flag
!= KLOCK_HELD
)) 220 printk("__unlock_kernel(): %s/%d (nip %08lX) " 221 "lock depth %x flags %lx\n", 222 task
->comm
,task
->pid
,task
->thread
.regs
->nip
, 223 task
->lock_depth
, klock_info
.kernel_flag
); 224 klock_info
.akp
= NO_PROC_ID
; 225 klock_info
.kernel_flag
=0; 228 #endif/* DEBUG_LOCKS */ 229 if(atomic_dec_and_test((atomic_t
*) &task
->lock_depth
)) 232 klock_info
.akp
= NO_PROC_ID
; 234 klock_info
.kernel_flag
= KLOCK_CLEAR
; 239 voidreacquire_kernel_lock(struct task_struct
*task
,int cpu
,int depth
) 245 task
->lock_depth
= depth
;