From 11ca4ed152e9ab9b0853fe65c630eb092ba49c05 Mon Sep 17 00:00:00 2001 From: "he, bo" Date: Sun, 9 Dec 2018 18:11:33 +0800 Subject: [PATCH 2/2] rcu: detect the preempt_rcu hang Change-Id: I2c059ffe7d8b3ef8ab5f2cb246dff24a729555f1 Tracked-On: Signed-off-by: he, bo --- kernel/rcu/tree.c | 34 ++++++++++++++++++++++++++++------ kernel/rcu/update.c | 4 +++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index a7ff53d..0a7e83c 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -61,6 +61,7 @@ #include #include #include +#include #include "tree.h" #include "rcu.h" @@ -637,11 +638,13 @@ void show_rcu_gp_kthreads(void) struct rcu_state *rsp; for_each_rcu_flavor(rsp) { - pr_info("%s: wait state: %d ->state: %#lx\n", - rsp->name, rsp->gp_state, rsp->gp_kthread->state); + pr_info("%s: wait state: %d ->state: %#lx gp_flags: %d rsp: gp_seq = %lu\n", + rsp->name, rsp->gp_state, rsp->gp_kthread->state, rsp->gp_flags, rsp->gp_seq); rcu_for_each_node_breadth_first(rsp, rnp) { - if (ULONG_CMP_GE(rsp->gp_seq, rnp->gp_seq_needed)) + if (ULONG_CMP_GE(rsp->gp_seq, rnp->gp_seq_needed)) { + pr_info("\trsp->gp_seq %lu is ge rnp->gp_seq_needed %lu\n", rsp->gp_seq, rnp->gp_seq_needed); continue; + } pr_info("\trcu_node %d:%d ->gp_seq %lu ->gp_seq_needed %lu\n", rnp->grplo, rnp->grphi, rnp->gp_seq, rnp->gp_seq_needed); @@ -651,8 +654,11 @@ void show_rcu_gp_kthreads(void) rdp = per_cpu_ptr(rsp->rda, cpu); if (rdp->gpwrap || ULONG_CMP_GE(rsp->gp_seq, - rdp->gp_seq_needed)) + rdp->gp_seq_needed)) { + pr_info("\tcpu %d rdp->gpwrap = %d rsp->gp_seq %lu is ge rdp->gp_seq_needed %lu\n", + cpu, rdp->gpwrap, rsp->gp_seq, rdp->gp_seq_needed); continue; + } pr_info("\tcpu %d ->gp_seq_needed %lu\n", cpu, rdp->gp_seq_needed); } @@ -2153,8 +2159,13 @@ static int __noreturn rcu_gp_kthread(void *arg) int ret; struct rcu_state *rsp = arg; struct rcu_node *rnp = rcu_get_root(rsp); + pid_t rcu_preempt_pid; rcu_bind_gp_kthread(); + if(!strcmp(rsp->name, "rcu_preempt")) { + rcu_preempt_pid = rsp->gp_kthread->pid; + } + for (;;) { /* Handle grace-period start. */ @@ -2163,8 +2174,19 @@ static int __noreturn rcu_gp_kthread(void *arg) READ_ONCE(rsp->gp_seq), TPS("reqwait")); rsp->gp_state = RCU_GP_WAIT_GPS; - swait_event_idle_exclusive(rsp->gp_wq, READ_ONCE(rsp->gp_flags) & - RCU_GP_FLAG_INIT); + if (current->pid != rcu_preempt_pid) { + swait_event_idle_exclusive(rsp->gp_wq, READ_ONCE(rsp->gp_flags) & + RCU_GP_FLAG_INIT); + } else { + ret = swait_event_idle_timeout_exclusive(rsp->gp_wq, READ_ONCE(rsp->gp_flags) & + RCU_GP_FLAG_INIT, 2*HZ); + + if(!ret) { + show_rcu_gp_kthreads(); + panic("hung_task: blocked in rcu_gp_kthread init"); + } + } + rsp->gp_state = RCU_GP_DONE_GPS; /* Locking provides needed memory barrier. */ if (rcu_gp_init(rsp)) diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 81db882..63f761a 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -364,8 +364,10 @@ void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array, break; if (j == i) { trace_printk("bobo: start wait for rcu gp\n"); - if(!wait_for_completion_timeout(&rs_array[i].completion, 3*HZ)) + if(!wait_for_completion_timeout(&rs_array[i].completion, 2*HZ)) { + show_rcu_gp_kthreads(); panic("hung_task: blocked tasks in rcu"); + } trace_printk("bobo: finish wait for rcu gp\n"); } -- 2.7.4