From: Rusty Russell <rusty@rustcorp.com.au>
To: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Max Krasnyansky <maxk@qualcomm.com>,
linux-kernel@vger.kernel.org, Jason Baron <jbaron@redhat.com>,
Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Subject: Re: [PATCH 2/3] stop_machine: simplify
Date: Sat, 12 Jul 2008 15:07:31 +1000 [thread overview]
Message-ID: <200807121507.31640.rusty@rustcorp.com.au> (raw)
In-Reply-To: <20080711131220.GA7589@Krystal>
On Friday 11 July 2008 23:12:21 Mathieu Desnoyers wrote:
> * Rusty Russell (rusty@rustcorp.com.au) wrote:
> > On Thursday 10 July 2008 10:30:37 Max Krasnyansky wrote:
> > > You mentioned (in private conversation) that you were going to add some
> > > logic that checks whether CPU is running user-space code and not
> > > holding any locks to avoid scheduling stop_machine thread on it.
> >
> > Will play with it again and report,
> > Rusty.
>
> Hrm, I must be missing something, but using the fact that other CPUs are
> running in userspace as a guarantee that they are not running within
> critical kernel sections seems kind of.. racy ? I'd like to have a look
> at this experimental patch : does it inhibit interrupts somehow and/or
> does it take control of userspace processes doing system calls at that
> precise moment ?
The idea was to try this ipi-to-all-cpus and fall back on the current thread
method if it doesn't work. I suspect it will succeed in the vast majority of
cases (with CONFIG_PREEMPT, we can also let the function execute if in-kernel
but preemptible). Something like this:
+struct ipi_data {
+ atomic_t acked;
+ atomic_t failed;
+ unsigned int cpu;
+ int fnret;
+ int (*fn)(void *data);
+ void *data;
+};
+
+static void ipi_func(void *info)
+{
+ struct ipi_data *ipi = info;
+ bool ok = false;
+
+ printk("get_irq_regs(%i) = %p\n", smp_processor_id(), get_irq_regs());
+ goto fail;
+
+ if (user_mode(get_irq_regs()))
+ ok = true;
+ else {
+#ifdef CONFIG_PREEMPT
+ /* We're in an interrupt, ok, but were we preemptible
+ * before that? */
+ if ((hardirq_count() >> HARDIRQ_SHIFT) == 1) {
+ int prev = preempt_count() & ~HARDIRQ_MASK;
+ if ((prev & ~PREEMPT_ACTIVE) == PREEMPT_INATOMIC_BASE)
+ ok = true;
+ }
+#endif
+ }
+
+fail:
+ if (!ok) {
+ /* Mark our failure before acking. */
+ atomic_inc(&ipi->failed);
+ wmb();
+ }
+
+ if (smp_processor_id() != ipi->cpu) {
+ /* Wait for cpu to call function (last to ack). */
+ atomic_inc(&ipi->acked);
+ while (atomic_read(&ipi->acked) != num_online_cpus())
+ cpu_relax();
+ } else {
+ while (atomic_read(&ipi->acked) != num_online_cpus() - 1)
+ cpu_relax();
+ /* Must read acked before failed. */
+ rmb();
+
+ /* Call function if noone failed. */
+ if (atomic_read(&ipi->failed) == 0)
+ ipi->fnret = ipi->fn(ipi->data);
+ atomic_inc(&ipi->acked);
+ }
+}
+
+static bool try_ipi_stop(int (*fn)(void *), void *data, unsigned int cpu,
+ int *ret)
+{
+ struct ipi_data ipi;
+
+ /* If they don't care which cpu fn runs on, just pick one. */
+ if (cpu == NR_CPUS)
+ ipi.cpu = any_online_cpu(cpu_online_map);
+ else
+ ipi.cpu = cpu;
+
+ atomic_set(&ipi.acked, 0);
+ atomic_set(&ipi.failed, 0);
+ ipi.fn = fn;
+ ipi.data = data;
+ ipi.fnret = 0;
+
+ smp_call_function(ipi_func, &ipi, 0, 1);
+
+ printk("stop_machine: ipi acked %u failed %u\n",
+ atomic_read(&ipi.acked), atomic_read(&ipi.failed));
+ *ret = ipi.fnret;
+ return (atomic_read(&ipi.failed) == 0);
+}
Hope that clarifies!
Rusty.
next prev parent reply other threads:[~2008-07-12 5:07 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-08 7:50 [PATCH 0/3] stop_machine enhancements and simplifications Rusty Russell
2008-07-08 7:56 ` [PATCH 1/3] stop_machine: add ALL_CPUS option Rusty Russell
2008-07-08 7:56 ` [PATCH 2/3] stop_machine: simplify Rusty Russell
2008-07-08 8:01 ` [PATCH 3/3] stop_machine: use cpu mask rather than magic numbers Rusty Russell
2008-07-10 21:07 ` [PATCH -next-20080709] fixup stop_machine use cpu mask vs ftrace Milton Miller
2008-07-10 21:07 ` Milton Miller
2008-07-11 6:43 ` Rusty Russell
2008-07-11 6:43 ` Rusty Russell
2008-07-11 7:46 ` Ingo Molnar
2008-07-11 7:46 ` Ingo Molnar
2008-07-11 8:55 ` Ingo Molnar
2008-07-11 8:55 ` Ingo Molnar
2008-07-11 12:34 ` Rusty Russell
2008-07-11 12:34 ` Rusty Russell
2008-07-08 11:44 ` [PATCH 2/3] stop_machine: simplify Akinobu Mita
2008-07-08 13:11 ` Rusty Russell
2008-07-08 15:02 ` Akinobu Mita
2008-07-09 2:18 ` Rusty Russell
2008-07-08 14:27 ` Mathieu Desnoyers
2008-07-09 2:11 ` Rusty Russell
2008-07-09 12:42 ` Mathieu Desnoyers
2008-07-10 0:30 ` Max Krasnyansky
2008-07-11 7:51 ` Rusty Russell
2008-07-11 13:12 ` Mathieu Desnoyers
2008-07-12 5:07 ` Rusty Russell [this message]
2008-07-08 16:21 ` [PATCH 0/3] stop_machine enhancements and simplifications Christian Borntraeger
2008-07-08 20:10 ` Jason Baron
2008-07-09 3:29 ` Mathieu Desnoyers
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=200807121507.31640.rusty@rustcorp.com.au \
--to=rusty@rustcorp.com.au \
--cc=jbaron@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@polymtl.ca \
--cc=maxk@qualcomm.com \
--cc=seto.hidetoshi@jp.fujitsu.com \
/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.