[PATCH 1/3] lockmeter: fixed-up: lockmeter fixes for preempt case

From: Ray Bryant
Date: Thu Sep 16 2004 - 18:31:48 EST


Updated lockmeter-preempt-fix.patch.

Signed-off-by: Ray Bryant <raybry@xxxxxxx>

Index: linux-2.6.9-rc2-mm1/kernel/lockmeter.c
===================================================================
--- linux-2.6.9-rc2-mm1.orig/kernel/lockmeter.c 2004-09-16 11:03:05.000000000 -0700
+++ linux-2.6.9-rc2-mm1/kernel/lockmeter.c 2004-09-16 12:03:20.000000000 -0700
@@ -1236,18 +1236,58 @@
EXPORT_SYMBOL(_write_trylock);

#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
+/*
+ * This could be a long-held lock. If another CPU holds it for a long time,
+ * and that CPU is not asked to reschedule then *this* CPU will spin on the
+ * lock for a long time, even if *this* CPU is asked to reschedule.
+ *
+ * So what we do here, in the slow (contended) path is to spin on the lock by
+ * hand while permitting preemption.
+ *
+ * Called inside preempt_disable().
+ */
+static inline void __preempt_spin_lock(spinlock_t *lock, void *caller_pc)
+{
+ if (preempt_count() > 1) {
+ _metered_spin_lock(lock, caller_pc);
+ return;
+ }
+
+ do {
+ preempt_enable();
+ while (spin_is_locked(lock))
+ cpu_relax();
+ preempt_disable();
+ } while (!_metered_spin_trylock(lock, caller_pc));
+}
+
void __lockfunc _spin_lock(spinlock_t *lock)
{
preempt_disable();
if (unlikely(!_metered_spin_trylock(lock, __builtin_return_address(0))))
- __preempt_spin_lock(lock);
+ __preempt_spin_lock(lock, __builtin_return_address(0));
+}
+
+static inline void __preempt_write_lock(rwlock_t *lock, void *caller_pc)
+{
+ if (preempt_count() > 1) {
+ _metered_write_lock(lock, caller_pc);
+ return;
+ }
+
+ do {
+ preempt_enable();
+ while (rwlock_is_locked(lock))
+ cpu_relax();
+ preempt_disable();
+ } while (!_metered_write_trylock(lock,caller_pc));
}

void __lockfunc _write_lock(rwlock_t *lock)
{
preempt_disable();
if (unlikely(!_metered_write_trylock(lock, __builtin_return_address(0))))
- __preempt_write_lock(lock);
+ __preempt_write_lock(lock, __builtin_return_address(0));
}
#else
void __lockfunc _spin_lock(spinlock_t *lock)
@@ -1458,3 +1498,13 @@
return 0;
}
EXPORT_SYMBOL(_spin_trylock_bh);
+
+int in_lock_functions(unsigned long addr)
+{
+ /* Linker adds these: start and end of __lockfunc functions */
+ extern char __lock_text_start[], __lock_text_end[];
+
+ return addr >= (unsigned long)__lock_text_start
+ && addr < (unsigned long)__lock_text_end;
+}
+EXPORT_SYMBOL(in_lock_functions);

--
Best Regards,
Ray
-----------------------------------------------
Ray Bryant raybry@xxxxxxx
The box said: "Requires Windows 98 or better",
so I installed Linux.
-----------------------------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/