All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gilad Ben-Yossef <gilad@benyossef.com>
To: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org, Chris Metcalf <cmetcalf@tilera.com>,
	Christoph Lameter <cl@linux-foundation.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Russell King <linux@arm.linux.org.uk>,
	linux-mm@kvack.org, Pekka Enberg <penberg@kernel.org>,
	Matt Mackall <mpm@selenic.com>,
	Sasha Levin <levinsasha928@gmail.com>,
	Rik van Riel <riel@redhat.com>, Andi Kleen <andi@firstfloor.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	linux-fsdevel@vger.kernel.org, Avi Kivity <avi@redhat.com>,
	Michal Nazarewicz <mina86@mina86.com>,
	Kosaki Motohiro <kosaki.motohiro@gmail.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Milton Miller <miltonm@bga.com>
Subject: Re: [PATCH v8 4/8] smp: add func to IPI cpus based on parameter func
Date: Sun, 5 Feb 2012 17:46:41 +0200	[thread overview]
Message-ID: <CAOtvUMdqpwOedhZHq6QpUnDyg1FzfK_K3=9HQujjoN9yU3XWnA@mail.gmail.com> (raw)
In-Reply-To: <4F2EA206.3000707@linux.vnet.ibm.com>

On Sun, Feb 5, 2012 at 5:36 PM, Srivatsa S. Bhat
<srivatsa.bhat@linux.vnet.ibm.com> wrote:
> On 02/05/2012 07:18 PM, Gilad Ben-Yossef wrote:
>
>> Add the on_each_cpu_cond() function that wraps on_each_cpu_mask()
>> and calculates the cpumask of cpus to IPI by calling a function supplied
>> as a parameter in order to determine whether to IPI each specific cpu.
>>
>> The function works around allocation failure of cpumask variable in
>> CONFIG_CPUMASK_OFFSTACK=y by itereating over cpus sending an IPI a
>> time via smp_call_function_single().
>>
>> The function is useful since it allows to seperate the specific
>> code that decided in each case whether to IPI a specific cpu for
>> a specific request from the common boilerplate code of handling
>> creating the mask, handling failures etc.
>>
>> Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
> ...
>> diff --git a/include/linux/smp.h b/include/linux/smp.h
>> index d0adb78..da4d034 100644
>> --- a/include/linux/smp.h
>> +++ b/include/linux/smp.h
>> @@ -109,6 +109,15 @@ void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
>>               void *info, bool wait);
>>
>>  /*
>> + * Call a function on each processor for which the supplied function
>> + * cond_func returns a positive value. This may include the local
>> + * processor.
>> + */
>> +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);
>> +
>> +/*
>>   * Mark the boot cpu "online" so that it can call console drivers in
>>   * printk() and can access its per-cpu storage.
>>   */
>> @@ -153,6 +162,21 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
>>                       local_irq_enable();             \
>>               }                                       \
>>       } while (0)
>> +/*
>> + * Preemption is disabled here to make sure the
>> + * cond_func is called under the same condtions in UP
>> + * and SMP.
>> + */
>> +#define on_each_cpu_cond(cond_func, func, info, wait, gfp_flags) \
>> +     do {                                            \
>> +             preempt_disable();                      \
>> +             if (cond_func(0, info)) {               \
>> +                     local_irq_disable();            \
>> +                     (func)(info);                   \
>> +                     local_irq_enable();             \
>> +             }                                       \
>> +             preempt_enable();                       \
>> +     } while (0)
>>
>>  static inline void smp_send_reschedule(int cpu) { }
>>  #define num_booting_cpus()                   1
>> diff --git a/kernel/smp.c b/kernel/smp.c
>> index a081e6c..28cbcc5 100644
>> --- a/kernel/smp.c
>> +++ b/kernel/smp.c
>> @@ -730,3 +730,63 @@ void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
>>       put_cpu();
>>  }
>>  EXPORT_SYMBOL(on_each_cpu_mask);
>> +
>> +/*
>> + * on_each_cpu_cond(): Call a function on each processor for which
>> + * the supplied function cond_func returns true, optionally waiting
>> + * for all the required CPUs to finish. This may include the local
>> + * processor.
>> + * @cond_func:       A callback function that is passed a cpu id and
>> + *           the the info parameter. The function is called
>> + *           with preemption disabled. The function should
>> + *           return a blooean value indicating whether to IPI
>> + *           the specified CPU.
>> + * @func:    The function to run on all applicable CPUs.
>> + *           This must be fast and non-blocking.
>> + * @info:    An arbitrary pointer to pass to both functions.
>> + * @wait:    If true, wait (atomically) until function has
>> + *           completed on other CPUs.
>> + * @gfp_flags:       GFP flags to use when allocating the cpumask
>> + *           used internally by the function.
>> + *
>> + * The function might sleep if the GFP flags indicates a non
>> + * atomic allocation is allowed.
>> + *
>> + * Preemption is disabled to protect against a hotplug event.
>
>
> Well, disabling preemption protects us only against CPU offline right?
> (because we use the stop_machine thing during cpu offline).
>
> What about CPU online?
>
> Just to cross-check my understanding of the code with the existing
> documentation on CPU hotplug, I looked up Documentation/cpu-hotplug.txt
> and this is what I found:
>
> "If you merely need to avoid cpus going away, you could also use
> preempt_disable() and preempt_enable() for those sections....
> ...The preempt_disable() will work as long as stop_machine_run() is used
> to take a cpu down."
>
> So even this only talks about using preempt_disable() to prevent CPU offline,
> not CPU online. Or, am I missing something?

You are not missing anything, this is simply a bad choice of words on my part.
Thank you for pointing this out.

I should write:

" Preemption is disabled to protect against CPU going offline but not online.
  CPUs going online during the call will not be seen or sent an IPI."

Protecting against CPU going online during the function is useless
since they might
as well go online right after the call is finished, so the caller has
to take care of it, if they
cares.

Thanks,
Gilad

>
>> + *
>> + * You must not call this function with disabled interrupts or
>> + * from a hardware interrupt handler or from a bottom half handler.
>> + */
>> +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)
>> +{
>> +     cpumask_var_t cpus;
>> +     int cpu, ret;
>> +
>> +     might_sleep_if(gfp_flags & __GFP_WAIT);
>> +
>> +     if (likely(zalloc_cpumask_var(&cpus, (gfp_flags|__GFP_NOWARN)))) {
>> +             preempt_disable();
>> +             for_each_online_cpu(cpu)
>> +                     if (cond_func(cpu, info))
>> +                             cpumask_set_cpu(cpu, cpus);
>
>
> IOW, what prevents a new CPU from becoming online at this point?
>
>> +             on_each_cpu_mask(cpus, func, info, wait);
>> +             preempt_enable();
>> +             free_cpumask_var(cpus);
>> +     } else {
>> +             /*
>> +              * No free cpumask, bother. No matter, we'll
>> +              * just have to IPI them one by one.
>> +              */
>> +             preempt_disable();
>> +             for_each_online_cpu(cpu)
>> +                     if (cond_func(cpu, info)) {
>> +                             ret = smp_call_function_single(cpu, func,
>> +                                                             info, wait);
>> +                             WARN_ON_ONCE(!ret);
>> +                     }
>> +             preempt_enable();
>> +     }
>> +}
>> +EXPORT_SYMBOL(on_each_cpu_cond);
>
>
>
> Regards,
> Srivatsa S. Bhat
>



-- 
Gilad Ben-Yossef
Chief Coffee Drinker
gilad@benyossef.com
Israel Cell: +972-52-8260388
US Cell: +1-973-8260388
http://benyossef.com

"If you take a class in large-scale robotics, can you end up in a
situation where the homework eats your dog?"
 -- Jean-Baptiste Queru

WARNING: multiple messages have this Message-ID (diff)
From: Gilad Ben-Yossef <gilad@benyossef.com>
To: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org, Chris Metcalf <cmetcalf@tilera.com>,
	Christoph Lameter <cl@linux-foundation.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Russell King <linux@arm.linux.org.uk>,
	linux-mm@kvack.org, Pekka Enberg <penberg@kernel.org>,
	Matt Mackall <mpm@selenic.com>,
	Sasha Levin <levinsasha928@gmail.com>,
	Rik van Riel <riel@redhat.com>, Andi Kleen <andi@firstfloor.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	linux-fsdevel@vger.kernel.org, Avi Kivity <avi@redhat.com>,
	Michal Nazarewicz <mina86@mina86.com>,
	Kosaki Motohiro <kosaki.motohiro@gmail.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Milton Miller <miltonm@bga.com>
Subject: Re: [PATCH v8 4/8] smp: add func to IPI cpus based on parameter func
Date: Sun, 5 Feb 2012 17:46:41 +0200	[thread overview]
Message-ID: <CAOtvUMdqpwOedhZHq6QpUnDyg1FzfK_K3=9HQujjoN9yU3XWnA@mail.gmail.com> (raw)
In-Reply-To: <4F2EA206.3000707@linux.vnet.ibm.com>

On Sun, Feb 5, 2012 at 5:36 PM, Srivatsa S. Bhat
<srivatsa.bhat@linux.vnet.ibm.com> wrote:
> On 02/05/2012 07:18 PM, Gilad Ben-Yossef wrote:
>
>> Add the on_each_cpu_cond() function that wraps on_each_cpu_mask()
>> and calculates the cpumask of cpus to IPI by calling a function supplied
>> as a parameter in order to determine whether to IPI each specific cpu.
>>
>> The function works around allocation failure of cpumask variable in
>> CONFIG_CPUMASK_OFFSTACK=y by itereating over cpus sending an IPI a
>> time via smp_call_function_single().
>>
>> The function is useful since it allows to seperate the specific
>> code that decided in each case whether to IPI a specific cpu for
>> a specific request from the common boilerplate code of handling
>> creating the mask, handling failures etc.
>>
>> Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
> ...
>> diff --git a/include/linux/smp.h b/include/linux/smp.h
>> index d0adb78..da4d034 100644
>> --- a/include/linux/smp.h
>> +++ b/include/linux/smp.h
>> @@ -109,6 +109,15 @@ void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
>>               void *info, bool wait);
>>
>>  /*
>> + * Call a function on each processor for which the supplied function
>> + * cond_func returns a positive value. This may include the local
>> + * processor.
>> + */
>> +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);
>> +
>> +/*
>>   * Mark the boot cpu "online" so that it can call console drivers in
>>   * printk() and can access its per-cpu storage.
>>   */
>> @@ -153,6 +162,21 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
>>                       local_irq_enable();             \
>>               }                                       \
>>       } while (0)
>> +/*
>> + * Preemption is disabled here to make sure the
>> + * cond_func is called under the same condtions in UP
>> + * and SMP.
>> + */
>> +#define on_each_cpu_cond(cond_func, func, info, wait, gfp_flags) \
>> +     do {                                            \
>> +             preempt_disable();                      \
>> +             if (cond_func(0, info)) {               \
>> +                     local_irq_disable();            \
>> +                     (func)(info);                   \
>> +                     local_irq_enable();             \
>> +             }                                       \
>> +             preempt_enable();                       \
>> +     } while (0)
>>
>>  static inline void smp_send_reschedule(int cpu) { }
>>  #define num_booting_cpus()                   1
>> diff --git a/kernel/smp.c b/kernel/smp.c
>> index a081e6c..28cbcc5 100644
>> --- a/kernel/smp.c
>> +++ b/kernel/smp.c
>> @@ -730,3 +730,63 @@ void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
>>       put_cpu();
>>  }
>>  EXPORT_SYMBOL(on_each_cpu_mask);
>> +
>> +/*
>> + * on_each_cpu_cond(): Call a function on each processor for which
>> + * the supplied function cond_func returns true, optionally waiting
>> + * for all the required CPUs to finish. This may include the local
>> + * processor.
>> + * @cond_func:       A callback function that is passed a cpu id and
>> + *           the the info parameter. The function is called
>> + *           with preemption disabled. The function should
>> + *           return a blooean value indicating whether to IPI
>> + *           the specified CPU.
>> + * @func:    The function to run on all applicable CPUs.
>> + *           This must be fast and non-blocking.
>> + * @info:    An arbitrary pointer to pass to both functions.
>> + * @wait:    If true, wait (atomically) until function has
>> + *           completed on other CPUs.
>> + * @gfp_flags:       GFP flags to use when allocating the cpumask
>> + *           used internally by the function.
>> + *
>> + * The function might sleep if the GFP flags indicates a non
>> + * atomic allocation is allowed.
>> + *
>> + * Preemption is disabled to protect against a hotplug event.
>
>
> Well, disabling preemption protects us only against CPU offline right?
> (because we use the stop_machine thing during cpu offline).
>
> What about CPU online?
>
> Just to cross-check my understanding of the code with the existing
> documentation on CPU hotplug, I looked up Documentation/cpu-hotplug.txt
> and this is what I found:
>
> "If you merely need to avoid cpus going away, you could also use
> preempt_disable() and preempt_enable() for those sections....
> ...The preempt_disable() will work as long as stop_machine_run() is used
> to take a cpu down."
>
> So even this only talks about using preempt_disable() to prevent CPU offline,
> not CPU online. Or, am I missing something?

You are not missing anything, this is simply a bad choice of words on my part.
Thank you for pointing this out.

I should write:

" Preemption is disabled to protect against CPU going offline but not online.
  CPUs going online during the call will not be seen or sent an IPI."

Protecting against CPU going online during the function is useless
since they might
as well go online right after the call is finished, so the caller has
to take care of it, if they
cares.

Thanks,
Gilad

>
>> + *
>> + * You must not call this function with disabled interrupts or
>> + * from a hardware interrupt handler or from a bottom half handler.
>> + */
>> +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)
>> +{
>> +     cpumask_var_t cpus;
>> +     int cpu, ret;
>> +
>> +     might_sleep_if(gfp_flags & __GFP_WAIT);
>> +
>> +     if (likely(zalloc_cpumask_var(&cpus, (gfp_flags|__GFP_NOWARN)))) {
>> +             preempt_disable();
>> +             for_each_online_cpu(cpu)
>> +                     if (cond_func(cpu, info))
>> +                             cpumask_set_cpu(cpu, cpus);
>
>
> IOW, what prevents a new CPU from becoming online at this point?
>
>> +             on_each_cpu_mask(cpus, func, info, wait);
>> +             preempt_enable();
>> +             free_cpumask_var(cpus);
>> +     } else {
>> +             /*
>> +              * No free cpumask, bother. No matter, we'll
>> +              * just have to IPI them one by one.
>> +              */
>> +             preempt_disable();
>> +             for_each_online_cpu(cpu)
>> +                     if (cond_func(cpu, info)) {
>> +                             ret = smp_call_function_single(cpu, func,
>> +                                                             info, wait);
>> +                             WARN_ON_ONCE(!ret);
>> +                     }
>> +             preempt_enable();
>> +     }
>> +}
>> +EXPORT_SYMBOL(on_each_cpu_cond);
>
>
>
> Regards,
> Srivatsa S. Bhat
>



-- 
Gilad Ben-Yossef
Chief Coffee Drinker
gilad@benyossef.com
Israel Cell: +972-52-8260388
US Cell: +1-973-8260388
http://benyossef.com

"If you take a class in large-scale robotics, can you end up in a
situation where the homework eats your dog?"
 -- Jean-Baptiste Queru

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  reply	other threads:[~2012-02-05 15:46 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-05 13:33 [PATCH v8 0/8] Reduce cross CPU IPI interference Gilad Ben-Yossef
2012-02-05 13:33 ` Gilad Ben-Yossef
2012-02-05 13:44 ` [PATCH v8 1/8] smp: introduce a generic on_each_cpu_mask function Gilad Ben-Yossef
2012-02-05 13:44   ` Gilad Ben-Yossef
2012-02-05 15:18   ` Srivatsa S. Bhat
2012-02-05 15:18     ` Srivatsa S. Bhat
2012-02-05 13:48 ` [PATCH v8 2/8] arm: move arm over to generic on_each_cpu_mask Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-05 13:48 ` [PATCH v8 3/8] tile: move tile to use " Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-05 13:48 ` [PATCH v8 4/8] smp: add func to IPI cpus based on parameter func Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-05 15:36   ` Srivatsa S. Bhat
2012-02-05 15:36     ` Srivatsa S. Bhat
2012-02-05 15:46     ` Gilad Ben-Yossef [this message]
2012-02-05 15:46       ` Gilad Ben-Yossef
2012-02-05 16:00       ` Srivatsa S. Bhat
2012-02-05 16:00         ` Srivatsa S. Bhat
2012-02-05 16:03         ` Srivatsa S. Bhat
2012-02-05 16:03           ` Srivatsa S. Bhat
2012-02-08  9:30   ` Michal Nazarewicz
2012-02-08  9:30     ` Michal Nazarewicz
2012-02-09  0:03     ` Andrew Morton
2012-02-09  0:03       ` Andrew Morton
2012-02-09  8:08       ` Gilad Ben-Yossef
2012-02-09  8:08         ` Gilad Ben-Yossef
2012-02-09  8:13         ` Andrew Morton
2012-02-09  8:13           ` Andrew Morton
2012-02-09  9:53           ` Gilad Ben-Yossef
2012-02-09  9:53             ` Gilad Ben-Yossef
2012-02-05 13:48 ` [PATCH v8 5/8] slub: only IPI CPUs that have per cpu obj to flush Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-05 13:48 ` [PATCH v8 6/8] fs: only send IPI to invalidate LRU BH when needed Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-05 13:48 ` [PATCH v8 7/8] mm: only IPI CPUs to drain local pages if they exist Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-08  9:33   ` Michal Nazarewicz
2012-02-08  9:33     ` Michal Nazarewicz
2012-02-09  8:09     ` Gilad Ben-Yossef
2012-02-09  8:09       ` Gilad Ben-Yossef
2012-02-05 13:48 ` [PATCH v8 8/8] mm: add vmstat counters for tracking PCP drains Gilad Ben-Yossef
2012-02-05 13:48   ` Gilad Ben-Yossef
2012-02-08  9:36 ` [PATCH v8 0/8] Reduce cross CPU IPI interference Michal Nazarewicz
2012-02-08  9:36   ` Michal Nazarewicz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAOtvUMdqpwOedhZHq6QpUnDyg1FzfK_K3=9HQujjoN9yU3XWnA@mail.gmail.com' \
    --to=gilad@benyossef.com \
    --cc=akpm@linux-foundation.org \
    --cc=andi@firstfloor.org \
    --cc=avi@redhat.com \
    --cc=cl@linux-foundation.org \
    --cc=cmetcalf@tilera.com \
    --cc=fweisbec@gmail.com \
    --cc=kosaki.motohiro@gmail.com \
    --cc=levinsasha928@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux@arm.linux.org.uk \
    --cc=miltonm@bga.com \
    --cc=mina86@mina86.com \
    --cc=mpm@selenic.com \
    --cc=penberg@kernel.org \
    --cc=riel@redhat.com \
    --cc=srivatsa.bhat@linux.vnet.ibm.com \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.