lkml.org 
[lkml]   [2007]   [Apr]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] [35/35] i386: Simplify smp_call_function*() by using common implementation
    Date

    From: Jeremy Fitzhardinge <jeremy@goop.org>
    Subject: Simplify smp_call_function*() by using common implementation

    smp_call_function and smp_call_function_single are almost complete
    duplicates of the same logic. This patch combines them by
    implementing them in terms of the more general
    smp_call_function_mask().

    Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
    Signed-off-by: Andi Kleen <ak@suse.de>
    Cc: Stephane Eranian <eranian@hpl.hp.com>
    Cc: Andrew Morton <akpm@osdl.org>
    Cc: Andi Kleen <ak@suse.de>
    Cc: "Randy.Dunlap" <rdunlap@xenotime.net>
    Cc: Ingo Molnar <mingo@elte.hu>

    ---
    arch/i386/kernel/smp.c | 173 +++++++++++++++++++++++++++----------------------
    1 file changed, 96 insertions(+), 77 deletions(-)
    ===================================================================
    Index: linux/arch/i386/kernel/smp.c
    ===================================================================
    --- linux.orig/arch/i386/kernel/smp.c
    +++ linux/arch/i386/kernel/smp.c
    @@ -546,34 +546,124 @@ static void __smp_call_function(void (*f
    cpu_relax();
    }

    +
    /**
    - * smp_call_function(): Run a function on all other CPUs.
    + * smp_call_function_mask(): Run a function on a set of other CPUs.
    + * @mask: The set of cpus to run on. Must not include the current cpu.
    * @func: The function to run. This must be fast and non-blocking.
    * @info: An arbitrary pointer to pass to the function.
    - * @nonatomic: currently unused.
    * @wait: If true, wait (atomically) until function has completed on other CPUs.
    *
    * Returns 0 on success, else a negative status code. Does not return until
    - * remote CPUs are nearly ready to execute <<func>> or are or have executed.
    + * remote CPUs are nearly ready to execute <<func>> or are or have finished.
    *
    * You must not call this function with disabled interrupts or from a
    * hardware interrupt handler or from a bottom half handler.
    */
    -int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
    - int wait)
    +int smp_call_function_mask(cpumask_t mask,
    + void (*func)(void *), void *info,
    + int wait)
    {
    + struct call_data_struct data;
    + cpumask_t allbutself;
    + int cpus;
    +
    /* Can deadlock when called with interrupts disabled */
    WARN_ON(irqs_disabled());

    /* Holding any lock stops cpus from going down. */
    spin_lock(&call_lock);
    - __smp_call_function(func, info, nonatomic, wait);
    +
    + allbutself = cpu_online_map;
    + cpu_clear(smp_processor_id(), allbutself);
    +
    + cpus_and(mask, mask, allbutself);
    + cpus = cpus_weight(mask);
    +
    + if (!cpus) {
    + spin_unlock(&call_lock);
    + return 0;
    + }
    +
    + data.func = func;
    + data.info = info;
    + atomic_set(&data.started, 0);
    + data.wait = wait;
    + if (wait)
    + atomic_set(&data.finished, 0);
    +
    + call_data = &data;
    + mb();
    +
    + /* Send a message to other CPUs */
    + if (cpus_equal(mask, allbutself))
    + send_IPI_allbutself(CALL_FUNCTION_VECTOR);
    + else
    + send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
    +
    + /* Wait for response */
    + while (atomic_read(&data.started) != cpus)
    + cpu_relax();
    +
    + if (wait)
    + while (atomic_read(&data.finished) != cpus)
    + cpu_relax();
    spin_unlock(&call_lock);

    return 0;
    }
    +
    +/**
    + * smp_call_function(): Run a function on all other CPUs.
    + * @func: The function to run. This must be fast and non-blocking.
    + * @info: An arbitrary pointer to pass to the function.
    + * @nonatomic: currently unused.
    + * @wait: If true, wait (atomically) until function has completed on other CPUs.
    + *
    + * Returns 0 on success, else a negative status code. Does not return until
    + * remote CPUs are nearly ready to execute <<func>> or are or have executed.
    + *
    + * You must not call this function with disabled interrupts or from a
    + * hardware interrupt handler or from a bottom half handler.
    + */
    +int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
    + int wait)
    +{
    + return smp_call_function_mask(cpu_online_map, func, info, wait);
    +}
    EXPORT_SYMBOL(smp_call_function);

    +/*
    + * smp_call_function_single - Run a function on another CPU
    + * @func: The function to run. This must be fast and non-blocking.
    + * @info: An arbitrary pointer to pass to the function.
    + * @nonatomic: Currently unused.
    + * @wait: If true, wait until function has completed on other CPUs.
    + *
    + * Retrurns 0 on success, else a negative status code.
    + *
    + * Does not return until the remote CPU is nearly ready to execute <func>
    + * or is or has executed.
    + */
    +int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
    + int nonatomic, int wait)
    +{
    + /* prevent preemption and reschedule on another processor */
    + int ret;
    + int me = get_cpu();
    + if (cpu == me) {
    + WARN_ON(1);
    + put_cpu();
    + return -EBUSY;
    + }
    +
    + ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait);
    +
    + put_cpu();
    + return ret;
    +}
    +EXPORT_SYMBOL(smp_call_function_single);
    +
    static void stop_this_cpu (void * dummy)
    {
    local_irq_disable();
    @@ -641,77 +731,6 @@ fastcall void smp_call_function_interrup
    }
    }

    -/*
    - * this function sends a 'generic call function' IPI to one other CPU
    - * in the system.
    - *
    - * cpu is a standard Linux logical CPU number.
    - */
    -static void
    -__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
    - int nonatomic, int wait)
    -{
    - struct call_data_struct data;
    - int cpus = 1;
    -
    - data.func = func;
    - data.info = info;
    - atomic_set(&data.started, 0);
    - data.wait = wait;
    - if (wait)
    - atomic_set(&data.finished, 0);
    -
    - call_data = &data;
    - wmb();
    - /* Send a message to all other CPUs and wait for them to respond */
    - send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
    -
    - /* Wait for response */
    - while (atomic_read(&data.started) != cpus)
    - cpu_relax();
    -
    - if (!wait)
    - return;
    -
    - while (atomic_read(&data.finished) != cpus)
    - cpu_relax();
    -}
    -
    -/*
    - * smp_call_function_single - Run a function on another CPU
    - * @func: The function to run. This must be fast and non-blocking.
    - * @info: An arbitrary pointer to pass to the function.
    - * @nonatomic: Currently unused.
    - * @wait: If true, wait until function has completed on other CPUs.
    - *
    - * Retrurns 0 on success, else a negative status code.
    - *
    - * Does not return until the remote CPU is nearly ready to execute <func>
    - * or is or has executed.
    - */
    -
    -int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
    - int nonatomic, int wait)
    -{
    - /* prevent preemption and reschedule on another processor */
    - int me = get_cpu();
    - if (cpu == me) {
    - WARN_ON(1);
    - put_cpu();
    - return -EBUSY;
    - }
    -
    - /* Can deadlock when called with interrupts disabled */
    - WARN_ON(irqs_disabled());
    -
    - spin_lock_bh(&call_lock);
    - __smp_call_function_single(cpu, func, info, nonatomic, wait);
    - spin_unlock_bh(&call_lock);
    - put_cpu();
    - return 0;
    -}
    -EXPORT_SYMBOL(smp_call_function_single);
    -
    static int convert_apicid_to_cpu(int apic_id)
    {
    int i;
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2007-04-28 20:15    [from the cache]
    ©2003-2014 Jasper Spaans. hosted at Digital Ocean