diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /arch/ppc/lib | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'arch/ppc/lib')
-rw-r--r-- | arch/ppc/lib/Makefile | 5 | ||||
-rw-r--r-- | arch/ppc/lib/checksum.S | 6 | ||||
-rw-r--r-- | arch/ppc/lib/locks.c | 195 | ||||
-rw-r--r-- | arch/ppc/lib/string.S | 1 |
4 files changed, 205 insertions, 2 deletions
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index 8b84ce2ae..4cc49de17 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile @@ -8,4 +8,9 @@ O_TARGET = lib.o O_OBJS = checksum.o string.o strcase.o +ifdef SMP +O_OBJS += locks.o +endif + + include $(TOPDIR)/Rules.make diff --git a/arch/ppc/lib/checksum.S b/arch/ppc/lib/checksum.S index 6c53d50ff..66a2e3aae 100644 --- a/arch/ppc/lib/checksum.S +++ b/arch/ppc/lib/checksum.S @@ -13,10 +13,11 @@ */ #include <linux/sys.h> +#include <asm/processor.h> #include <asm/errno.h> #include "../kernel/ppc_asm.tmpl" -_TEXT() + .text /* * ip_fast_csum(buf, len) -- Optimized for IP header @@ -140,7 +141,8 @@ _GLOBAL(csum_partial_copy_generic) 5: addze r3,r0 /* add in final carry */ blr -.section .fixup,"ax" +/* These shouldn't go in the fixup section, since that would + cause the ex_table addresses to get out of order. */ src_error_1: li r6,0 diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c new file mode 100644 index 000000000..5e2ceb889 --- /dev/null +++ b/arch/ppc/lib/locks.c @@ -0,0 +1,195 @@ +/* + * $Id: locks.c,v 1.7 1998/01/06 06:44:59 cort Exp $ + * + * Locks for smp ppc + * + * Written by Cort Dougan (cort@cs.nmt.edu) + */ + + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <asm/processor.h> +#include <asm/system.h> +#include <asm/spinlock.h> + +#define DEBUG_LOCKS 1 + +#undef INIT_STUCK +#define INIT_STUCK 10000 + +#undef STUCK +#define STUCK \ +if(!--stuck) { printk("spin_lock(%p) CPU#%d nip %08lx\n", lock, cpu, nip); stuck = INIT_STUCK; } + +void _spin_lock(spinlock_t *lock) +{ + unsigned long val, nip = (unsigned long)__builtin_return_address(0); + int cpu = smp_processor_id(); + int stuck = INIT_STUCK; + +again: + /* try expensive atomic load/store to get lock */ + __asm__ __volatile__( + "10: \n\t" + "lwarx %0,0,%1 \n\t" + "stwcx. %2,0,%1 \n\t" + "bne- 10b \n\t" + : "=r" (val) + : "r" (&(lock->lock)), "r" ( (cpu&3)|(nip&~3L) )); + if(val) { + /* try cheap load until it's free */ + while(lock->lock) { + STUCK; + barrier(); + } + goto again; + } +} + +void _spin_unlock(spinlock_t *lp) +{ + lp->lock = 0; +} + +#undef STUCK +#define STUCK \ +if(!--stuck) { printk("_read_lock(%p) CPU#%d\n", rw, cpu); stuck = INIT_STUCK; } + +/* + * Just like x86, implement read-write locks as a 32-bit counter + * with the high bit (sign) being the "write" bit. + * -- Cort + */ +void _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) + { + STUCK; + } + /* try to get the read lock again */ + goto again; + } +} + +void _read_unlock(rwlock_t *rw) +{ +#ifdef DEBUG_LOCKS + if ( rw->lock == 0 ) + { + if ( current) + printk("_read_unlock(): %s/%d (nip %08lX) lock %lx", + current->comm,current->pid,current->tss.regs->nip, + rw->lock); + else + printk("no current\n"); + } +#endif /* DEBUG_LOCKS */ + atomic_dec((atomic_t *) &(rw)->lock); +} + +#undef STUCK +#define STUCK \ +if(!--stuck) { printk("write_lock(%p) CPU#%d lock %lx)\n", rw, cpu,rw->lock); stuck = INIT_STUCK; } + +void _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 */ + { + STUCK; + } + 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) ) + { + STUCK; + } + goto again; + } +} + +void _write_unlock(rwlock_t *rw) +{ +#ifdef DEBUG_LOCKS + if ( !(rw->lock & (1<<31)) ) + { + if ( current) + printk("_write_lock(): %s/%d (nip %08lX) lock %lx", + current->comm,current->pid,current->tss.regs->nip, + rw->lock); + else + printk("no current\n"); + } +#endif /* DEBUG_LOCKS */ + clear_bit(31,&(rw)->lock); +} + +void __lock_kernel(struct task_struct *task) +{ +#ifdef DEBUG_LOCKS + if ( (signed long)(task->lock_depth) < 0 ) + { + printk("__lock_kernel(): %s/%d (nip %08lX) lock depth %x\n", + task->comm,task->pid,task->tss.regs->nip, + task->lock_depth); + } +#endif /* DEBUG_LOCKS */ + /* mine! */ + if ( atomic_inc_return((atomic_t *) &task->lock_depth) == 1 ) + 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 ) + { + printk("__unlock_kernel(): %s/%d (nip %08lX) lock depth %x\n", + task->comm,task->pid,task->tss.regs->nip, + task->lock_depth); + 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) ) + { + klock_info.akp = NO_PROC_ID; + klock_info.kernel_flag = 0; + } +} + +void reacquire_kernel_lock(struct task_struct *task, int cpu,int depth) +{ + if (depth) + { + __cli(); + __lock_kernel(task); + task->lock_depth = depth; + __sti(); + } +} + diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S index 96378dec1..c44868b7a 100644 --- a/arch/ppc/lib/string.S +++ b/arch/ppc/lib/string.S @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. */ #include "../kernel/ppc_asm.tmpl" +#include <asm/processor.h> #include <asm/errno.h> .globl strcpy |