diff options
Diffstat (limited to 'kernel/rcutree_plugin.h')
-rw-r--r-- | kernel/rcutree_plugin.h | 50 |
1 files changed, 25 insertions, 25 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 1cee04f627eb..8ff1ba7b3c43 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
@@ -150,6 +150,16 @@ void __rcu_read_lock(void) | |||
150 | } | 150 | } |
151 | EXPORT_SYMBOL_GPL(__rcu_read_lock); | 151 | EXPORT_SYMBOL_GPL(__rcu_read_lock); |
152 | 152 | ||
153 | /* | ||
154 | * Check for preempted RCU readers blocking the current grace period | ||
155 | * for the specified rcu_node structure. If the caller needs a reliable | ||
156 | * answer, it must hold the rcu_node's ->lock. | ||
157 | */ | ||
158 | static int rcu_preempted_readers(struct rcu_node *rnp) | ||
159 | { | ||
160 | return !list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]); | ||
161 | } | ||
162 | |||
153 | static void rcu_read_unlock_special(struct task_struct *t) | 163 | static void rcu_read_unlock_special(struct task_struct *t) |
154 | { | 164 | { |
155 | int empty; | 165 | int empty; |
@@ -196,7 +206,7 @@ static void rcu_read_unlock_special(struct task_struct *t) | |||
196 | break; | 206 | break; |
197 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 207 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
198 | } | 208 | } |
199 | empty = list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]); | 209 | empty = !rcu_preempted_readers(rnp); |
200 | list_del_init(&t->rcu_node_entry); | 210 | list_del_init(&t->rcu_node_entry); |
201 | t->rcu_blocked_node = NULL; | 211 | t->rcu_blocked_node = NULL; |
202 | 212 | ||
@@ -207,7 +217,7 @@ static void rcu_read_unlock_special(struct task_struct *t) | |||
207 | * drop rnp->lock and restore irq. | 217 | * drop rnp->lock and restore irq. |
208 | */ | 218 | */ |
209 | if (!empty && rnp->qsmask == 0 && | 219 | if (!empty && rnp->qsmask == 0 && |
210 | list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1])) { | 220 | !rcu_preempted_readers(rnp)) { |
211 | struct rcu_node *rnp_p; | 221 | struct rcu_node *rnp_p; |
212 | 222 | ||
213 | if (rnp->parent == NULL) { | 223 | if (rnp->parent == NULL) { |
@@ -257,12 +267,12 @@ static void rcu_print_task_stall(struct rcu_node *rnp) | |||
257 | { | 267 | { |
258 | unsigned long flags; | 268 | unsigned long flags; |
259 | struct list_head *lp; | 269 | struct list_head *lp; |
260 | int phase = rnp->gpnum & 0x1; | 270 | int phase; |
261 | struct task_struct *t; | 271 | struct task_struct *t; |
262 | 272 | ||
263 | if (!list_empty(&rnp->blocked_tasks[phase])) { | 273 | if (rcu_preempted_readers(rnp)) { |
264 | spin_lock_irqsave(&rnp->lock, flags); | 274 | spin_lock_irqsave(&rnp->lock, flags); |
265 | phase = rnp->gpnum & 0x1; /* re-read under lock. */ | 275 | phase = rnp->gpnum & 0x1; |
266 | lp = &rnp->blocked_tasks[phase]; | 276 | lp = &rnp->blocked_tasks[phase]; |
267 | list_for_each_entry(t, lp, rcu_node_entry) | 277 | list_for_each_entry(t, lp, rcu_node_entry) |
268 | printk(" P%d", t->pid); | 278 | printk(" P%d", t->pid); |
@@ -281,20 +291,10 @@ static void rcu_print_task_stall(struct rcu_node *rnp) | |||
281 | */ | 291 | */ |
282 | static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp) | 292 | static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp) |
283 | { | 293 | { |
284 | WARN_ON_ONCE(!list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1])); | 294 | WARN_ON_ONCE(rcu_preempted_readers(rnp)); |
285 | WARN_ON_ONCE(rnp->qsmask); | 295 | WARN_ON_ONCE(rnp->qsmask); |
286 | } | 296 | } |
287 | 297 | ||
288 | /* | ||
289 | * Check for preempted RCU readers for the specified rcu_node structure. | ||
290 | * If the caller needs a reliable answer, it must hold the rcu_node's | ||
291 | * >lock. | ||
292 | */ | ||
293 | static int rcu_preempted_readers(struct rcu_node *rnp) | ||
294 | { | ||
295 | return !list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]); | ||
296 | } | ||
297 | |||
298 | #ifdef CONFIG_HOTPLUG_CPU | 298 | #ifdef CONFIG_HOTPLUG_CPU |
299 | 299 | ||
300 | /* | 300 | /* |
@@ -461,6 +461,15 @@ static void rcu_preempt_note_context_switch(int cpu) | |||
461 | { | 461 | { |
462 | } | 462 | } |
463 | 463 | ||
464 | /* | ||
465 | * Because preemptable RCU does not exist, there are never any preempted | ||
466 | * RCU readers. | ||
467 | */ | ||
468 | static int rcu_preempted_readers(struct rcu_node *rnp) | ||
469 | { | ||
470 | return 0; | ||
471 | } | ||
472 | |||
464 | #ifdef CONFIG_RCU_CPU_STALL_DETECTOR | 473 | #ifdef CONFIG_RCU_CPU_STALL_DETECTOR |
465 | 474 | ||
466 | /* | 475 | /* |
@@ -483,15 +492,6 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp) | |||
483 | WARN_ON_ONCE(rnp->qsmask); | 492 | WARN_ON_ONCE(rnp->qsmask); |
484 | } | 493 | } |
485 | 494 | ||
486 | /* | ||
487 | * Because preemptable RCU does not exist, there are never any preempted | ||
488 | * RCU readers. | ||
489 | */ | ||
490 | static int rcu_preempted_readers(struct rcu_node *rnp) | ||
491 | { | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | #ifdef CONFIG_HOTPLUG_CPU | 495 | #ifdef CONFIG_HOTPLUG_CPU |
496 | 496 | ||
497 | /* | 497 | /* |