Messages in this thread Patch in this message | | | Date | Thu, 16 Sep 2004 16:03:51 -0700 (PDT) | From | Ray Bryant <> | Subject | [PATCH 1/3] lockmeter: fixed-up: lockmeter fixes for preempt case |
| |
Updated lockmeter-preempt-fix.patch.
Signed-off-by: Ray Bryant <raybry@sgi.com>
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@sgi.com 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |