mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
rcu: Replace the rcu_barrier enum with pointer to call_rcu*() function
The rcu_barrier enum causes several problems: (1) you have to define the enum somewhere, and there is no convenient place, (2) the difference between TREE_RCU and TREE_PREEMPT_RCU causes problems when you need to map from rcu_barrier enum to struct rcu_state, (3) the switch statement are large, and (4) TINY_RCU really needs a different rcu_barrier() than do the treercu implementations. So replace it with a functionally equivalent but cleaner function pointer abstraction. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: akpm@linux-foundation.org Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com LKML-Reference: <12541998232366-git-send-email-> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
a0b6c9a78c
commit
135c8aea55
@ -53,12 +53,6 @@ struct lockdep_map rcu_lock_map =
|
||||
EXPORT_SYMBOL_GPL(rcu_lock_map);
|
||||
#endif
|
||||
|
||||
enum rcu_barrier {
|
||||
RCU_BARRIER_STD,
|
||||
RCU_BARRIER_BH,
|
||||
RCU_BARRIER_SCHED,
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
|
||||
static atomic_t rcu_barrier_cpu_count;
|
||||
static DEFINE_MUTEX(rcu_barrier_mutex);
|
||||
@ -184,19 +178,12 @@ static void rcu_barrier_func(void *type)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct rcu_head *head = &per_cpu(rcu_barrier_head, cpu);
|
||||
void (*call_rcu_func)(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *head));
|
||||
|
||||
atomic_inc(&rcu_barrier_cpu_count);
|
||||
switch ((enum rcu_barrier)type) {
|
||||
case RCU_BARRIER_STD:
|
||||
call_rcu(head, rcu_barrier_callback);
|
||||
break;
|
||||
case RCU_BARRIER_BH:
|
||||
call_rcu_bh(head, rcu_barrier_callback);
|
||||
break;
|
||||
case RCU_BARRIER_SCHED:
|
||||
call_rcu_sched(head, rcu_barrier_callback);
|
||||
break;
|
||||
}
|
||||
call_rcu_func = type;
|
||||
call_rcu_func(head, rcu_barrier_callback);
|
||||
}
|
||||
|
||||
static inline void wait_migrated_callbacks(void)
|
||||
@ -209,7 +196,8 @@ static inline void wait_migrated_callbacks(void)
|
||||
* Orchestrate the specified type of RCU barrier, waiting for all
|
||||
* RCU callbacks of the specified type to complete.
|
||||
*/
|
||||
static void _rcu_barrier(enum rcu_barrier type)
|
||||
static void _rcu_barrier(void (*call_rcu_func)(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *head)))
|
||||
{
|
||||
BUG_ON(in_interrupt());
|
||||
/* Take cpucontrol mutex to protect against CPU hotplug */
|
||||
@ -225,7 +213,7 @@ static void _rcu_barrier(enum rcu_barrier type)
|
||||
* early.
|
||||
*/
|
||||
atomic_set(&rcu_barrier_cpu_count, 1);
|
||||
on_each_cpu(rcu_barrier_func, (void *)type, 1);
|
||||
on_each_cpu(rcu_barrier_func, (void *)call_rcu_func, 1);
|
||||
if (atomic_dec_and_test(&rcu_barrier_cpu_count))
|
||||
complete(&rcu_barrier_completion);
|
||||
wait_for_completion(&rcu_barrier_completion);
|
||||
@ -238,7 +226,7 @@ static void _rcu_barrier(enum rcu_barrier type)
|
||||
*/
|
||||
void rcu_barrier(void)
|
||||
{
|
||||
_rcu_barrier(RCU_BARRIER_STD);
|
||||
_rcu_barrier(call_rcu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_barrier);
|
||||
|
||||
@ -247,7 +235,7 @@ EXPORT_SYMBOL_GPL(rcu_barrier);
|
||||
*/
|
||||
void rcu_barrier_bh(void)
|
||||
{
|
||||
_rcu_barrier(RCU_BARRIER_BH);
|
||||
_rcu_barrier(call_rcu_bh);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_barrier_bh);
|
||||
|
||||
@ -256,7 +244,7 @@ EXPORT_SYMBOL_GPL(rcu_barrier_bh);
|
||||
*/
|
||||
void rcu_barrier_sched(void)
|
||||
{
|
||||
_rcu_barrier(RCU_BARRIER_SCHED);
|
||||
_rcu_barrier(call_rcu_sched);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_barrier_sched);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user