linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gilad Ben-Yossef <gilad@benyossef.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org, Chris Metcalf <cmetcalf@tilera.com>,
	Christoph Lameter <cl@linux-foundation.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	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>,
	Milton Miller <miltonm@bga.com>
Subject: Re: [v7 4/8] smp: add func to IPI cpus based on parameter func
Date: Sun, 29 Jan 2012 14:04:25 +0200	[thread overview]
Message-ID: <CAOtvUMfceR8zZf5resfcNQFWZyrKG5BdB00gqq3GZRpgFRD=yw@mail.gmail.com> (raw)
In-Reply-To: <20120127155725.86654035.akpm@linux-foundation.org>

On Sat, Jan 28, 2012 at 1:57 AM, Andrew Morton
<akpm@linux-foundation.org> wrote:
> On Thu, 26 Jan 2012 12:01:57 +0200
> Gilad Ben-Yossef <gilad@benyossef.com> wrote:
...
>>
>> @@ -153,6 +162,16 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
>>                       local_irq_enable();             \
>>               }                                       \
>>       } while (0)
>> +#define on_each_cpu_cond(cond_func, func, info, wait, gfpflags) \
>> +     do {                                            \
>> +             preempt_disable();                      \
>> +             if (cond_func(0, info)) {               \
>> +                     local_irq_disable();            \
>> +                     (func)(info);                   \
>> +                     local_irq_enable();             \
>
> Ordinarily, local_irq_enable() in such a low-level thing is dangerous,
> because it can cause horrid bugs when called from local_irq_disable()d
> code.
>
> However I think we're OK here because it is a bug to call on_each_cpu()
> and friends with local irqs disabled, yes?

Yes, that is my understanding and this way the function gets called in
the same conditions in UP and SMP.

> Do we have any warnings printks if someone calls the ipi-sending
> functions with local interrupts disabled?  I didn't see any, but didn't
> look very hard.

There is this check in smp_call_function_many():

        WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
                     && !oops_in_progress && !early_boot_irqs_disabled);

Only catches SMP offenders though.


> If my above claims are correct then why does on_each_cpu() use
> local_irq_save()?  hrm.

The comment in on_each_cpu() in kernel.smp.c says: "May be
used during early boot while early_boot_irqs_disabled is set.  Use
local_irq_save/restore() instead of local_irq_disable/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..fa0912a 100644
>> --- a/kernel/smp.c
>> +++ b/kernel/smp.c
>> @@ -730,3 +730,61 @@ 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.
>> + * @gfpflags:        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.
>> + *
>> + * 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 gfpflags)
>
> bah.
>
> z:/usr/src/linux-3.3-rc1> grep -r gfpflags . | wc -l
> 78
> z:/usr/src/linux-3.3-rc1> grep -r gfp_flags . | wc -l
> 548
>

I have no specific preference. Should I switch?

