diff options
| -rw-r--r-- | init/Kconfig | 1 | ||||
| -rw-r--r-- | kernel/rcutree.c | 17 | ||||
| -rw-r--r-- | kernel/rcutree.h | 2 |
3 files changed, 18 insertions, 2 deletions
diff --git a/init/Kconfig b/init/Kconfig index 9d3a7887a6d3..2d9b83104dcf 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -431,6 +431,7 @@ choice | |||
| 431 | config TREE_RCU | 431 | config TREE_RCU |
| 432 | bool "Tree-based hierarchical RCU" | 432 | bool "Tree-based hierarchical RCU" |
| 433 | depends on !PREEMPT && SMP | 433 | depends on !PREEMPT && SMP |
| 434 | select IRQ_WORK | ||
| 434 | help | 435 | help |
| 435 | This option selects the RCU implementation that is | 436 | This option selects the RCU implementation that is |
| 436 | designed for very large SMP system with hundreds or | 437 | designed for very large SMP system with hundreds or |
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 16ea67925015..b61d20c5ee7b 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
| @@ -1613,6 +1613,14 @@ static int __noreturn rcu_gp_kthread(void *arg) | |||
| 1613 | } | 1613 | } |
| 1614 | } | 1614 | } |
| 1615 | 1615 | ||
| 1616 | static void rsp_wakeup(struct irq_work *work) | ||
| 1617 | { | ||
| 1618 | struct rcu_state *rsp = container_of(work, struct rcu_state, wakeup_work); | ||
| 1619 | |||
| 1620 | /* Wake up rcu_gp_kthread() to start the grace period. */ | ||
| 1621 | wake_up(&rsp->gp_wq); | ||
| 1622 | } | ||
| 1623 | |||
| 1616 | /* | 1624 | /* |
| 1617 | * Start a new RCU grace period if warranted, re-initializing the hierarchy | 1625 | * Start a new RCU grace period if warranted, re-initializing the hierarchy |
| 1618 | * in preparation for detecting the next grace period. The caller must hold | 1626 | * in preparation for detecting the next grace period. The caller must hold |
| @@ -1637,8 +1645,12 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp, | |||
| 1637 | } | 1645 | } |
| 1638 | rsp->gp_flags = RCU_GP_FLAG_INIT; | 1646 | rsp->gp_flags = RCU_GP_FLAG_INIT; |
| 1639 | 1647 | ||
| 1640 | /* Wake up rcu_gp_kthread() to start the grace period. */ | 1648 | /* |
| 1641 | wake_up(&rsp->gp_wq); | 1649 | * We can't do wakeups while holding the rnp->lock, as that |
| 1650 | * could cause possible deadlocks with the rq->lock. Deter | ||
| 1651 | * the wakeup to interrupt context. | ||
| 1652 | */ | ||
| 1653 | irq_work_queue(&rsp->wakeup_work); | ||
| 1642 | } | 1654 | } |
| 1643 | 1655 | ||
| 1644 | /* | 1656 | /* |
| @@ -3235,6 +3247,7 @@ static void __init rcu_init_one(struct rcu_state *rsp, | |||
| 3235 | 3247 | ||
| 3236 | rsp->rda = rda; | 3248 | rsp->rda = rda; |
| 3237 | init_waitqueue_head(&rsp->gp_wq); | 3249 | init_waitqueue_head(&rsp->gp_wq); |
| 3250 | init_irq_work(&rsp->wakeup_work, rsp_wakeup); | ||
| 3238 | rnp = rsp->level[rcu_num_lvls - 1]; | 3251 | rnp = rsp->level[rcu_num_lvls - 1]; |
| 3239 | for_each_possible_cpu(i) { | 3252 | for_each_possible_cpu(i) { |
| 3240 | while (i > rnp->grphi) | 3253 | while (i > rnp->grphi) |
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index da77a8f57ff9..4df503470e42 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/threads.h> | 27 | #include <linux/threads.h> |
| 28 | #include <linux/cpumask.h> | 28 | #include <linux/cpumask.h> |
| 29 | #include <linux/seqlock.h> | 29 | #include <linux/seqlock.h> |
| 30 | #include <linux/irq_work.h> | ||
| 30 | 31 | ||
| 31 | /* | 32 | /* |
| 32 | * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and | 33 | * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and |
| @@ -442,6 +443,7 @@ struct rcu_state { | |||
| 442 | char *name; /* Name of structure. */ | 443 | char *name; /* Name of structure. */ |
| 443 | char abbr; /* Abbreviated name. */ | 444 | char abbr; /* Abbreviated name. */ |
| 444 | struct list_head flavors; /* List of RCU flavors. */ | 445 | struct list_head flavors; /* List of RCU flavors. */ |
| 446 | struct irq_work wakeup_work; /* Postponed wakeups */ | ||
| 445 | }; | 447 | }; |
| 446 | 448 | ||
| 447 | /* Values for rcu_state structure's gp_flags field. */ | 449 | /* Values for rcu_state structure's gp_flags field. */ |
