@@ -44,8 +44,9 @@ config COVERAGE
If unsure, say N here.
-config LOCK_PROFILE
+config DEBUG_LOCK_PROFILE
bool "Lock Profiling"
+ select DEBUG_LOCKS
---help---
Lock profiling allows you to see how often locks are taken and blocked.
You can use serial console to print (and reset) using 'l' and 'L'
@@ -54,12 +54,6 @@ SECTIONS
*(.data.rel.ro)
*(.data.rel.ro.*)
-#ifdef CONFIG_LOCK_PROFILE
- . = ALIGN(POINTER_ALIGN);
- __lock_profile_start = .;
- *(.lockprofile.data)
- __lock_profile_end = .;
-#endif
. = ALIGN(POINTER_ALIGN);
__param_start = .;
*(.data.param)
@@ -173,6 +167,13 @@ SECTIONS
. = ALIGN(4);
*(.altinstr_replacement)
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
+ . = ALIGN(POINTER_ALIGN);
+ __lock_profile_start = .;
+ *(.lockprofile.data)
+ __lock_profile_end = .;
+#endif
+
*(.init.data)
*(.init.data.rel)
*(.init.data.rel.*)
@@ -305,7 +305,7 @@ struct domain *alloc_domain_struct(void)
#endif
-#ifndef CONFIG_LOCK_PROFILE
+#ifndef CONFIG_DEBUG_LOCK_PROFILE
BUILD_BUG_ON(sizeof(*d) > PAGE_SIZE);
#endif
d = alloc_xenheap_pages(order, MEMF_bits(bits));
@@ -128,12 +128,6 @@ SECTIONS
*(.ex_table.pre)
__stop___pre_ex_table = .;
-#ifdef CONFIG_LOCK_PROFILE
- . = ALIGN(POINTER_ALIGN);
- __lock_profile_start = .;
- *(.lockprofile.data)
- __lock_profile_end = .;
-#endif
. = ALIGN(POINTER_ALIGN);
__param_start = .;
*(.data.param)
@@ -251,6 +245,13 @@ SECTIONS
*(.altinstructions)
__alt_instructions_end = .;
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
+ . = ALIGN(POINTER_ALIGN);
+ __lock_profile_start = .;
+ *(.lockprofile.data)
+ __lock_profile_end = .;
+#endif
+
. = ALIGN(8);
__ctors_start = .;
*(.ctors)
@@ -62,7 +62,7 @@ static struct keyhandler {
KEYHANDLER('P', perfc_reset, "reset performance counters", 0),
#endif
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
KEYHANDLER('l', spinlock_profile_printall, "print lock profile info", 1),
KEYHANDLER('L', spinlock_profile_reset, "reset lock profile info", 0),
#endif
@@ -106,7 +106,7 @@ void spin_debug_disable(void)
#endif
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
#define LOCK_PROFILE_REL \
if (lock->profile) \
@@ -243,7 +243,7 @@ int _spin_trylock(spinlock_t *lock)
old.head_tail, new.head_tail) != old.head_tail )
return 0;
got_lock(&lock->debug);
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
if (lock->profile)
lock->profile->time_locked = NOW();
#endif
@@ -258,7 +258,7 @@ int _spin_trylock(spinlock_t *lock)
void _spin_barrier(spinlock_t *lock)
{
spinlock_tickets_t sample;
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
s_time_t block = NOW();
#endif
@@ -269,7 +269,7 @@ void _spin_barrier(spinlock_t *lock)
{
while ( observe_head(&lock->tickets) == sample.head )
arch_lock_relax();
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
if ( lock->profile )
{
lock->profile->time_block += NOW() - block;
@@ -327,7 +327,7 @@ void _spin_unlock_recursive(spinlock_t *lock)
}
}
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
struct lock_profile_anc {
struct lock_profile_qhead *head_q; /* first head of this type */
@@ -362,14 +362,19 @@ static void spinlock_profile_iterate(lock_profile_subfunc *sub, void *par)
static void spinlock_profile_print_elem(struct lock_profile *data,
int32_t type, int32_t idx, void *par)
{
- if ( type == LOCKPROF_TYPE_GLOBAL )
- printk("%s %s:\n", lock_profile_ancs[type].name, data->name);
+ struct spinlock *lock = data->lock;
+
+ printk("%s ", lock_profile_ancs[type].name);
+ if ( type != LOCKPROF_TYPE_GLOBAL )
+ printk("%d ", idx);
+ printk("%s: addr=%p, lockval=%08x, ", data->name, lock,
+ lock->tickets.head_tail);
+ if ( lock->debug.cpu == SPINLOCK_NO_CPU )
+ printk("not locked\n");
else
- printk("%s %d %s:\n", lock_profile_ancs[type].name, idx, data->name);
- printk(" lock:%12"PRId64"(%08X:%08X), block:%12"PRId64"(%08X:%08X)\n",
- data->lock_cnt, (u32)(data->time_hold >> 32), (u32)data->time_hold,
- data->block_cnt, (u32)(data->time_block >> 32),
- (u32)data->time_block);
+ printk("cpu=%d\n", lock->debug.cpu);
+ printk(" lock:%" PRId64 "(%" PRI_stime "), block:%" PRId64 "(%" PRI_stime ")\n",
+ data->lock_cnt, data->time_hold, data->block_cnt, data->time_block);
}
void spinlock_profile_printall(unsigned char key)
@@ -488,7 +493,6 @@ void _lock_profile_deregister_struct(
spin_unlock(&lock_profile_lock);
}
-#ifdef CONFIG_LOCK_PROFILE
static int __init lock_prof_init(void)
{
struct lock_profile **q;
@@ -507,6 +511,5 @@ static int __init lock_prof_init(void)
return 0;
}
__initcall(lock_prof_init);
-#endif
-#endif /* LOCK_PROFILE */
+#endif /* CONFIG_DEBUG_LOCK_PROFILE */
@@ -119,7 +119,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
break;
#endif
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
case XEN_SYSCTL_lockprof_op:
ret = spinlock_profile_control(&op->u.lockprof_op);
break;
@@ -1170,7 +1170,9 @@ void panic(const char *fmt, ...)
unsigned long flags;
static DEFINE_SPINLOCK(lock);
static char buf[128];
-
+
+ spin_debug_disable();
+ spinlock_profile_printall('\0');
debugtrace_dump();
/* Protects buf[] and ensure multi-line message prints atomically. */
@@ -1,6 +1,7 @@
#ifndef __SPINLOCK_H__
#define __SPINLOCK_H__
+#include <xen/time.h>
#include <asm/system.h>
#include <asm/spinlock.h>
#include <asm/types.h>
@@ -28,7 +29,7 @@ union lock_debug { };
#define spin_debug_disable() ((void)0)
#endif
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
#include <public/sysctl.h>
@@ -74,9 +75,9 @@ struct lock_profile {
struct spinlock *lock; /* the lock itself */
u64 lock_cnt; /* # of complete locking ops */
u64 block_cnt; /* # of complete wait for lock */
- s64 time_hold; /* cumulated lock time */
- s64 time_block; /* cumulated wait time */
- s64 time_locked; /* system time of last locking */
+ s_time_t time_hold; /* cumulated lock time */
+ s_time_t time_block; /* cumulated wait time */
+ s_time_t time_locked; /* system time of last locking */
};
struct lock_profile_qhead {
@@ -132,6 +133,7 @@ struct lock_profile_qhead { };
#define spin_lock_init_prof(s, l) spin_lock_init(&((s)->l))
#define lock_profile_register_struct(type, ptr, idx, print)
#define lock_profile_deregister_struct(type, ptr)
+#define spinlock_profile_printall(key)
#endif
@@ -153,7 +155,7 @@ typedef struct spinlock {
u16 recurse_cnt:SPINLOCK_RECURSE_BITS;
#define SPINLOCK_MAX_RECURSE ((1u << SPINLOCK_RECURSE_BITS) - 1)
union lock_debug debug;
-#ifdef CONFIG_LOCK_PROFILE
+#ifdef CONFIG_DEBUG_LOCK_PROFILE
struct lock_profile *profile;
#endif
} spinlock_t;