diff options
Diffstat (limited to 'kernel/rcu/update.c')
| -rw-r--r-- | kernel/rcu/update.c | 7 | 
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 3e888cd5a594..f0d8322bc3ec 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -528,6 +528,7 @@ static int rcu_task_stall_timeout __read_mostly = HZ * 60 * 10;  module_param(rcu_task_stall_timeout, int, 0644);  static void rcu_spawn_tasks_kthread(void); +static struct task_struct *rcu_tasks_kthread_ptr;  /*   * Post an RCU-tasks callback.  First call must be from process context @@ -537,6 +538,7 @@ void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func)  {  	unsigned long flags;  	bool needwake; +	bool havetask = READ_ONCE(rcu_tasks_kthread_ptr);  	rhp->next = NULL;  	rhp->func = func; @@ -545,7 +547,9 @@ void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func)  	*rcu_tasks_cbs_tail = rhp;  	rcu_tasks_cbs_tail = &rhp->next;  	raw_spin_unlock_irqrestore(&rcu_tasks_cbs_lock, flags); -	if (needwake) { +	/* We can't create the thread unless interrupts are enabled. */ +	if ((needwake && havetask) || +	    (!havetask && !irqs_disabled_flags(flags))) {  		rcu_spawn_tasks_kthread();  		wake_up(&rcu_tasks_cbs_wq);  	} @@ -790,7 +794,6 @@ static int __noreturn rcu_tasks_kthread(void *arg)  static void rcu_spawn_tasks_kthread(void)  {  	static DEFINE_MUTEX(rcu_tasks_kthread_mutex); -	static struct task_struct *rcu_tasks_kthread_ptr;  	struct task_struct *t;  	if (READ_ONCE(rcu_tasks_kthread_ptr)) {  |