Add a monitor debug function for rendez waiters
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 18 Dec 2018 20:56:58 +0000 (15:56 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 18 Dec 2018 20:56:58 +0000 (15:56 -0500)
When debugging, it's helpful to be able to tell what is waiting on a
particular rendez.  "db rv 0xWAITER" will do the trick.

Like many monitor commands, this is dangerous.  Not only will it cast
whatever you pass it to an alarm_waiter, but even if you don't mess up,
there's no telling that the alarm isn't currently firing and unwinding
the stack.  That being said, it's been useful for me.

Usage:

(akaros) / $ m alarm pcpu
PCPU Chains:  It is now [    189.392342216]
Chain 0xffffffffcc683c48:  earliest: [    189.399452912] latest: [    482.049028825]
Waiter 0xffffffffcc683ac0, time [    189.399452912] (0x0000008cc62c95fa), func 0xffffffffc205a740 (__ksched_tick)
Waiter 0xfffffff000097dd8, time [    189.416393761] (0x0000008cc965c92b), func 0xffffffffc20586e0 (rendez_alarm_handler)
Waiter 0xfffffff0000a9c98, time [    482.049028825] (0x000001664a5eef19), func 0xffffffffc20586e0 (rendez_alarm_handler)
Chain 0xffffffffcc683f08:  earliest: [    189.477399144] latest: [    189.477399144]
Waiter 0xfffffff0000a6cb8, time [    189.477399144] (0x0000008cd50165fa), func 0xffffffffc20586e0 (rendez_alarm_handler)

(akaros) / $ m db rv 0xfffffff0000a6cb8
-------- kth #I0tcpack ----------

Backtrace of kernel context on Core 0:
 #01 [<0xffffffffc20145ab>] in cv_wait_and_unlock
 #02 [<0xffffffffc2014651>] in cv_wait
 #03 [<0xffffffffc20585cd>] in rendez_sleep_timeout
 #04 [<0xffffffffc2013d72>] in kthread_usleep
 #05 [<0xffffffffc20327a4>] in tcpackproc
 #06 [<0xffffffffc2013274>] in __ktask_wrapper
 #07 [<0xffffffffc2063bad>] in process_routine_kmsg
 #08 [<0xffffffffc205d59e>] in __smp_idle
-----------------

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/rendez.h
kern/src/monitor.c
kern/src/rendez.c

index f607105..06f257a 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <ros/common.h>
 #include <kthread.h>
+#include <alarm.h>
 
 struct rendez {
        struct cond_var                         cv;
@@ -51,3 +52,4 @@ void rendez_sleep(struct rendez *rv, int (*cond)(void*), void *arg);
 void rendez_sleep_timeout(struct rendez *rv, int (*cond)(void*), void *arg,
                           uint64_t usec);
 bool rendez_wakeup(struct rendez *rv);
+void rendez_debug_waiter(struct alarm_waiter *awaiter);
index 3f26125..8c137fd 100644 (file)
@@ -1007,6 +1007,7 @@ int mon_db(int argc, char **argv, struct hw_trapframe *hw_tf)
                printk("Usage: db OPTION\n");
                printk("\tblk [PID]: print all blocked kthreads\n");
                printk("\taddr PID 0xADDR: for PID lookup ADDR's file/vmr info\n");
+               printk("\trv WAITER: backtrace rendez alarm waiter\n");
                return 1;
        }
        if (!strcmp(argv[1], "blk") || !strcmp(argv[1], "sem")) {
@@ -1019,6 +1020,12 @@ int mon_db(int argc, char **argv, struct hw_trapframe *hw_tf)
                        return 1;
                }
                debug_addr_pid(strtol(argv[2], 0, 10), strtol(argv[3], 0, 16));
+       } else if (!strcmp(argv[1], "rv")) {
+               if (argc < 3) {
+                       printk("Usage: db rv 0xWAITER\n");
+                       return 1;
+               }
+               rendez_debug_waiter((struct alarm_waiter*)strtoul(argv[2], 0, 16));
        } else {
                printk("Bad option\n");
                return 1;
index 215e85f..6d5de7c 100644 (file)
@@ -61,6 +61,24 @@ static void rendez_alarm_handler(struct alarm_waiter *awaiter)
        rendez_wakeup(rv);
 }
 
+void rendez_debug_waiter(struct alarm_waiter *awaiter)
+{
+       struct rendez *rv = (struct rendez*)awaiter->data;
+       struct cond_var *cv = &rv->cv;
+       struct kthread *kth;
+       int8_t irq_state = 0;
+
+       cv_lock_irqsave(cv, &irq_state);
+       TAILQ_FOREACH(kth, &cv->waiters, link) {
+               print_lock();
+               printk("-------- kth %s ----------\n", kth->name);
+               backtrace_kthread(kth);
+               printk("-----------------\n");
+               print_unlock();
+       }
+       cv_unlock_irqsave(cv, &irq_state);
+}
+
 /* Like sleep, but it will timeout in 'usec' microseconds. */
 void rendez_sleep_timeout(struct rendez *rv, int (*cond)(void*), void *arg,
                           uint64_t usec)