smp: Remove wait argument from __smp_call_function_single()
authorFrederic Weisbecker <fweisbec@gmail.com>
Mon, 24 Feb 2014 15:40:01 +0000 (16:40 +0100)
committerJens Axboe <axboe@fb.com>
Mon, 24 Feb 2014 22:47:09 +0000 (14:47 -0800)
The main point of calling __smp_call_function_single() is to send
an IPI in a pure asynchronous way. By embedding a csd in an object,
a caller can send the IPI without waiting for a previous one to complete
as is required by smp_call_function_single() for example. As such,
sending this kind of IPI can be safe even when irqs are disabled.

This flexibility comes at the expense of the caller who then needs to
synchronize the csd lifecycle by himself and make sure that IPIs on a
single csd are serialized.

This is how __smp_call_function_single() works when wait = 0 and this
usecase is relevant.

Now there don't seem to be any usecase with wait = 1 that can't be
covered by smp_call_function_single() instead, which is safer. Lets look
at the two possible scenario:

1) The user calls __smp_call_function_single(wait = 1) on a csd embedded
   in an object. It looks like a nice and convenient pattern at the first
   sight because we can then retrieve the object from the IPI handler easily.

   But actually it is a waste of memory space in the object since the csd
   can be allocated from the stack by smp_call_function_single(wait = 1)
   and the object can be passed an the IPI argument.

   Besides that, embedding the csd in an object is more error prone
   because the caller must take care of the serialization of the IPIs
   for this csd.

2) The user calls __smp_call_function_single(wait = 1) on a csd that
   is allocated on the stack. It's ok but smp_call_function_single()
   can do it as well and it already takes care of the allocation on the
   stack. Again it's more simple and less error prone.

Therefore, using the underscore prepend API version with wait = 1
is a bad pattern and a sign that the caller can do safer and more
simple.

There was a single user of that which has just been converted.
So lets remove this option to discourage further users.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Jens Axboe <axboe@fb.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
block/blk-mq.c
block/blk-softirq.c
drivers/cpuidle/coupled.c
include/linux/smp.h
kernel/sched/core.c
kernel/smp.c
kernel/up.c
net/core/dev.c

index 1fa9dd153fde22a976483ef3b5da3ec39f0f458e..62154edf1489bc75fc0e6bcd2fb054d9f9ac2936 100644 (file)
@@ -353,7 +353,7 @@ void __blk_mq_complete_request(struct request *rq)
                rq->csd.func = __blk_mq_complete_request_remote;
                rq->csd.info = rq;
                rq->csd.flags = 0;
-               __smp_call_function_single(ctx->cpu, &rq->csd, 0);
+               __smp_call_function_single(ctx->cpu, &rq->csd);
        } else {
                rq->q->softirq_done_fn(rq);
        }
index b5c37d96cf0e4813c349159cdb4664c712824233..6345b7ebd0dff743a4491cacf690e53ce29fe4a5 100644 (file)
@@ -70,7 +70,7 @@ static int raise_blk_irq(int cpu, struct request *rq)
                data->info = rq;
                data->flags = 0;
 
-               __smp_call_function_single(cpu, data, 0);
+               __smp_call_function_single(cpu, data);
                return 0;
        }
 
index e952936418d0f4de89251c8fd64677c14e5a8889..04115947accc3a49e86e3f3206f928734981a812 100644 (file)
@@ -323,7 +323,7 @@ static void cpuidle_coupled_poke(int cpu)
        struct call_single_data *csd = &per_cpu(cpuidle_coupled_poke_cb, cpu);
 
        if (!cpumask_test_and_set_cpu(cpu, &cpuidle_coupled_poke_pending))
-               __smp_call_function_single(cpu, csd, 0);
+               __smp_call_function_single(cpu, csd);
 }
 
 /**
index c39074c794c5db555a815dfc273e434e8e135f20..b410a1f232812933c05e0ad072a68c2736699384 100644 (file)
@@ -50,7 +50,7 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
                smp_call_func_t func, void *info, bool wait,
                gfp_t gfp_flags);
 
-int __smp_call_function_single(int cpu, struct call_single_data *csd, int wait);
+int __smp_call_function_single(int cpu, struct call_single_data *csd);
 
 #ifdef CONFIG_SMP
 
index b46131ef6aab0ac48149482a03f8354330adf188..eba3d84765f3fbf1a6316e3a85cedcff40c374e8 100644 (file)
@@ -432,7 +432,7 @@ void hrtick_start(struct rq *rq, u64 delay)
        if (rq == this_rq()) {
                __hrtick_restart(rq);
        } else if (!rq->hrtick_csd_pending) {
-               __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 0);
+               __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd);
                rq->hrtick_csd_pending = 1;
        }
 }
index fa04ab938e5212e5c1f28e9309e0d1165067cff8..b76763189752fe1303d35b8c9f8508014a174486 100644 (file)
@@ -241,29 +241,18 @@ EXPORT_SYMBOL(smp_call_function_single);
  * __smp_call_function_single(): Run a function on a specific CPU
  * @cpu: The CPU to run on.
  * @csd: Pre-allocated and setup data structure
- * @wait: If true, wait until function has completed on specified CPU.
  *
  * Like smp_call_function_single(), but allow caller to pass in a
  * pre-allocated data structure. Useful for embedding @data inside
  * other structures, for instance.
  */
-int __smp_call_function_single(int cpu, struct call_single_data *csd, int wait)
+int __smp_call_function_single(int cpu, struct call_single_data *csd)
 {
        int err = 0;
-       int this_cpu;
 
-       this_cpu = get_cpu();
-       /*
-        * Can deadlock when called with interrupts disabled.
-        * We allow cpu's that are not yet online though, as no one else can
-        * send smp call function interrupt to this cpu and as such deadlocks
-        * can't happen.
-        */
-       WARN_ON_ONCE(cpu_online(this_cpu) && wait && irqs_disabled()
-                    && !oops_in_progress);
-
-       err = generic_exec_single(cpu, csd, csd->func, csd->info, wait);
-       put_cpu();
+       preempt_disable();
+       err = generic_exec_single(cpu, csd, csd->func, csd->info, 0);
+       preempt_enable();
 
        return err;
 }
index cdf03d16840e0d33304ce48d20ad10412c8ea0e3..4e199d4cef8e6edba601a2944cc85172aa2d4c4c 100644 (file)
@@ -22,8 +22,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
 }
 EXPORT_SYMBOL(smp_call_function_single);
 
-int __smp_call_function_single(int cpu, struct call_single_data *csd,
-                              int wait)
+int __smp_call_function_single(int cpu, struct call_single_data *csd)
 {
        unsigned long flags;
 
index 4ad1b78c9c7790a84d4e697da1e025213e3a0eae..d1298128bff49f793a447e07bd6f7e2fb96b91f9 100644 (file)
@@ -4129,7 +4129,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd)
 
                        if (cpu_online(remsd->cpu))
                                __smp_call_function_single(remsd->cpu,
-                                                          &remsd->csd, 0);
+                                                          &remsd->csd);
                        remsd = next;
                }
        } else
This page took 0.039428 seconds and 5 git commands to generate.