diff options
Diffstat (limited to 'kernel/rcutree_plugin.h')
| -rw-r--r-- | kernel/rcutree_plugin.h | 595 |
1 files changed, 472 insertions, 123 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index a3638710dc67..f629479d4b1f 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Read-Copy Update mechanism for mutual exclusion (tree-based version) | 2 | * Read-Copy Update mechanism for mutual exclusion (tree-based version) |
| 3 | * Internal non-public definitions that provide either classic | 3 | * Internal non-public definitions that provide either classic |
| 4 | * or preemptable semantics. | 4 | * or preemptible semantics. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -54,10 +54,6 @@ static void __init rcu_bootup_announce_oddness(void) | |||
| 54 | #ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE | 54 | #ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE |
| 55 | printk(KERN_INFO "\tRCU torture testing starts during boot.\n"); | 55 | printk(KERN_INFO "\tRCU torture testing starts during boot.\n"); |
| 56 | #endif | 56 | #endif |
| 57 | #ifndef CONFIG_RCU_CPU_STALL_DETECTOR | ||
| 58 | printk(KERN_INFO | ||
| 59 | "\tRCU-based detection of stalled CPUs is disabled.\n"); | ||
| 60 | #endif | ||
| 61 | #if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE) | 57 | #if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE) |
| 62 | printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n"); | 58 | printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n"); |
| 63 | #endif | 59 | #endif |
| @@ -70,6 +66,7 @@ static void __init rcu_bootup_announce_oddness(void) | |||
| 70 | 66 | ||
| 71 | struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt_state); | 67 | struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt_state); |
| 72 | DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data); | 68 | DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data); |
| 69 | static struct rcu_state *rcu_state = &rcu_preempt_state; | ||
| 73 | 70 | ||
| 74 | static int rcu_preempted_readers_exp(struct rcu_node *rnp); | 71 | static int rcu_preempted_readers_exp(struct rcu_node *rnp); |
| 75 | 72 | ||
| @@ -78,7 +75,7 @@ static int rcu_preempted_readers_exp(struct rcu_node *rnp); | |||
| 78 | */ | 75 | */ |
| 79 | static void __init rcu_bootup_announce(void) | 76 | static void __init rcu_bootup_announce(void) |
| 80 | { | 77 | { |
| 81 | printk(KERN_INFO "Preemptable hierarchical RCU implementation.\n"); | 78 | printk(KERN_INFO "Preemptible hierarchical RCU implementation.\n"); |
| 82 | rcu_bootup_announce_oddness(); | 79 | rcu_bootup_announce_oddness(); |
| 83 | } | 80 | } |
| 84 | 81 | ||
| @@ -111,7 +108,7 @@ void rcu_force_quiescent_state(void) | |||
| 111 | EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); | 108 | EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); |
| 112 | 109 | ||
| 113 | /* | 110 | /* |
| 114 | * Record a preemptable-RCU quiescent state for the specified CPU. Note | 111 | * Record a preemptible-RCU quiescent state for the specified CPU. Note |
| 115 | * that this just means that the task currently running on the CPU is | 112 | * that this just means that the task currently running on the CPU is |
| 116 | * not in a quiescent state. There might be any number of tasks blocked | 113 | * not in a quiescent state. There might be any number of tasks blocked |
| 117 | * while in an RCU read-side critical section. | 114 | * while in an RCU read-side critical section. |
| @@ -134,12 +131,12 @@ static void rcu_preempt_qs(int cpu) | |||
| 134 | * We have entered the scheduler, and the current task might soon be | 131 | * We have entered the scheduler, and the current task might soon be |
| 135 | * context-switched away from. If this task is in an RCU read-side | 132 | * context-switched away from. If this task is in an RCU read-side |
| 136 | * critical section, we will no longer be able to rely on the CPU to | 133 | * critical section, we will no longer be able to rely on the CPU to |
| 137 | * record that fact, so we enqueue the task on the appropriate entry | 134 | * record that fact, so we enqueue the task on the blkd_tasks list. |
| 138 | * of the blocked_tasks[] array. The task will dequeue itself when | 135 | * The task will dequeue itself when it exits the outermost enclosing |
| 139 | * it exits the outermost enclosing RCU read-side critical section. | 136 | * RCU read-side critical section. Therefore, the current grace period |
| 140 | * Therefore, the current grace period cannot be permitted to complete | 137 | * cannot be permitted to complete until the blkd_tasks list entries |
| 141 | * until the blocked_tasks[] entry indexed by the low-order bit of | 138 | * predating the current grace period drain, in other words, until |
| 142 | * rnp->gpnum empties. | 139 | * rnp->gp_tasks becomes NULL. |
| 143 | * | 140 | * |
| 144 | * Caller must disable preemption. | 141 | * Caller must disable preemption. |
| 145 | */ | 142 | */ |
| @@ -147,7 +144,6 @@ static void rcu_preempt_note_context_switch(int cpu) | |||
| 147 | { | 144 | { |
| 148 | struct task_struct *t = current; | 145 | struct task_struct *t = current; |
| 149 | unsigned long flags; | 146 | unsigned long flags; |
| 150 | int phase; | ||
| 151 | struct rcu_data *rdp; | 147 | struct rcu_data *rdp; |
| 152 | struct rcu_node *rnp; | 148 | struct rcu_node *rnp; |
| 153 | 149 | ||
| @@ -169,15 +165,30 @@ static void rcu_preempt_note_context_switch(int cpu) | |||
| 169 | * (i.e., this CPU has not yet passed through a quiescent | 165 | * (i.e., this CPU has not yet passed through a quiescent |
| 170 | * state for the current grace period), then as long | 166 | * state for the current grace period), then as long |
| 171 | * as that task remains queued, the current grace period | 167 | * as that task remains queued, the current grace period |
| 172 | * cannot end. | 168 | * cannot end. Note that there is some uncertainty as |
| 169 | * to exactly when the current grace period started. | ||
| 170 | * We take a conservative approach, which can result | ||
| 171 | * in unnecessarily waiting on tasks that started very | ||
| 172 | * slightly after the current grace period began. C'est | ||
| 173 | * la vie!!! | ||
| 173 | * | 174 | * |
| 174 | * But first, note that the current CPU must still be | 175 | * But first, note that the current CPU must still be |
| 175 | * on line! | 176 | * on line! |
| 176 | */ | 177 | */ |
| 177 | WARN_ON_ONCE((rdp->grpmask & rnp->qsmaskinit) == 0); | 178 | WARN_ON_ONCE((rdp->grpmask & rnp->qsmaskinit) == 0); |
| 178 | WARN_ON_ONCE(!list_empty(&t->rcu_node_entry)); | 179 | WARN_ON_ONCE(!list_empty(&t->rcu_node_entry)); |
| 179 | phase = (rnp->gpnum + !(rnp->qsmask & rdp->grpmask)) & 0x1; | 180 | if ((rnp->qsmask & rdp->grpmask) && rnp->gp_tasks != NULL) { |
| 180 | list_add(&t->rcu_node_entry, &rnp->blocked_tasks[phase]); | 181 | list_add(&t->rcu_node_entry, rnp->gp_tasks->prev); |
| 182 | rnp->gp_tasks = &t->rcu_node_entry; | ||
| 183 | #ifdef CONFIG_RCU_BOOST | ||
| 184 | if (rnp->boost_tasks != NULL) | ||
| 185 | rnp->boost_tasks = rnp->gp_tasks; | ||
| 186 | #endif /* #ifdef CONFIG_RCU_BOOST */ | ||
| 187 | } else { | ||
| 188 | list_add(&t->rcu_node_entry, &rnp->blkd_tasks); | ||
| 189 | if (rnp->qsmask & rdp->grpmask) | ||
| 190 | rnp->gp_tasks = &t->rcu_node_entry; | ||
| 191 | } | ||
| 181 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 192 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
| 182 | } | 193 | } |
| 183 | 194 | ||
| @@ -196,7 +207,7 @@ static void rcu_preempt_note_context_switch(int cpu) | |||
| 196 | } | 207 | } |
| 197 | 208 | ||
| 198 | /* | 209 | /* |
| 199 | * Tree-preemptable RCU implementation for rcu_read_lock(). | 210 | * Tree-preemptible RCU implementation for rcu_read_lock(). |
| 200 | * Just increment ->rcu_read_lock_nesting, shared state will be updated | 211 | * Just increment ->rcu_read_lock_nesting, shared state will be updated |
| 201 | * if we block. | 212 | * if we block. |
| 202 | */ | 213 | */ |
| @@ -212,12 +223,9 @@ EXPORT_SYMBOL_GPL(__rcu_read_lock); | |||
| 212 | * for the specified rcu_node structure. If the caller needs a reliable | 223 | * for the specified rcu_node structure. If the caller needs a reliable |
| 213 | * answer, it must hold the rcu_node's ->lock. | 224 | * answer, it must hold the rcu_node's ->lock. |
| 214 | */ | 225 | */ |
| 215 | static int rcu_preempted_readers(struct rcu_node *rnp) | 226 | static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp) |
| 216 | { | 227 | { |
| 217 | int phase = rnp->gpnum & 0x1; | 228 | return rnp->gp_tasks != NULL; |
| 218 | |||
| 219 | return !list_empty(&rnp->blocked_tasks[phase]) || | ||
| 220 | !list_empty(&rnp->blocked_tasks[phase + 2]); | ||
| 221 | } | 229 | } |
| 222 | 230 | ||
| 223 | /* | 231 | /* |
| @@ -233,7 +241,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) | |||
| 233 | unsigned long mask; | 241 | unsigned long mask; |
| 234 | struct rcu_node *rnp_p; | 242 | struct rcu_node *rnp_p; |
| 235 | 243 | ||
| 236 | if (rnp->qsmask != 0 || rcu_preempted_readers(rnp)) { | 244 | if (rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) { |
| 237 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 245 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
| 238 | return; /* Still need more quiescent states! */ | 246 | return; /* Still need more quiescent states! */ |
| 239 | } | 247 | } |
| @@ -257,6 +265,21 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) | |||
| 257 | } | 265 | } |
| 258 | 266 | ||
| 259 | /* | 267 | /* |
| 268 | * Advance a ->blkd_tasks-list pointer to the next entry, instead | ||
| 269 | * returning NULL if at the end of the list. | ||
| 270 | */ | ||
| 271 | static struct list_head *rcu_next_node_entry(struct task_struct *t, | ||
| 272 | struct rcu_node *rnp) | ||
| 273 | { | ||
| 274 | struct list_head *np; | ||
| 275 | |||
| 276 | np = t->rcu_node_entry.next; | ||
| 277 | if (np == &rnp->blkd_tasks) | ||
| 278 | np = NULL; | ||
| 279 | return np; | ||
| 280 | } | ||
| 281 | |||
| 282 | /* | ||
| 260 | * Handle special cases during rcu_read_unlock(), such as needing to | 283 | * Handle special cases during rcu_read_unlock(), such as needing to |
| 261 | * notify RCU core processing or task having blocked during the RCU | ||
