MACH_LOCK_MON's locate_lock_info() guessed the caller of a lock with
li->caller = *((vm_offset_t *)lock - 1);
which reads an unrelated stack slot and is compiler/codegen dependent.
Under MACH_LOCK_MON the lock entry points are real functions when
NCPUS > 1, so the stored value is frequently not a code address and
`show all slocks` / `lip` print bare or bogus hex such as 0x315(...)
instead of a caller function name.
Capture the actual return address at the three lock entry points with
__builtin_return_address(0) and pass it to locate_lock_info(). Resolve
the stored address with db_printsym(..., DB_STGY_PROC) so the
LOCK/CALLER column prints name+offset, and always show the lock address
in parentheses. This only bites the MACH_LOCK_MON diagnostic path:
locking semantics, statistics and the millisecond timing are unchanged,
and MACH_LOCK_MON remains off by default.
Based on upstream commit 5e25bd3c ("Add timing info to MACH_LOCK_MON
lock monitoring").
---
kern/lock_mon.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/kern/lock_mon.c b/kern/lock_mon.c
index edc8ae55..5a7e72fa 100644
--- a/kern/lock_mon.c
+++ b/kern/lock_mon.c
@@ -91,8 +91,9 @@ extern spl_t curr_ipl[];
struct lock_info *
-locate_lock_info(lock)
+locate_lock_info(lock, caller)
decl_simple_lock_data(, **lock)
+vm_offset_t caller;
{
struct lock_info *li = &(lock_info[HASH_LOCK(*lock)].info[0]);
int i;
@@ -103,7 +104,7 @@ decl_simple_lock_data(, **lock)
return(li);
} else {
li->lock = *lock;
- li->caller = *((vm_offset_t *)lock - 1);
+ li->caller = caller;
return(li);
}
db_printf("out of lock_info slots\n");
@@ -115,7 +116,8 @@ decl_simple_lock_data(, **lock)
void simple_lock(lock)
decl_simple_lock_data(, *lock)
{
- struct lock_info *li = locate_lock_info(&lock);
+ struct lock_info *li = locate_lock_info(&lock,
+ (vm_offset_t)
__builtin_return_address(0));
int my_cpu = cpu_number();
if (current_thread())
@@ -134,7 +136,8 @@ decl_simple_lock_data(, *lock)
int simple_lock_try(lock)
decl_simple_lock_data(, *lock)
{
- struct lock_info *li = locate_lock_info(&lock);
+ struct lock_info *li = locate_lock_info(&lock,
+ (vm_offset_t)
__builtin_return_address(0));
int my_cpu = cpu_number();
if (curr_ipl[my_cpu])
@@ -155,7 +158,8 @@ void simple_unlock(lock)
decl_simple_lock_data(, *lock)
{
time_stamp_t stamp = time_stamp;
- time_stamp_t *time = &locate_lock_info(&lock)->time;
+ time_stamp_t *time = &locate_lock_info(&lock,
+ (vm_offset_t)
__builtin_return_address(0))->time;
unsigned *lock_stack;
*time = stamp - *time;
@@ -265,20 +269,14 @@ void lock_info_clear(void)
static void print_lock_info(struct lock_info *li)
{
- db_addr_t off;
int sum = li->success + li->fail;
db_printf("%d %d/%d %d/%d %d/%d %d/%d ", li->success,
li->fail, (li->fail*100)/sum,
li->masked, (li->masked*100)/sum,
li->stack, li->stack/sum,
li->time, li->time/sum);
- db_free_symbol(db_search_symbol((db_addr_t) li->lock, 0, &off));
- if (off < 1024)
- db_printsym((db_addr_t) li->lock, 0);
- else {
- db_printsym(li->caller, 0);
- db_printf("(%X)", li->lock);
- }
+ db_printsym(li->caller, DB_STGY_PROC);
+ db_printf("(%X)", li->lock);
db_printf("\n");
}
--
2.47.3