Hi
In s390's spin_lock_irqsave, interrupts remain disabled while spinning.
In other architectures like x86 and powerpc, interrupts are re-enabled
while spinning
if IRQ is not masked before spin_lock_irqsave is called.
The following patch re-enables interrupts through local_irq_restore while
spinning
for a lock acquisition. This can improve system response.
Comments?
Thanks.
Signed-off-by :Hisashi Hifumi <hifumi.hisashi@xxxxxxxxxxxxx>
diff -Nrup linux-2.6.24-rc8.org/arch/s390/lib/spinlock.c
linux-2.6.24-rc8/arch/s390/lib/spinlock.c
--- linux-2.6.24-rc8.org/arch/s390/lib/spinlock.c 2007-10-10
05:31:38.000000000 +0900
+++ linux-2.6.24-rc8/arch/s390/lib/spinlock.c 2008-01-21 19:20:43.000000000 +0900
@@ -61,6 +61,32 @@ void _raw_spin_lock_wait(raw_spinlock_t
}
EXPORT_SYMBOL(_raw_spin_lock_wait);
+void _raw_spin_lock_wait_flags(raw_spinlock_t *lp,
+ unsigned int pc, unsigned long flags)
+{
+ int count = spin_retry;
+ unsigned int cpu = ~smp_processor_id();
+
+ local_irq_restore(flags);
+ while (1) {
+ if (count-- <= 0) {
+ unsigned int owner = lp->owner_cpu;
+ if (owner != 0)
+ _raw_yield_cpu(~owner);
+ count = spin_retry;
+ }
+ if (__raw_spin_is_locked(lp))
+ continue;
+ local_irq_disable();
+ if (_raw_compare_and_swap(&lp->owner_cpu, 0, cpu) == 0) {
+ lp->owner_pc = pc;
+ return;
+ }
+ local_irq_restore(flags);
+ }
+}
+EXPORT_SYMBOL(_raw_spin_lock_wait_flags);
+
int _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
{
unsigned int cpu = ~smp_processor_id();
diff -Nrup linux-2.6.24-rc8.org/include/asm-s390/spinlock.h
linux-2.6.24-rc8/include/asm-s390/spinlock.h
--- linux-2.6.24-rc8.org/include/asm-s390/spinlock.h 2007-10-10
05:31:38.000000000 +0900
+++ linux-2.6.24-rc8/include/asm-s390/spinlock.h 2008-01-21
19:20:43.000000000 +0900
@@ -53,12 +53,13 @@ _raw_compare_and_swap(volatile unsigned
*/
#define __raw_spin_is_locked(x) ((x)->owner_cpu != 0)
-#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
#define __raw_spin_unlock_wait(lock) \
do { while (__raw_spin_is_locked(lock)) \
_raw_spin_relax(lock); } while (0)
extern void _raw_spin_lock_wait(raw_spinlock_t *, unsigned int pc);
+extern void _raw_spin_lock_wait_flags(raw_spinlock_t *,
+ unsigned int pc, unsigned long flags);
extern int _raw_spin_trylock_retry(raw_spinlock_t *, unsigned int pc);
extern void _raw_spin_relax(raw_spinlock_t *lock);
@@ -75,6 +76,19 @@ static inline void __raw_spin_lock(raw_s
_raw_spin_lock_wait(lp, pc);
}
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lp, unsigned long
flags)
+{
+ unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
+ int old;
+
+ old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id());
+ if (likely(old == 0)) {
+ lp->owner_pc = pc;
+ return;
+ }
+ _raw_spin_lock_wait_flags(lp, pc, flags);
+}
+
static inline int __raw_spin_trylock(raw_spinlock_t *lp)
{
unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
-
To unsubscribe from this list: send the line "unsubscribe linux-s390" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html