|
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)
|