rcu: Break call_rcu() deadlock involving scheduler and perf
[platform/adaptation/renesas_rcar/renesas_kernel.git] / kernel / rcu / tree.h
index 8e34d86..a87adfc 100644 (file)
@@ -317,6 +317,7 @@ struct rcu_data {
        unsigned long n_rp_cpu_needs_gp;
        unsigned long n_rp_gp_completed;
        unsigned long n_rp_gp_started;
+       unsigned long n_rp_nocb_defer_wakeup;
        unsigned long n_rp_need_nothing;
 
        /* 6) _rcu_barrier() and OOM callbacks. */
@@ -335,6 +336,7 @@ struct rcu_data {
        int nocb_p_count_lazy;          /*  (approximate). */
        wait_queue_head_t nocb_wq;      /* For nocb kthreads to sleep on. */
        struct task_struct *nocb_kthread;
+       bool nocb_defer_wakeup;         /* Defer wakeup of nocb_kthread. */
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 
        /* 8) RCU CPU stall data. */
@@ -550,9 +552,12 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq);
 static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp);
 static void rcu_init_one_nocb(struct rcu_node *rnp);
 static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
-                           bool lazy);
+                           bool lazy, unsigned long flags);
 static bool rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
-                                     struct rcu_data *rdp);
+                                     struct rcu_data *rdp,
+                                     unsigned long flags);
+static bool rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
+static void do_nocb_deferred_wakeup(struct rcu_data *rdp);
 static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
 static void rcu_spawn_nocb_kthreads(struct rcu_state *rsp);
 static void rcu_kick_nohz_cpu(int cpu);