rcu: priority boosting for TREE_PREEMPT_RCU
[platform/adaptation/renesas_rcar/renesas_kernel.git] / kernel / rcutree.h
index e8f057e..8db0cdc 100644 (file)
  * Dynticks per-CPU state.
  */
 struct rcu_dynticks {
-       int dynticks_nesting;   /* Track nesting level, sort of. */
-       int dynticks;           /* Even value for dynticks-idle, else odd. */
-       int dynticks_nmi;       /* Even value for either dynticks-idle or */
-                               /*  not in nmi handler, else odd.  So this */
-                               /*  remains even for nmi from irq handler. */
+       int dynticks_nesting;   /* Track irq/process nesting level. */
+       int dynticks_nmi_nesting; /* Track NMI nesting level. */
+       atomic_t dynticks;      /* Even value for dynticks-idle, else odd. */
 };
 
 /*
@@ -109,10 +107,11 @@ struct rcu_node {
                                /*  an rcu_data structure, otherwise, each */
                                /*  bit corresponds to a child rcu_node */
                                /*  structure. */
-       unsigned long expmask;  /* Groups that have ->blocked_tasks[] */
+       unsigned long expmask;  /* Groups that have ->blkd_tasks */
                                /*  elements that need to drain to allow the */
                                /*  current expedited grace period to */
                                /*  complete (only for TREE_PREEMPT_RCU). */
+       unsigned long wakemask; /* CPUs whose kthread needs to be awakened. */
        unsigned long qsmaskinit;
                                /* Per-GP initial value for qsmask & expmask. */
        unsigned long grpmask;  /* Mask to apply to parent qsmask. */
@@ -122,11 +121,45 @@ struct rcu_node {
        u8      grpnum;         /* CPU/group number for next level up. */
        u8      level;          /* root is at level 0. */
        struct rcu_node *parent;
-       struct list_head blocked_tasks[4];
-                               /* Tasks blocked in RCU read-side critsect. */
-                               /*  Grace period number (->gpnum) x blocked */
-                               /*  by tasks on the (x & 0x1) element of the */
-                               /*  blocked_tasks[] array. */
+       struct list_head blkd_tasks;
+                               /* Tasks blocked in RCU read-side critical */
+                               /*  section.  Tasks are placed at the head */
+                               /*  of this list and age towards the tail. */
+       struct list_head *gp_tasks;
+                               /* Pointer to the first task blocking the */
+                               /*  current grace period, or NULL if there */
+                               /*  is no such task. */
+       struct list_head *exp_tasks;
+                               /* Pointer to the first task blocking the */
+                               /*  current expedited grace period, or NULL */
+                               /*  if there is no such task.  If there */
+                               /*  is no current expedited grace period, */
+                               /*  then there can cannot be any such task. */
+#ifdef CONFIG_RCU_BOOST
+       struct list_head *boost_tasks;
+                               /* Pointer to first task that needs to be */
+                               /*  priority boosted, or NULL if no priority */
+                               /*  boosting is needed for this rcu_node */
+                               /*  structure.  If there are no tasks */
+                               /*  queued on this rcu_node structure that */
+                               /*  are blocking the current grace period, */
+                               /*  there can be no such task. */
+       unsigned long boost_time;
+                               /* When to start boosting (jiffies). */
+       struct task_struct *boost_kthread_task;
+                               /* kthread that takes care of priority */
+                               /*  boosting for this rcu_node structure. */
+       wait_queue_head_t boost_wq;
+                               /* Wait queue on which to park the boost */
+                               /*  kthread. */
+#endif /* #ifdef CONFIG_RCU_BOOST */
+       struct task_struct *node_kthread_task;
+                               /* kthread that takes care of this rcu_node */
+                               /*  structure, for example, awakening the */
+                               /*  per-CPU kthreads as needed. */
+       wait_queue_head_t node_wq;
+                               /* Wait queue on which to park the per-node */
+                               /*  kthread. */
 } ____cacheline_internodealigned_in_smp;
 
 /*
@@ -218,7 +251,6 @@ struct rcu_data {
        /* 3) dynticks interface. */
        struct rcu_dynticks *dynticks;  /* Shared per-CPU dynticks state. */
        int dynticks_snap;              /* Per-GP tracking for dynticks. */
-       int dynticks_nmi_snap;          /* Per-GP tracking for dynticks_nmi. */
 #endif /* #ifdef CONFIG_NO_HZ */
 
        /* 4) reasons this CPU needed to be kicked by force_quiescent_state */
@@ -254,7 +286,6 @@ struct rcu_data {
 #endif /* #else #ifdef CONFIG_NO_HZ */
 
 #define RCU_JIFFIES_TILL_FORCE_QS       3      /* for rsp->jiffies_force_qs */
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 
 #ifdef CONFIG_PROVE_RCU
 #define RCU_STALL_DELAY_DELTA         (5 * HZ)
@@ -272,13 +303,6 @@ struct rcu_data {
                                                /*  scheduling clock irq */
                                                /*  before ratting on them. */
 
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE
-#define RCU_CPU_STALL_SUPPRESS_INIT 0
-#else
-#define RCU_CPU_STALL_SUPPRESS_INIT 1
-#endif
-
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
  * RCU global state, including node hierarchy.  This hierarchy is
@@ -325,12 +349,10 @@ struct rcu_state {
                                                /*  due to lock unavailable. */
        unsigned long n_force_qs_ngp;           /* Number of calls leaving */
                                                /*  due to no GP active. */
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
        unsigned long gp_start;                 /* Time at which GP started, */
                                                /*  but in jiffies. */
        unsigned long jiffies_stall;            /* Time at which to check */
                                                /*  for CPU stalls. */
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
        char *name;                             /* Name of structure. */
 };
 
@@ -361,16 +383,14 @@ DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);
 static void rcu_bootup_announce(void);
 long rcu_batches_completed(void);
 static void rcu_preempt_note_context_switch(int cpu);
-static int rcu_preempted_readers(struct rcu_node *rnp);
+static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
                                      unsigned long flags);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static void rcu_print_task_stall(struct rcu_node *rnp);
 static void rcu_preempt_stall_reset(void);
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
@@ -390,5 +410,16 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
 static void rcu_preempt_send_cbs_to_online(void);
 static void __init __rcu_init_preempt(void);
 static void rcu_needs_cpu_flush(void);
+static void __init rcu_init_boost_waitqueue(struct rcu_node *rnp);
+static void rcu_initiate_boost(struct rcu_node *rnp);
+static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp,
+                                         cpumask_var_t cm);
+static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
+static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
+                                                struct rcu_node *rnp,
+                                                int rnp_index);
+#ifdef CONFIG_HOTPLUG_CPU
+static void rcu_stop_boost_kthread(struct rcu_node *rnp);
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
 #endif /* #ifndef RCU_TREE_NONCORE */