[parisc-linux-cvs] linux-2.6 jejb
James Bottomley
James.Bottomley at SteelEye.com
Sun Aug 15 08:20:55 MDT 2004
On Sun, 2004-08-15 at 10:17, James Bottomley wrote:
> CVSROOT: /var/cvs
> Module name: linux-2.6
> Changes by: jejb 04/08/15 08:17:39
>
> Modified files:
> . : Makefile
> arch/parisc/lib: bitops.c
> include/asm-parisc: atomic.h bitops.h spinlock.h system.h
>
> Log message:
> Fix SMP f_list corruption problem.
>
> This was rather subtle. It turns out that gcc was doing a small
> amount of reordering around the file_lock because it doesn't see our
> spinlock implementation as being a barrier. To fix this I
>
> - Added the appropriate barriers to all the spinlocks.
> - Removed the atomic opencoded spinlock and redid it as a proper one.
>
> SMP now seems stable on a 2xA500 and has survived a 10 hour 35 loop
> make -j 4 kernel compile without showing any problems (previously, it
> usually fell over in the first loop).
Index: arch/parisc/lib/bitops.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/bitops.c,v
retrieving revision 1.3
diff -u -r1.3 bitops.c
--- arch/parisc/lib/bitops.c 28 Jul 2004 16:57:53 -0000 1.3
+++ arch/parisc/lib/bitops.c 15 Aug 2004 14:13:12 -0000
@@ -13,8 +13,8 @@
#include <asm/atomic.h>
#ifdef CONFIG_SMP
-atomic_lock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
- [0 ... (ATOMIC_HASH_SIZE-1)] = (atomic_lock_t) { { 1, 1, 1, 1 } }
+spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
+ [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
};
#endif
@@ -23,10 +23,10 @@
{
unsigned long temp, flags;
- atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_lock_irqsave(ptr, flags);
temp = *ptr;
*ptr = x;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_unlock_irqrestore(ptr, flags);
return temp;
}
#endif
@@ -36,10 +36,10 @@
unsigned long flags;
long temp;
- atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_lock_irqsave(ptr, flags);
temp = (long) *ptr; /* XXX - sign extension wanted? */
*ptr = x;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_unlock_irqrestore(ptr, flags);
return (unsigned long)temp;
}
@@ -49,10 +49,10 @@
unsigned long flags;
long temp;
- atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_lock_irqsave(ptr, flags);
temp = (long) *ptr; /* XXX - sign extension wanted? */
*ptr = x;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_unlock_irqrestore(ptr, flags);
return (unsigned long)temp;
}
@@ -63,10 +63,10 @@
unsigned long flags;
unsigned long prev;
- atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_lock_irqsave(ptr, flags);
if ((prev = *ptr) == old)
*ptr = new;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_unlock_irqrestore(ptr, flags);
return prev;
}
#endif
@@ -76,9 +76,9 @@
unsigned long flags;
unsigned int prev;
- atomic_spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_lock_irqsave(ptr, flags);
if ((prev = *ptr) == old)
*ptr = new;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+ _atomic_spin_unlock_irqrestore(ptr, flags);
return (unsigned long)prev;
}
Index: include/asm-parisc/atomic.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/atomic.h,v
retrieving revision 1.8
diff -u -r1.8 atomic.h
--- include/asm-parisc/atomic.h 23 May 2004 23:53:01 -0000 1.8
+++ include/asm-parisc/atomic.h 15 Aug 2004 14:13:22 -0000
@@ -2,7 +2,7 @@
#define _ASM_PARISC_ATOMIC_H_
#include <linux/config.h>
-#include <asm/system.h>
+#include <asm/spinlock.h>
/* Copyright (C) 2000 Philipp Rumpf <prumpf at tux.org>. */
/*
@@ -16,8 +16,6 @@
#ifdef CONFIG_SMP
#include <asm/cache.h> /* we use L1_CACHE_BYTES */
-typedef spinlock_t atomic_lock_t;
-
/* Use an array of spinlocks for our atomic_ts.
* Hash function to index into a different SPINLOCK.
* Since "a" is usually an address, use one spinlock per cacheline.
@@ -25,37 +23,28 @@
# define ATOMIC_HASH_SIZE 4
# define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))
-extern atomic_lock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
+extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
-static inline void atomic_spin_lock(atomic_lock_t *a)
-{
- while (__ldcw(a) == 0)
- while (a->lock[0] == 0);
-}
+/* Can't use _raw_spin_lock_irq because of #include problems, so
+ * this is the substitute */
+#define _atomic_spin_lock_irqsave(l,f) do { \
+ spinlock_t *s = ATOMIC_HASH(l); \
+ local_irq_save(f); \
+ _raw_spin_lock(s); \
+} while(0)
+
+#define _atomic_spin_unlock_irqrestore(l,f) do { \
+ spinlock_t *s = ATOMIC_HASH(l); \
+ _raw_spin_unlock(s); \
+ local_irq_restore(f); \
+} while(0)
-static inline void atomic_spin_unlock(atomic_lock_t *a)
-{
- a->lock[0] = 1;
-}
#else
# define ATOMIC_HASH_SIZE 1
# define ATOMIC_HASH(a) (0)
-# define atomic_spin_lock(x) (void)(x)
-# define atomic_spin_unlock(x) do { } while(0)
#endif
-/* copied from <linux/spinlock.h> and modified */
-#define atomic_spin_lock_irqsave(lock, flags) do { \
- local_irq_save(flags); \
- atomic_spin_lock(lock); \
-} while (0)
-
-#define atomic_spin_unlock_irqrestore(lock, flags) do { \
- atomic_spin_unlock(lock); \
- local_irq_restore(flags); \
-} while (0)
-
/* Note that we need not lock read accesses - aligned word writes/reads
* are atomic, so a reader never sees unconsistent values.
*
@@ -150,22 +139,22 @@
{
int ret;
unsigned long flags;
- atomic_spin_lock_irqsave(ATOMIC_HASH(v), flags);
+ _atomic_spin_lock_irqsave(v, flags);
ret = (v->counter += i);
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
+ _atomic_spin_unlock_irqrestore(v, flags);
return ret;
}
static __inline__ void atomic_set(atomic_t *v, int i)
{
unsigned long flags;
- atomic_spin_lock_irqsave(ATOMIC_HASH(v), flags);
+ _atomic_spin_lock_irqsave(v, flags);
v->counter = i;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
+ _atomic_spin_unlock_irqrestore(v, flags);
}
static __inline__ int atomic_read(const atomic_t *v)
Index: include/asm-parisc/bitops.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/bitops.h,v
retrieving revision 1.12
diff -u -r1.12 bitops.h
--- include/asm-parisc/bitops.h 13 Jul 2004 05:36:36 -0000 1.12
+++ include/asm-parisc/bitops.h 15 Aug 2004 14:13:22 -0000
@@ -38,9 +38,9 @@
addr += (nr >> SHIFT_PER_LONG);
mask = 1L << CHOP_SHIFTCOUNT(nr);
- atomic_spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ _atomic_spin_lock_irqsave(addr, flags);
*addr |= mask;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ _atomic_spin_unlock_irqrestore(addr, flags);
}
static __inline__ void __set_bit(int nr, volatile unsigned long * address)
@@ -61,9 +61,9 @@
addr += (nr >> SHIFT_PER_LONG);
mask = 1L << CHOP_SHIFTCOUNT(nr);
- atomic_spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ _atomic_spin_lock_irqsave(addr, flags);
*addr &= ~mask;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ _atomic_spin_unlock_irqrestore(addr, flags);
}
static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long * address)
@@ -84,9 +84,9 @@
addr += (nr >> SHIFT_PER_LONG);
mask = 1L << CHOP_SHIFTCOUNT(nr);
- atomic_spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ _atomic_spin_lock_irqsave(addr, flags);
*addr ^= mask;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ _atomic_spin_unlock_irqrestore(addr, flags);
}
static __inline__ void __change_bit(int nr, volatile unsigned long * address)
@@ -108,10 +108,10 @@
addr += (nr >> SHIFT_PER_LONG);
mask = 1L << CHOP_SHIFTCOUNT(nr);
- atomic_spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ _atomic_spin_lock_irqsave(addr, flags);
oldbit = (*addr & mask) ? 1 : 0;
*addr |= mask;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ _atomic_spin_unlock_irqrestore(addr, flags);
return oldbit;
}
@@ -139,10 +139,10 @@
addr += (nr >> SHIFT_PER_LONG);
mask = 1L << CHOP_SHIFTCOUNT(nr);
- atomic_spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ _atomic_spin_lock_irqsave(addr, flags);
oldbit = (*addr & mask) ? 1 : 0;
*addr &= ~mask;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ _atomic_spin_unlock_irqrestore(addr, flags);
return oldbit;
}
@@ -170,10 +170,10 @@
addr += (nr >> SHIFT_PER_LONG);
mask = 1L << CHOP_SHIFTCOUNT(nr);
- atomic_spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ _atomic_spin_lock_irqsave(addr, flags);
oldbit = (*addr & mask) ? 1 : 0;
*addr ^= mask;
- atomic_spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ _atomic_spin_unlock_irqrestore(addr, flags);
return oldbit;
}
Index: include/asm-parisc/spinlock.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/spinlock.h,v
retrieving revision 1.5
diff -u -r1.5 spinlock.h
--- include/asm-parisc/spinlock.h 8 Jul 2004 17:16:21 -0000 1.5
+++ include/asm-parisc/spinlock.h 15 Aug 2004 14:13:22 -0000
@@ -27,21 +27,35 @@
static inline void _raw_spin_lock(spinlock_t *x)
{
- volatile unsigned int *a = __ldcw_align(x);
+ volatile unsigned int *a;
+
+ mb();
+ a = __ldcw_align(x);
while (__ldcw(a) == 0)
while (*a == 0);
+ mb();
}
static inline void _raw_spin_unlock(spinlock_t *x)
{
- volatile unsigned int *a = __ldcw_align(x);
+ volatile unsigned int *a;
+ mb();
+ a = __ldcw_align(x);
*a = 1;
+ mb();
}
static inline int _raw_spin_trylock(spinlock_t *x)
{
- volatile unsigned int *a = __ldcw_align(x);
- return __ldcw(a) != 0;
+ volatile unsigned int *a;
+ int ret;
+
+ mb();
+ a = __ldcw_align(x);
+ ret = __ldcw(a) != 0;
+ mb();
+
+ return ret;
}
#define spin_lock_own(LOCK, LOCATION) ((void)0)
Index: include/asm-parisc/system.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/system.h,v
retrieving revision 1.4
diff -u -r1.4 system.h
--- include/asm-parisc/system.h 1 Jul 2004 18:30:37 -0000 1.4
+++ include/asm-parisc/system.h 15 Aug 2004 14:13:22 -0000
@@ -154,7 +154,7 @@
for the semaphore. */
#define __PA_LDCW_ALIGNMENT 16
#define __ldcw_align(a) ({ \
- unsigned long __ret = (unsigned long) a; \
+ unsigned long __ret = (unsigned long) &a->lock[0]; \
__ret = (__ret + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); \
(volatile unsigned int *) __ret; \
})
More information about the parisc-linux-cvs
mailing list