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


Reply via email to