From: Andy P. <at...@us...> - 2002-04-10 18:40:48
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/ppc/lib In directory usw-pr-cvs1:/tmp/cvs-serv25860/ppc/lib Modified Files: Makefile checksum.S locks.c strcase.c string.S Added Files: dec_and_lock.c Log Message: synch 2.4.15 commit 43 --- NEW FILE --- #include <linux/module.h> #include <linux/spinlock.h> #include <asm/atomic.h> #include <asm/system.h> /* * This is an implementation of the notion of "decrement a * reference count, and return locked if it decremented to zero". * * This implementation can be used on any architecture that * has a cmpxchg, and where atomic->value is an int holding * the value of the atomic (i.e. the high bits aren't used * for a lock or anything like that). * * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h * if spinlocks are empty and thus atomic_dec_and_lock is defined * to be atomic_dec_and_test - in that case we don't need it * defined here as well. */ #ifndef ATOMIC_DEC_AND_LOCK int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; int newcount; for (;;) { counter = atomic_read(atomic); newcount = counter - 1; if (!newcount) break; /* do it the slow way */ newcount = cmpxchg(&atomic->counter, counter, newcount); if (newcount == counter) return 0; } spin_lock(lock); if (atomic_dec_and_test(atomic)) return 1; spin_unlock(lock); return 0; } EXPORT_SYMBOL(atomic_dec_and_lock); #endif /* ATOMIC_DEC_AND_LOCK */ Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/ppc/lib/Makefile,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- Makefile 25 Feb 2001 23:15:18 -0000 1.1.1.2 +++ Makefile 10 Apr 2002 15:04:10 -0000 1.2 @@ -1,13 +1,16 @@ +# BK Id: SCCS/s.Makefile 1.10 11/08/01 07:57:40 paulus +# # # Makefile for ppc-specific library files.. # -.S.o: - $(CC) $(AFLAGS) -c $< -o $*.o +USE_STANDARD_AS_RULE := true O_TARGET := lib.o -obj-y := checksum.o string.o strcase.o +export-objs := dec_and_lock.o + +obj-y := checksum.o string.o strcase.o dec_and_lock.o obj-$(CONFIG_SMP) += locks.o Index: checksum.S =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/ppc/lib/checksum.S,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- checksum.S 14 Jan 2001 19:31:36 -0000 1.1.1.1 +++ checksum.S 10 Apr 2002 15:04:10 -0000 1.2 @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.checksum.S 1.8 08/20/01 22:09:34 paulus + */ +/* * This file contains assembly-language implementations * of IP-style 1's complement checksum routines. * @@ -119,12 +122,30 @@ addc r0,r0,r6 srwi. r6,r5,2 /* # words to do */ beq 3f -1: mtctr r6 -82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */ -92: stwu r6,4(r4) /* be unnecessary to unroll this loop */ +1: srwi. r6,r5,4 /* # groups of 4 words to do */ + beq 10f + mtctr r6 +71: lwz r6,4(r3) +72: lwz r9,8(r3) +73: lwz r10,12(r3) +74: lwzu r11,16(r3) adde r0,r0,r6 +75: stw r6,4(r4) + adde r0,r0,r9 +76: stw r9,8(r4) + adde r0,r0,r10 +77: stw r10,12(r4) + adde r0,r0,r11 +78: stwu r11,16(r4) + bdnz 71b +10: rlwinm. r6,r5,30,30,31 /* # words left to do */ + beq 13f + mtctr r6 +82: lwzu r9,4(r3) +92: stwu r9,4(r4) + adde r0,r0,r9 bdnz 82b - andi. r5,r5,3 +13: andi. r5,r5,3 3: cmpi 0,r5,2 blt+ 4f 83: lhz r6,4(r3) @@ -145,12 +166,16 @@ /* These shouldn't go in the fixup section, since that would cause the ex_table addresses to get out of order. */ +src_error_4: + mfctr r6 /* update # bytes remaining from ctr */ + rlwimi r5,r6,4,0,27 + b 79f src_error_1: li r6,0 subi r5,r5,2 95: sth r6,4(r4) addi r4,r4,2 - srwi. r6,r5,2 +79: srwi. r6,r5,2 beq 3f mtctr r6 src_error_2: @@ -184,6 +209,14 @@ .section __ex_table,"a" .long 81b,src_error_1 .long 91b,dst_error + .long 71b,src_error_4 + .long 72b,src_error_4 + .long 73b,src_error_4 + .long 74b,src_error_4 + .long 75b,dst_error + .long 76b,dst_error + .long 77b,dst_error + .long 78b,dst_error .long 82b,src_error_2 .long 92b,dst_error .long 83b,src_error_3 Index: locks.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/ppc/lib/locks.c,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- locks.c 25 Feb 2001 23:15:18 -0000 1.1.1.2 +++ locks.c 10 Apr 2002 15:04:10 -0000 1.2 @@ -1,6 +1,7 @@ /* - * $Id$ - * + * BK Id: SCCS/s.locks.c 1.11 08/19/01 22:27:32 paulus + */ +/* * Locks for smp ppc * * Written by Cort Dougan (co...@cs...) @@ -15,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; @@ -52,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), @@ -65,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. @@ -79,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 */ { @@ -95,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; @@ -111,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; @@ -154,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; @@ -171,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 Index: strcase.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/ppc/lib/strcase.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- strcase.c 14 Jan 2001 19:31:36 -0000 1.1.1.1 +++ strcase.c 10 Apr 2002 15:04:10 -0000 1.2 @@ -1,3 +1,6 @@ +/* + * BK Id: SCCS/s.strcase.c 1.5 05/17/01 18:14:22 cort + */ #include <linux/ctype.h> int strcasecmp(const char *s1, const char *s2) Index: string.S =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/ppc/lib/string.S,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- string.S 14 Jan 2001 19:31:35 -0000 1.1.1.1 +++ string.S 10 Apr 2002 15:04:10 -0000 1.2 @@ -1,4 +1,7 @@ /* + * BK Id: SCCS/s.string.S 1.9 10/25/01 10:08:51 trini + */ +/* * String handling functions for PowerPC. * * Copyright (C) 1996 Paul Mackerras. @@ -11,22 +14,9 @@ #include "../kernel/ppc_asm.tmpl" #include <linux/config.h> #include <asm/processor.h> +#include <asm/cache.h> #include <asm/errno.h> -#if defined(CONFIG_4xx) || defined(CONFIG_8xx) -#define CACHE_LINE_SIZE 16 -#define LG_CACHE_LINE_SIZE 4 -#define MAX_COPY_PREFETCH 1 -#elif !defined(CONFIG_PPC64BRIDGE) -#define CACHE_LINE_SIZE 32 -#define LG_CACHE_LINE_SIZE 5 -#define MAX_COPY_PREFETCH 4 -#else -#define CACHE_LINE_SIZE 128 -#define LG_CACHE_LINE_SIZE 7 -#define MAX_COPY_PREFETCH 1 -#endif /* CONFIG_4xx || CONFIG_8xx */ - #define COPY_16_BYTES \ lwz r7,4(r4); \ lwz r8,8(r4); \ @@ -72,11 +62,13 @@ .long 8 ## n ## 5b,9 ## n ## 1b; \ .long 8 ## n ## 6b,9 ## n ## 1b; \ .long 8 ## n ## 7b,9 ## n ## 1b; \ -.text + .text + + .text -CACHELINE_BYTES = CACHE_LINE_SIZE -LG_CACHELINE_BYTES = LG_CACHE_LINE_SIZE -CACHELINE_MASK = (CACHE_LINE_SIZE-1) +CACHELINE_BYTES = L1_CACHE_LINE_SIZE +LG_CACHELINE_BYTES = LG_L1_CACHE_LINE_SIZE +CACHELINE_MASK = (L1_CACHE_LINE_SIZE-1) .globl strcpy strcpy: @@ -275,12 +267,12 @@ dcbz r11,r6 #endif COPY_16_BYTES -#if CACHE_LINE_SIZE >= 32 +#if L1_CACHE_LINE_SIZE >= 32 COPY_16_BYTES -#if CACHE_LINE_SIZE >= 64 +#if L1_CACHE_LINE_SIZE >= 64 COPY_16_BYTES COPY_16_BYTES -#if CACHE_LINE_SIZE >= 128 +#if L1_CACHE_LINE_SIZE >= 128 COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES @@ -453,23 +445,23 @@ #if !defined(CONFIG_8xx) /* Here we decide how far ahead to prefetch the source */ -#if MAX_COPY_PREFETCH > 1 +#if MAX_L1_COPY_PREFETCH > 1 /* Heuristically, for large transfers we prefetch - MAX_COPY_PREFETCH cachelines ahead. For small transfers + MAX_L1_COPY_PREFETCH cachelines ahead. For small transfers we prefetch 1 cacheline ahead. */ - cmpwi r0,MAX_COPY_PREFETCH + cmpwi r0,MAX_L1_COPY_PREFETCH li r7,1 li r3,4 ble 111f - li r7,MAX_COPY_PREFETCH + li r7,MAX_L1_COPY_PREFETCH 111: mtctr r7 112: dcbt r3,r4 addi r3,r3,CACHELINE_BYTES bdnz 112b -#else /* MAX_COPY_PREFETCH == 1 */ +#else /* MAX_L1_COPY_PREFETCH == 1 */ li r3,CACHELINE_BYTES + 4 dcbt r11,r4 -#endif /* MAX_COPY_PREFETCH */ +#endif /* MAX_L1_COPY_PREFETCH */ #endif /* CONFIG_8xx */ mtctr r0 @@ -489,12 +481,12 @@ .text /* the main body of the cacheline loop */ COPY_16_BYTES_WITHEX(0) -#if CACHE_LINE_SIZE >= 32 +#if L1_CACHE_LINE_SIZE >= 32 COPY_16_BYTES_WITHEX(1) -#if CACHE_LINE_SIZE >= 64 +#if L1_CACHE_LINE_SIZE >= 64 COPY_16_BYTES_WITHEX(2) COPY_16_BYTES_WITHEX(3) -#if CACHE_LINE_SIZE >= 128 +#if L1_CACHE_LINE_SIZE >= 128 COPY_16_BYTES_WITHEX(4) COPY_16_BYTES_WITHEX(5) COPY_16_BYTES_WITHEX(6) @@ -543,12 +535,12 @@ * 104f (if in read part) or 105f (if in write part), after updating r5 */ COPY_16_BYTES_EXCODE(0) -#if CACHE_LINE_SIZE >= 32 +#if L1_CACHE_LINE_SIZE >= 32 COPY_16_BYTES_EXCODE(1) -#if CACHE_LINE_SIZE >= 64 +#if L1_CACHE_LINE_SIZE >= 64 COPY_16_BYTES_EXCODE(2) COPY_16_BYTES_EXCODE(3) -#if CACHE_LINE_SIZE >= 128 +#if L1_CACHE_LINE_SIZE >= 128 COPY_16_BYTES_EXCODE(4) COPY_16_BYTES_EXCODE(5) COPY_16_BYTES_EXCODE(6) |