lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Fri, 26 Dec 2008 15:24:30 +0800 From: "Yang Xi" <yangxilkm@...il.com> To: "Peter Zijlstra" <a.p.zijlstra@...llo.nl> Cc: linux-kernel@...r.kernel.org, mingo@...e.hu, chyyuu <chyyuu@...il.com> Subject: Re: [PATCH 2.6.28-rc4]lock_stat: Add "con-hungry" to show that how many person-time fight for the ticket spinlock *Add max-hungry to capture the max value of the number of threads who fight on a ticket lock *For non-ticketlock implementation, spin_nr_contended(lock) is (spin_is_contended(lock) ? 1 : 0), which means "con-hungry" represent how many times there are more than two threads waiting for the spinlock to be free. Because the lock-stat and lock-dep is so heavy, this statistic result is not very accurate :( Here is the patch. Signed-off-by: Yangxi <hiyangxi@...il.com> --- arch/x86/Kconfig | 1 + arch/x86/include/asm/spinlock.h | 7 +++++++ include/linux/lockdep.h | 5 ++++- include/linux/spinlock.h | 6 ++++++ kernel/lockdep.c | 24 +++++++++++++++++++++--- kernel/lockdep_proc.c | 10 +++++++--- lib/Kconfig.debug | 3 +++ lib/spinlock_debug.c | 1 + 8 files changed, 50 insertions(+), 7 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4cf0ab1..20fee72 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -34,6 +34,7 @@ config X86 select HAVE_ARCH_TRACEHOOK select HAVE_GENERIC_DMA_COHERENT if X86_32 select HAVE_EFFICIENT_UNALIGNED_ACCESS + select HAVE_TICKET_SPINLOCK config ARCH_DEFCONFIG string diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index d17c919..da9cffc 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h @@ -172,6 +172,13 @@ static inline int __ticket_spin_is_contended(raw_spinlock_t *lock) return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) > 1; } +static inline int __ticket_spin_nr_contended(raw_spinlock_t *lock) +{ + int tmp = ACCESS_ONCE(lock->slock); + + return (((tmp >> TICKET_SHIFT) - tmp) & ((1 << TICKET_SHIFT) - 1)) + 1; +} + #ifdef CONFIG_PARAVIRT /* * Define virtualization-friendly old-style lock byte lock, for use in diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 331e5f1..c45efc2 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -136,6 +136,8 @@ enum bounce_type { bounce_acquired_read, bounce_contended_write, bounce_contended_read, + bounce_hungry, + bounce_max_hungry, nr_bounce_types, bounce_acquired = bounce_acquired_write, @@ -164,7 +166,8 @@ struct lockdep_map { struct lock_class *class_cache; const char *name; #ifdef CONFIG_LOCK_STAT - int cpu; + unsigned int cpu:31; + unsigned int isticketspinlock:1; #endif }; diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index e0c0fcc..c6be4bc 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -127,6 +127,12 @@ do { \ #define spin_is_contended(lock) __raw_spin_is_contended(&(lock)->raw_lock) #endif +#ifdef CONFIG_HAVE_TICKET_SPINLOCK +#define spin_nr_contended(lock) __ticket_spin_nr_contended(&(lock)->raw_lock) +#else +#define spin_nr_contended(lock) (spin_is_contended(lock) ? 1 : 0) +#endif + /** * spin_unlock_wait - wait until the spinlock gets unlocked * @lock: the spinlock in question. diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 06e1571..8483e1e 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -191,8 +191,14 @@ struct lock_class_stats lock_stats(struct lock_class *class) lock_time_add(&pcs->read_holdtime, &stats.read_holdtime); lock_time_add(&pcs->write_holdtime, &stats.write_holdtime); - for (i = 0; i < ARRAY_SIZE(stats.bounces); i++) + for (i = 0; i < ARRAY_SIZE(stats.bounces); i++) { + if (i == bounce_max_hungry) { + if (stats.bounces[i] < pcs->bounces[i]) + stats.bounces[i] = pcs->bounces[i]; + continue; + } stats.bounces[i] += pcs->bounces[i]; + } } return stats; @@ -2588,7 +2594,6 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, if (check == 2 && !mark_irqflags(curr, hlock)) return 0; - /* mark it as used: */ if (!mark_lock(curr, hlock, LOCK_USED)) return 0; @@ -2623,7 +2628,6 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, if (!validate_chain(curr, lock, hlock, chain_head, chain_key)) return 0; - curr->curr_chain_key = chain_key; curr->lockdep_depth++; check_chain_key(curr); @@ -3000,6 +3004,13 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip) struct lock_class_stats *stats; unsigned int depth; int i, point; + spinlock_t *lock_ptr; + unsigned long hungry = 0; + + if (lock->isticketspinlock) { + lock_ptr = container_of(lock, spinlock_t, dep_map); + hungry = spin_nr_contended(lock_ptr); + } depth = curr->lockdep_depth; if (DEBUG_LOCKS_WARN_ON(!depth)) @@ -3030,9 +3041,16 @@ found_it: stats->contention_point[point]++; if (lock->cpu != smp_processor_id()) stats->bounces[bounce_contended + !!hlock->read]++; + stats->bounces[bounce_hungry] += hungry; + if (lock->isticketspinlock) { + if (stats->bounces[bounce_max_hungry] < hungry) + stats->bounces[bounce_max_hungry] = hungry; + } + put_lock_stats(stats); } + static void __lock_acquired(struct lockdep_map *lock) { diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index 20dbcbf..d5f94e5 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c @@ -535,6 +535,8 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) seq_printf(m, "%40s:", name); seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]); + seq_printf(m, "%14lu ", stats->bounces[bounce_hungry]); + seq_printf(m, "%14lu ", stats->bounces[bounce_max_hungry]); seq_lock_time(m, &stats->write_waittime); seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]); seq_lock_time(m, &stats->write_holdtime); @@ -583,11 +585,13 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) static void seq_header(struct seq_file *m) { seq_printf(m, "lock_stat version 0.2\n"); - seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); - seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " + seq_line(m, '-', 0, 40 + 1 + 12 * (14 + 1)); + seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s %14s %14s " "%14s %14s\n", "class name", "con-bounces", + "con-hungry", + "max-hungry", "contentions", "waittime-min", "waittime-max", @@ -597,7 +601,7 @@ static void seq_header(struct seq_file *m) "holdtime-min", "holdtime-max", "holdtime-total"); - seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); + seq_line(m, '-', 0, 40 + 1 + 12 * (14 + 1)); seq_printf(m, "\n"); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index b0f239e..b9eb62a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -318,6 +318,9 @@ config RT_MUTEX_TESTER help This option enables a rt-mutex tester. +config HAVE_TICKET_SPINLOCK + bool + config DEBUG_SPINLOCK bool "Spinlock and rw-lock debugging: basic checks" depends on DEBUG_KERNEL diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index 9c4b025..bba8d3e 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -27,6 +27,7 @@ void __spin_lock_init(spinlock_t *lock, const char *name, lock->magic = SPINLOCK_MAGIC; lock->owner = SPINLOCK_OWNER_INIT; lock->owner_cpu = -1; + lock->dep_map.isticketspinlock = 1; } EXPORT_SYMBOL(__spin_lock_init); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists