locks.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 207 行
C
207 行
/* * Locks for smp ppc * * Written by Cort Dougan (cort@cs.nmt.edu) */#include <linux/config.h>#include <linux/sched.h>#include <linux/spinlock.h>#include <linux/module.h>#include <asm/ppc_asm.h>#include <asm/smp.h>#ifdef CONFIG_DEBUG_SPINLOCK#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 inline 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" PPC405_ERR77(0,%1)" stwcx. %2,0,%1\n\ bne- 1b\n\ isync\n\2:" : "=&r"(ret) : "r"(lock), "r"(1) : "cr0", "memory"); return ret;}void _raw_spin_lock(spinlock_t *lock){ int cpu = smp_processor_id(); unsigned int stuck = INIT_STUCK; while (__spin_trylock(&lock->lock)) { 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);*/ } } } lock->owner_pc = (unsigned long)__builtin_return_address(0); lock->owner_cpu = cpu;}EXPORT_SYMBOL(_raw_spin_lock);int _raw_spin_trylock(spinlock_t *lock){ if (__spin_trylock(&lock->lock)) return 0; lock->owner_cpu = smp_processor_id(); lock->owner_pc = (unsigned long)__builtin_return_address(0); return 1;}EXPORT_SYMBOL(_raw_spin_trylock);void _raw_spin_unlock(spinlock_t *lp){ 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), current->comm, current->pid); if ( lp->owner_cpu != smp_processor_id() ) 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); lp->owner_pc = lp->owner_cpu = 0; wmb(); lp->lock = 0;}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 */void _raw_read_lock(rwlock_t *rw){ unsigned long stuck = INIT_STUCK; int cpu = smp_processor_id();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); 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", current->comm,current->pid,current->thread.regs->nip, rw->lock); wmb(); atomic_dec((atomic_t *) &(rw)->lock);}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); stuck = INIT_STUCK; } barrier(); } goto again; } wmb();}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 */ 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;}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", current->comm,current->pid,current->thread.regs->nip, rw->lock); wmb(); clear_bit(31,&(rw)->lock);}EXPORT_SYMBOL(_raw_write_unlock);#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?