From dde58a67db34eda9ebd9cf95d835ec0ba3e68db7 Mon Sep 17 00:00:00 2001 From: Wei Jiangang Date: Sun, 13 May 2012 20:07:01 +0800 Subject: [PATCH] add an option -t for command runq The option "-t" dispaly the timestamp information about the runqueue each of cpu. The timestamp information, which according to kernel version, may be the value of runqueue's member. For example, rq.clock or rq.timestamp_last_tick, even runqueue.timestamp_last_tick. Signed-off-by: Wei Jiangang --- defs.h | 1 + help.c | 11 ++++++++++ kernel.c | 15 +++++++++++-- task.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 4 deletions(-) diff --git a/defs.h b/defs.h index 77a623d..73e2168 100755 --- a/defs.h +++ b/defs.h @@ -1557,6 +1557,7 @@ struct offset_table { /* stash of commonly-used offsets */ long rq_cfs; long rq_rt; long rq_nr_running; + long rq_timestamp; long cfs_rq_rb_leftmost; long cfs_rq_nr_running; long cfs_rq_tasks_timeline; diff --git a/help.c b/help.c index 8ce8247..aa60182 100755 --- a/help.c +++ b/help.c @@ -2140,7 +2140,13 @@ char *help_runq[] = { "runq", "run queue", " ", +" [-t] ", " This command displays the tasks on the run queues of each cpu.", +" The arguments are as follows:\n", +" -t Display the timestamp information about the runqueue each of cpu.", +" the timstamp information may be the value of rq.clock or", +" rq.timestamp_last_tick, which according to kernel version.", +" ", "\nEXAMPLES", " %s> runq", " CPU 0 RUNQUEUE: ffff880001cdb460", @@ -2157,6 +2163,11 @@ char *help_runq[] = { " [115] PID: 1779 TASK: ffff88003207a860 COMMAND: \"klogd\"", " EXPIRED PRIO_ARRAY: ffff880001ce3db8", " [no tasks queued]", +" %s> runq -t ", +" CPU 0: 67393251944103", +" [67393251944103] PID: 14776 TASK: ea54aab0 COMMAND: \"crash\"", +" CPU 1: 66789719628339", +" [67393251858710] PID: 14769 TASK: f4bdc030 COMMAND: \"crash\"", NULL }; diff --git a/kernel.c b/kernel.c index 4342bce..9873f98 100755 --- a/kernel.c +++ b/kernel.c @@ -67,6 +67,7 @@ kernel_init() char *p1, *p2, buf[BUFSIZE]; struct syment *sp1, *sp2; char *rqstruct; + char *rq_timestamp_name = NULL; char *irq_desc_type_name; ulong pv_init_ops; @@ -225,11 +226,18 @@ kernel_init() &kt->__per_cpu_offset[0]); kt->flags |= PER_CPU_OFF; } - if (STRUCT_EXISTS("runqueue")) + if (STRUCT_EXISTS("runqueue")) { rqstruct = "runqueue"; - else if (STRUCT_EXISTS("rq")) + rq_timestamp_name = "timestamp_last_tick"; + } else if (STRUCT_EXISTS("rq")) { rqstruct = "rq"; - else { + if (MEMBER_EXISTS("rq", "clock")) + rq_timestamp_name = "clock"; + else if (MEMBER_EXISTS("rq", "most_recent_timestamp")) + rq_timestamp_name = "most_recent_timestamp"; + else if (MEMBER_EXISTS("rq", "timestamp_last_tick")) + rq_timestamp_name = "timestamp_last_tick"; + } else { rqstruct = NULL; error(FATAL, "neither runqueue nor rq structures exist\n"); } @@ -275,6 +283,7 @@ kernel_init() MEMBER_OFFSET_INIT(runqueue_active, rqstruct, "active"); MEMBER_OFFSET_INIT(runqueue_expired, rqstruct, "expired"); MEMBER_OFFSET_INIT(runqueue_arrays, rqstruct, "arrays"); + MEMBER_OFFSET_INIT(rq_timestamp, rqstruct, rq_timestamp_name); MEMBER_OFFSET_INIT(prio_array_queue, "prio_array", "queue"); MEMBER_OFFSET_INIT(prio_array_nr_active, "prio_array", "nr_active"); STRUCT_SIZE_INIT(runqueue, rqstruct); diff --git a/task.c b/task.c index 002e8b6..3e8d936 100755 --- a/task.c +++ b/task.c @@ -53,6 +53,7 @@ static ulong get_curr_task(int, char *); static long rq_idx(int); static long cpu_idx(int); static void dump_runq(void); +static void dump_on_rq_timestamp(void); static void dump_runqueues(void); static void dump_prio_array(int, ulong, char *); struct rb_root; @@ -7000,13 +7001,17 @@ cmd_runq(void) { int c; int sched_debug = 0; + int dump_timestamp_flag = 0; - while ((c = getopt(argcnt, args, "d")) != EOF) { + while ((c = getopt(argcnt, args, "dt")) != EOF) { switch(c) { case 'd': sched_debug = 1; break; + case 't': + dump_timestamp_flag = 1; + break; default: argerrs++; break; @@ -7017,6 +7022,12 @@ cmd_runq(void) if (argerrs) cmd_usage(pc->curcmd, SYNOPSIS); + if (dump_timestamp_flag) { + dump_on_rq_timestamp(); + return; + } + + if (sched_debug) { dump_on_rq_tasks(); return; @@ -7026,6 +7037,56 @@ cmd_runq(void) } /* + * Displays the timestamp information about the runqueue each of cpu + */ +void +dump_on_rq_timestamp(void) +{ + struct task_context *tcp; + char format[15]; + ulong runq; + char buf[BUFSIZE]; + struct syment *rq_sp; + struct task_context *tc; + int cpu, c; + ulonglong timestamp; + + runq = 0; + tcp = FIRST_CONTEXT(); + sprintf(buf, pc->output_radix == 10 ? "%lld" : "%llx", + task_last_run(tcp->task)); + c = strlen(buf); + + if (!(rq_sp = per_cpu_symbol_search("per_cpu__runqueues"))) + error(FATAL, "per-cpu runqueues does not exist\n"); + + for (cpu = 0; cpu < kt->cpus; cpu++) { + if ((kt->flags & SMP) && (kt->flags &PER_CPU_OFF)) + runq = rq_sp->value + kt->__per_cpu_offset[cpu]; + else + runq = rq_sp->value; + + readmem(runq + OFFSET(rq_timestamp), KVADDR, ×tamp, + sizeof(ulonglong), "per-cpu rq timestamp", + FAULT_ON_ERROR); + + sprintf(format, " CPU%2d: %c%dll%c\n", cpu, '%', c, + pc->output_radix == 10 ? 'u' : 'x'); + fprintf(fp, format, timestamp); + + if((tc = task_to_context(tt->active_set[cpu]))){ + sprintf(format, "[%c%dll%c] ", '%', c, + pc->output_radix == 10 ? 'u' : 'x'); + fprintf(fp, format, task_last_run(tc->task)); + fprintf(fp, "PID: %-5ld TASK: %lx COMMAND: \"%s\"\n", + tc->pid, tc->task, tc->comm); + } else + fprintf(fp, "%lx\n", tt->active_set[cpu]); + + } +} + +/* * Dump the task run queue on behalf cmd_runq(). */ -- 1.7.1