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
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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