From 32e4616ba0bf98cb4482595decc971fe1a4608f6 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Date: Thu, 5 Jan 2012 15:16:55 +0900
Subject: [PATCH] runq: search current task's runqueue explicitly

A current task has been excluded from runqueue. So we need to search
current task's runqueue explicitly. Also, we need to consider the case
that cfs_rq->curr or cfs_rq->curr->my_q is NULL in the following
conditions:

- cpu runqueues->current is idle task or real time task, or
- very short moment during context switch.

Also remove the second argument from dump_tasks_in_cfs_rq() that has
been used for a temporary workaround.

Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
---
 defs.h |    1 +
 task.c |   37 +++++++++++++++++--------------------
 2 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/defs.h b/defs.h
index 82d51e5..5d18a54 100755
--- a/defs.h
+++ b/defs.h
@@ -1631,6 +1631,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long sched_entity_my_q;
 	long sched_entity_on_rq;
 	long task_struct_on_rq;
+	long cfs_rq_curr;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
diff --git a/task.c b/task.c
index 433a043..293969e 100755
--- a/task.c
+++ b/task.c
@@ -62,7 +62,7 @@ static struct rb_node *rb_parent(struct rb_node *, struct rb_node *);
 static struct rb_node *rb_right(struct rb_node *, struct rb_node *);
 static struct rb_node *rb_left(struct rb_node *, struct rb_node *);
 static void dump_task_runq_entry(struct task_context *);
-static int dump_tasks_in_cfs_rq(ulong, ulong);
+static int dump_tasks_in_cfs_rq(ulong);
 static void dump_on_rq_tasks(void);
 static void dump_CFS_runqueues(void);
 static void dump_RT_prio_array(int, ulong, char *);
@@ -7019,21 +7019,28 @@ dump_task_runq_entry(struct task_context *tc)
 }
 
 static int
-dump_tasks_in_cfs_rq(ulong cfs_rq, ulong skip)
+dump_tasks_in_cfs_rq(ulong cfs_rq)
 {
 	struct task_context *tc;
 	struct rb_root *root;
 	struct rb_node *node;
-	ulong my_q, leftmost;
+	ulong my_q, leftmost, curr, curr_my_q;
 	int total;
 
-	if (cfs_rq == skip)
-		return 0;
+	total = 0;
+
+	readmem(cfs_rq + OFFSET(cfs_rq_curr), KVADDR, &curr, sizeof(ulong),
+		"curr", FAULT_ON_ERROR);
+	if (curr) {
+		readmem(curr + OFFSET(sched_entity_my_q), KVADDR, &curr_my_q,
+			sizeof(ulong), "curr->my_q", FAULT_ON_ERROR);
+		if (curr_my_q)
+			total += dump_tasks_in_cfs_rq(curr_my_q);
+	}
 
 	readmem(cfs_rq + OFFSET(cfs_rq_rb_leftmost), KVADDR, &leftmost,
 		sizeof(ulong), "rb_leftmost", FAULT_ON_ERROR);
 	root = (struct rb_root *)(cfs_rq + OFFSET(cfs_rq_tasks_timeline));
-	total = 0;
 
 	for (node = rb_first(root); leftmost && node; node = rb_next(node)) {
 		if (VALID_MEMBER(sched_entity_my_q)) {
@@ -7041,7 +7048,7 @@ dump_tasks_in_cfs_rq(ulong cfs_rq, ulong skip)
 				+ OFFSET(sched_entity_my_q), KVADDR, &my_q,
 				sizeof(ulong), "my_q", FAULT_ON_ERROR);
 			if (my_q) {
-				total += dump_tasks_in_cfs_rq(my_q, skip);
+				total += dump_tasks_in_cfs_rq(my_q);
 				continue;
 			}
 		}
@@ -7115,7 +7122,7 @@ static void
 dump_CFS_runqueues(void)
 {
 	int tot, cpu;
-	ulong runq, cfs_rq, curr_cfs_rq;
+	ulong runq, cfs_rq;
 	char *runqbuf, *cfs_rq_buf;
 	ulong tasks_timeline ATTRIBUTE_UNUSED;
 	struct task_context *tc;
@@ -7140,6 +7147,7 @@ dump_CFS_runqueues(void)
 		MEMBER_OFFSET_INIT(cfs_rq_nr_running, "cfs_rq", "nr_running");
 		MEMBER_OFFSET_INIT(cfs_rq_tasks_timeline, "cfs_rq", 
 			"tasks_timeline");
+		MEMBER_OFFSET_INIT(cfs_rq_curr, "cfs_rq", "curr");
 		MEMBER_OFFSET_INIT(rt_rq_active, "rt_rq", "active");
                 MEMBER_OFFSET_INIT(task_struct_run_list, "task_struct",
                         "run_list");
@@ -7203,24 +7211,13 @@ dump_CFS_runqueues(void)
 				OFFSET(cfs_rq_tasks_timeline));
 		}
 
-		if (tt->active_set[cpu] && VALID_MEMBER(sched_entity_cfs_rq)) {
-			readmem(tt->active_set[cpu] + OFFSET(task_struct_se) +
-				OFFSET(sched_entity_cfs_rq), KVADDR, &curr_cfs_rq,
-				sizeof(ulong), "current cfs_rq", FAULT_ON_ERROR);
-		} else
-			curr_cfs_rq = 0;
-
 		dump_RT_prio_array(nr_running != cfs_rq_nr_running,
 			runq + OFFSET(rq_rt) + OFFSET(rt_rq_active), 
 			&runqbuf[OFFSET(rq_rt) + OFFSET(rt_rq_active)]);
 
 		fprintf(fp, "  CFS RB_ROOT: %lx\n", (ulong)root);
 
-		tot = 0;
-		if (curr_cfs_rq)
-			tot += dump_tasks_in_cfs_rq(curr_cfs_rq, 0);
-		if (cfs_rq != curr_cfs_rq)
-			tot += dump_tasks_in_cfs_rq(cfs_rq, curr_cfs_rq);
+		tot = dump_tasks_in_cfs_rq(cfs_rq);
 		if (!tot) {
 			INDENT(5);
 			fprintf(fp, "[no tasks queued]\n");
-- 
1.7.4.4

