diff options
| author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-03-27 16:02:08 -0700 | 
|---|---|---|
| committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-05-02 14:43:23 -0700 | 
| commit | 616c310e83b872024271c915c1b9ab505b9efad9 (patch) | |
| tree | 1339bc7b3bef920b4641a5af2f182e9dfa2a6632 /kernel | |
| parent | 66f75a5d028beaf67c931435fdc3e7823125730c (diff) | |
rcu: Move PREEMPT_RCU preemption to switch_to() invocation
Currently, PREEMPT_RCU readers are enqueued upon entry to the scheduler.
This is inefficient because enqueuing is required only if there is a
context switch, and entry to the scheduler does not guarantee a context
switch.
The commit therefore moves the enqueuing to immediately precede the
call to switch_to() from the scheduler.
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Tested-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/rcutree.c | 1 | ||||
| -rw-r--r-- | kernel/rcutree.h | 1 | ||||
| -rw-r--r-- | kernel/rcutree_plugin.h | 14 | ||||
| -rw-r--r-- | kernel/sched/core.c | 1 | 
4 files changed, 4 insertions, 13 deletions
| diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 1050d6d3922c..61351505ec78 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -192,7 +192,6 @@ void rcu_note_context_switch(int cpu)  {  	trace_rcu_utilization("Start context switch");  	rcu_sched_qs(cpu); -	rcu_preempt_note_context_switch(cpu);  	trace_rcu_utilization("End context switch");  }  EXPORT_SYMBOL_GPL(rcu_note_context_switch); diff --git a/kernel/rcutree.h b/kernel/rcutree.h index cdd1be0a4072..d6b70b08a01a 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -423,7 +423,6 @@ DECLARE_PER_CPU(char, rcu_cpu_has_work);  /* Forward declarations for rcutree_plugin.h */  static void rcu_bootup_announce(void);  long rcu_batches_completed(void); -static void rcu_preempt_note_context_switch(int cpu);  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, diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index c023464816be..b1ac22e6fa31 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -153,7 +153,7 @@ static void rcu_preempt_qs(int cpu)   *   * Caller must disable preemption.   */ -static void rcu_preempt_note_context_switch(int cpu) +void rcu_preempt_note_context_switch(void)  {  	struct task_struct *t = current;  	unsigned long flags; @@ -164,7 +164,7 @@ static void rcu_preempt_note_context_switch(int cpu)  	    (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {  		/* Possibly blocking in an RCU read-side critical section. */ -		rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu); +		rdp = __this_cpu_ptr(rcu_preempt_state.rda);  		rnp = rdp->mynode;  		raw_spin_lock_irqsave(&rnp->lock, flags);  		t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; @@ -228,7 +228,7 @@ static void rcu_preempt_note_context_switch(int cpu)  	 * means that we continue to block the current grace period.  	 */  	local_irq_save(flags); -	rcu_preempt_qs(cpu); +	rcu_preempt_qs(smp_processor_id());  	local_irq_restore(flags);  } @@ -1018,14 +1018,6 @@ void rcu_force_quiescent_state(void)  EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);  /* - * Because preemptible RCU does not exist, we never have to check for - * CPUs being in quiescent states. - */ -static void rcu_preempt_note_context_switch(int cpu) -{ -} - -/*   * Because preemptible RCU does not exist, there are never any preempted   * RCU readers.   */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 4603b9d8f30a..5d89eb93f7e4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2083,6 +2083,7 @@ context_switch(struct rq *rq, struct task_struct *prev,  #endif  	/* Here we just switch the register state and the stack. */ +	rcu_switch_from(prev);  	switch_to(prev, next, prev);  	barrier(); | 