>> +{
>> +     cpumask_var_t cpus;
>> +     int cpu, ret;
>> +
>> +     might_sleep_if(gfpflags & __GFP_WAIT);
>
> For the zalloc_cpumask_var(), it seems.  I expect there are
> might_sleep() elsewhere in the memory allocation paths, but putting one
> here will detect bugs even if CONFIG_CPUMASK_OFFSTACK=n.

Well, yes, although I didn't think about that :-)

>
>> +     if (likely(zalloc_cpumask_var(&cpus, (gfpflags|__GFP_NOWARN)))) {
>> +             preempt_disable();
>> +             for_each_online_cpu(cpu)
>> +                     if (cond_func(cpu, info))
>> +                             cpumask_set_cpu(cpu, cpus);
>> +             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);
>
> I assume the preempt_disable()s here are to suspend CPU hotplug?

Yes.  Also, I figured that since the original code disabled
preemption for the entire on_each_cpu run time, including waiting for all
the CPUs to ack the IPI, and since we (hopefully) wait for less CPUs, the
overall runtime with  preemption disabled will be (usually) lower then the
original  code most of the time and we'll get a more robust interface.

Thanks,
Gilad

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

"Unfortunately, cache misses are an equal opportunity pain provider."
-- Mike Galbraith, LKML

  reply	other threads:[~2012-01-29 12:04 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-26 10:01 [v7 0/8] Reduce cross CPU IPI interference Gilad Ben-Yossef
2012-01-26 10:01 ` [v7 1/8] smp: introduce a generic on_each_cpu_mask function Gilad Ben-Yossef
2012-01-29 12:24   ` Gilad Ben-Yossef
2012-01-30 21:52     ` Andrew Morton
2012-01-31  6:33       ` Gilad Ben-Yossef
2012-01-26 10:01 ` [v7 2/8] arm: move arm over to generic on_each_cpu_mask Gilad Ben-Yossef
2012-01-26 10:01 ` [v7 3/8] tile: move tile to use " Gilad Ben-Yossef
2012-01-26 10:01 ` [v7 4/8] smp: add func to IPI cpus based on parameter func Gilad Ben-Yossef
2012-01-27 23:57   ` Andrew Morton
2012-01-29 12:04     ` Gilad Ben-Yossef [this message]
2012-01-26 10:01 ` [v7 5/8] slub: only IPI CPUs that have per cpu obj to flush Gilad Ben-Yossef
2012-01-26 15:09   ` Christoph Lameter
2012-01-26 10:01 ` [v7 6/8] fs: only send IPI to invalidate LRU BH when needed Gilad Ben-Yossef
2012-01-26 10:02 ` [v7 7/8] mm: only IPI CPUs to drain local pages if they exist Gilad Ben-Yossef
2012-01-26 15:13   ` Christoph Lameter
2012-01-28  0:12   ` Andrew Morton
2012-01-29 12:18     ` Gilad Ben-Yossef
2012-01-30 21:49       ` Andrew Morton
2012-01-31  6:32         ` Gilad Ben-Yossef
2012-01-30 14:59   ` Mel Gorman
2012-01-30 15:14     ` Gilad Ben-Yossef
2012-01-30 15:44       ` Mel Gorman
2012-01-26 10:02 ` [v7 8/8] mm: add vmstat counters for tracking PCP drains Gilad Ben-Yossef
2012-01-26 15:19 ` [v7 0/8] Reduce cross CPU IPI interference Peter Zijlstra
2012-01-29  8:25   ` Gilad Ben-Yossef
2012-02-01 17:04     ` Frederic Weisbecker
2012-02-02  8:46       ` Gilad Ben-Yossef
2012-02-02 15:41         ` Chris Metcalf
2012-02-05 11:46           ` Gilad Ben-Yossef
2012-02-10 18:39             ` Peter Zijlstra
2012-02-10 20:13               ` Gilad Ben-Yossef
2012-02-10 20:29                 ` Peter Zijlstra
2012-02-10 20:39                   ` Gilad Ben-Yossef
2012-02-10 18:33           ` Peter Zijlstra
2012-02-10 20:33             ` Gilad Ben-Yossef
2012-02-15 21:50             ` Chris Metcalf
2012-02-15 22:15               ` Christoph Lameter
2012-02-15 23:44                 ` Chris Metcalf
2012-02-21  1:34               ` Frederic Weisbecker
2012-03-01 18:27                 ` Chris Metcalf
2012-02-10 18:38           ` Peter Zijlstra
2012-02-10 20:24             ` Gilad Ben-Yossef
2012-02-15 15:11               ` Peter Zijlstra
2012-02-15 15:19                 ` Gilad Ben-Yossef
2012-02-15 21:51               ` Chris Metcalf
2012-02-02 16:24         ` Frederic Weisbecker
2012-02-02 16:29           ` Christoph Lameter
2012-02-09 15:52             ` Frederic Weisbecker
2012-02-09 15:59               ` Chris Metcalf
2012-02-09 18:11                 ` Frederic Weisbecker
2012-02-09 16:26               ` Christoph Lameter
2012-02-09 18:32                 ` Frederic Weisbecker
2012-02-01 17:35     ` Peter Zijlstra
2012-02-01 17:57       ` Peter Zijlstra
2012-02-02  9:42         ` Gilad Ben-Yossef
2012-02-01 18:40       ` Paul E. McKenney
2012-02-01 20:06         ` Christoph Lameter
2012-02-01 20:13           ` Paul E. McKenney
2012-02-02  9:34             ` Avi Kivity
2012-02-02 15:34               ` Paul E. McKenney
2012-02-02 16:14                 ` Avi Kivity
2012-02-02 17:01                   ` Paul E. McKenney
2012-02-02 17:23                     ` Avi Kivity
2012-02-02 17:51                       ` Paul E. McKenney
2012-02-05 12:16                         ` Avi Kivity
2012-02-05 16:59                           ` Paul E. McKenney
2012-02-09 15:22                             ` Frederic Weisbecker
2012-02-09 16:05                               ` Avi Kivity
2012-02-09 18:22                                 ` Frederic Weisbecker
2012-02-09 23:41                                   ` Paul E. McKenney
2012-02-10  1:39                                     ` Frederic Weisbecker
2012-02-14 13:18                                       ` Avi Kivity
2012-02-21  0:02                                         ` Frederic Weisbecker
2012-02-02 17:25                     ` Christoph Lameter
2012-02-05 12:06                       ` Gilad Ben-Yossef
2012-02-06 18:19                         ` Christoph Lameter
2012-02-09 15:37                           ` Frederic Weisbecker

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='CAOtvUMfceR8zZf5resfcNQFWZyrKG5BdB00gqq3GZRpgFRD=yw@mail.gmail.com' \
    --to=gilad@benyossef.com \
    --cc=a.p.zijlstra@chello.nl \
    --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=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).