Commit f8eca41f authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Ingo Molnar

xen: measure how long spinlocks spend blocking

Measure how long spinlocks spend blocked.  Also rename some fields to
be more consistent.
Signed-off-by: default avatarJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Acked-by: default avatarJan Beulich <jbeulich@novell.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 1e696f63
...@@ -29,12 +29,14 @@ static struct xen_spinlock_stats ...@@ -29,12 +29,14 @@ static struct xen_spinlock_stats
u32 released_slow; u32 released_slow;
u32 released_slow_kicked; u32 released_slow_kicked;
#define HISTO_BUCKETS 20 #define HISTO_BUCKETS 30
u32 histo_spin_fast[HISTO_BUCKETS+1]; u32 histo_spin_total[HISTO_BUCKETS+1];
u32 histo_spin[HISTO_BUCKETS+1]; u32 histo_spin_spinning[HISTO_BUCKETS+1];
u32 histo_spin_blocked[HISTO_BUCKETS+1];
u64 spinning_time;
u64 total_time; u64 time_total;
u64 time_spinning;
u64 time_blocked;
} spinlock_stats; } spinlock_stats;
static u8 zero_stats; static u8 zero_stats;
...@@ -70,20 +72,28 @@ static void __spin_time_accum(u64 delta, u32 *array) ...@@ -70,20 +72,28 @@ static void __spin_time_accum(u64 delta, u32 *array)
array[HISTO_BUCKETS]++; array[HISTO_BUCKETS]++;
} }
static inline void spin_time_accum_fast(u64 start) static inline void spin_time_accum_spinning(u64 start)
{
u32 delta = xen_clocksource_read() - start;
__spin_time_accum(delta, spinlock_stats.histo_spin_spinning);
spinlock_stats.time_spinning += delta;
}
static inline void spin_time_accum_total(u64 start)
{ {
u32 delta = xen_clocksource_read() - start; u32 delta = xen_clocksource_read() - start;
__spin_time_accum(delta, spinlock_stats.histo_spin_fast); __spin_time_accum(delta, spinlock_stats.histo_spin_total);
spinlock_stats.spinning_time += delta; spinlock_stats.time_total += delta;
} }
static inline void spin_time_accum(u64 start) static inline void spin_time_accum_blocked(u64 start)
{ {
u32 delta = xen_clocksource_read() - start; u32 delta = xen_clocksource_read() - start;
__spin_time_accum(delta, spinlock_stats.histo_spin); __spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
spinlock_stats.total_time += delta; spinlock_stats.time_blocked += delta;
} }
#else /* !CONFIG_XEN_DEBUG_FS */ #else /* !CONFIG_XEN_DEBUG_FS */
#define TIMEOUT (1 << 10) #define TIMEOUT (1 << 10)
...@@ -94,10 +104,13 @@ static inline u64 spin_time_start(void) ...@@ -94,10 +104,13 @@ static inline u64 spin_time_start(void)
return 0; return 0;
} }
static inline void spin_time_accum_fast(u64 start) static inline void spin_time_accum_total(u64 start)
{
}
static inline void spin_time_accum_spinning(u64 start)
{ {
} }
static inline void spin_time_accum(u64 start) static inline void spin_time_accum_blocked(u64 start)
{ {
} }
#endif /* CONFIG_XEN_DEBUG_FS */ #endif /* CONFIG_XEN_DEBUG_FS */
...@@ -175,11 +188,14 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl ...@@ -175,11 +188,14 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl
int irq = __get_cpu_var(lock_kicker_irq); int irq = __get_cpu_var(lock_kicker_irq);
int ret; int ret;
unsigned long flags; unsigned long flags;
u64 start;
/* If kicker interrupts not initialized yet, just spin */ /* If kicker interrupts not initialized yet, just spin */
if (irq == -1) if (irq == -1)
return 0; return 0;
start = spin_time_start();
/* announce we're spinning */ /* announce we're spinning */
prev = spinning_lock(xl); prev = spinning_lock(xl);
...@@ -230,6 +246,8 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl ...@@ -230,6 +246,8 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl
out: out:
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
unspinning_lock(xl, prev); unspinning_lock(xl, prev);
spin_time_accum_blocked(start);
return ret; return ret;
} }
...@@ -262,12 +280,12 @@ static inline void __xen_spin_lock(struct raw_spinlock *lock, bool irq_enable) ...@@ -262,12 +280,12 @@ static inline void __xen_spin_lock(struct raw_spinlock *lock, bool irq_enable)
: "1" (1) : "1" (1)
: "memory"); : "memory");
spin_time_accum_fast(start_spin_fast); spin_time_accum_spinning(start_spin_fast);
} while (unlikely(oldval != 0 && } while (unlikely(oldval != 0 &&
(TIMEOUT == ~0 || !xen_spin_lock_slow(lock, irq_enable)))); (TIMEOUT == ~0 || !xen_spin_lock_slow(lock, irq_enable))));
spin_time_accum(start_spin); spin_time_accum_total(start_spin);
} }
static void xen_spin_lock(struct raw_spinlock *lock) static void xen_spin_lock(struct raw_spinlock *lock)
...@@ -385,14 +403,18 @@ static int __init xen_spinlock_debugfs(void) ...@@ -385,14 +403,18 @@ static int __init xen_spinlock_debugfs(void)
&spinlock_stats.released_slow_kicked); &spinlock_stats.released_slow_kicked);
debugfs_create_u64("time_spinning", 0444, d_spin_debug, debugfs_create_u64("time_spinning", 0444, d_spin_debug,
&spinlock_stats.spinning_time); &spinlock_stats.time_spinning);
debugfs_create_u64("time_blocked", 0444, d_spin_debug,
&spinlock_stats.time_blocked);
debugfs_create_u64("time_total", 0444, d_spin_debug, debugfs_create_u64("time_total", 0444, d_spin_debug,
&spinlock_stats.total_time); &spinlock_stats.time_total);
xen_debugfs_create_u32_array("histo_total", 0444, d_spin_debug, xen_debugfs_create_u32_array("histo_total", 0444, d_spin_debug,
spinlock_stats.histo_spin, HISTO_BUCKETS + 1); spinlock_stats.histo_spin_total, HISTO_BUCKETS + 1);
xen_debugfs_create_u32_array("histo_spinning", 0444, d_spin_debug, xen_debugfs_create_u32_array("histo_spinning", 0444, d_spin_debug,
spinlock_stats.histo_spin_fast, HISTO_BUCKETS + 1); spinlock_stats.histo_spin_spinning, HISTO_BUCKETS + 1);
xen_debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment