From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: joel@joelfernandes.org, mathieu.desnoyers@efficios.com,
peterz@infradead.org, tj@kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH RFC] Make call_srcu() available during very early boot
Date: Tue, 14 Aug 2018 14:02:04 -0700 [thread overview]
Message-ID: <20180814210204.GA12851@linux.vnet.ibm.com> (raw)
In-Reply-To: <20180814170618.GA24813@linux.vnet.ibm.com>
On Tue, Aug 14, 2018 at 10:06:18AM -0700, Paul E. McKenney wrote:
> On Tue, Aug 14, 2018 at 12:49:45PM -0400, Steven Rostedt wrote:
> > On Tue, 14 Aug 2018 09:24:48 -0700
> > "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote:
> >
> > > Event tracing is moving to SRCU in order to take advantage of the fact
> > > that SRCU may be safely used from idle and even offline CPUs. However,
> > > event tracing can invoke call_srcu() very early in the boot process,
> > > even before workqueue_init_early() is invoked (let alone rcu_init()).
> > > Therefore, call_srcu()'s attempts to queue work fail miserably.
> > >
> > > This commit therefore detects this situation, and refrains from attempting
> > > to queue work before rcu_init() time, but does everything else that it
> > > would have done, and in addition, adds the srcu_struct to a global list.
> > > The rcu_init() function now invokes a new srcu_init() function, which
> > > is empty if CONFIG_SRCU=n. Otherwise, srcu_init() queues work for
> > > each srcu_struct on the list. This all happens early enough in boot
> > > that there is but a single CPU with interrupts disabled, which allows
> > > synchronization to be dispensed with.
> > >
> > > Of course, the queued work won't actually be invoked until after
> > > workqueue_init() is invoked, which happens shortly after the scheduler
> > > is up and running. This means that although call_srcu() may be invoked
> > > any time after per-CPU variables have been set up, there is still a very
> > > narrow window when synchronize_srcu() won't work, and this window
> > > extends from the time that the scheduler starts until the time that
> > > workqueue_init() returns. This can be fixed in a manner similar to
> > > the fix for synchronize_rcu_expedited() and friends, but until someone
> > > actually needs to use synchronize_srcu() during this window, this fix
> > > is added churn for no benefit.
> > >
> > > Finally, note that Tree SRCU's new srcu_init() function invokes
> > > queue_work() rather than the queue_delayed_work() function that is invoked
> > > post-boot. The reason is that queue_delayed_work() will (as you would
> > > expect) post a timer, and timers have not yet been initialized. So use
> > > of queue_delayed_work() avoids the complaints about use of uninitialized
> >
> > You mean "So use of queue_work() avoids .." ?
>
> Indeed I do! Fixed.
>
> > > spinlocks that would otherwise result. Besides, delay is in any case
> > > provide by the aforementioned fact that the queued work won't actually
> > > be invoked until after the scheduler is up and running.
> > >
> > > Requested-by: Steven Rostedt <rostedt@goodmis.org>
> > > Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
> > >
> > > diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h
> > > index f41d2fb09f87..2b5c0822e683 100644
> > > --- a/include/linux/srcutiny.h
> > > +++ b/include/linux/srcutiny.h
> > > @@ -36,6 +36,7 @@ struct srcu_struct {
> > > struct rcu_head *srcu_cb_head; /* Pending callbacks: Head. */
> > > struct rcu_head **srcu_cb_tail; /* Pending callbacks: Tail. */
> > > struct work_struct srcu_work; /* For driving grace periods. */
> > > + struct list_head srcu_boot_entry; /* Early-boot callbacks. */
> >
> > I really don't like increasing the size of a structure for a field that
> > is hardly ever used.
> >
> > Is there a way we could make a union, or reuse one of the other fields,
> > as we know that synchronize_srcu() can't be used yet (and if it is,
> > either warn, or just make it a nop). And when we call srcu_init() and
> > remove the srcu_struct from the list, we can then initialize whatever
> > we used as the temporary boot up list field.
>
> I will take a look. If nothing else, I could union it with the
> struct work_struct, since it cannot be used that early anyway. ;-)
Not so much!!! The problem is that the srcu_struct needs to be
initialized differently depending on whether it is used before or after
start_kernel()'s call to rcu_init(). Before, it needs to be initialized
as a list_head, after as a work_struct. But the type of initialization
is determined not by the time of initialization but rather by the time
of first use. So it looks like reusing work_struct's list_head makes
more sense.
> Or I could just use the work_struct that is already inside the struct
> work_struct. Tejun, would you be OK with that?
I am creating a separate patch that eliminates the boot-time-only
->srcu_boot_entry field to allow the decisions to be made separately.
Thanx, Paul
> For whatever it is worth, synchronize_srcu() is perfectly legal way
> early in boot, at least as early as call_srcu(). The reason is that
> until the scheduler starts, synchronize_srcu() is a no-op.
>
> > srcu_init is called when we are still running only one CPU correct?
>
> Yes, single CPU interrupts disabled.
>
> > > #ifdef CONFIG_DEBUG_LOCK_ALLOC
> > > struct lockdep_map dep_map;
> > > #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
> > > @@ -48,6 +49,7 @@ void srcu_drive_gp(struct work_struct *wp);
> > > .srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq), \
> > > .srcu_cb_tail = &name.srcu_cb_head, \
> > > .srcu_work = __WORK_INITIALIZER(name.srcu_work, srcu_drive_gp), \
> > > + .srcu_boot_entry = LIST_HEAD_INIT(name.srcu_boot_entry), \
> > > __SRCU_DEP_MAP_INIT(name) \
> > > }
> > >
> > > diff --git a/include/linux/srcutree.h b/include/linux/srcutree.h
> > > index 745d4ca4dd50..86ad97111315 100644
> > > --- a/include/linux/srcutree.h
> > > +++ b/include/linux/srcutree.h
> > > @@ -94,6 +94,7 @@ struct srcu_struct {
> > > /* callback for the barrier */
> > > /* operation. */
> > > struct delayed_work work;
> > > + struct list_head srcu_boot_entry; /* Early-boot callbacks. */
> > > #ifdef CONFIG_DEBUG_LOCK_ALLOC
> > > struct lockdep_map dep_map;
> > > #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
> > > @@ -105,12 +106,13 @@ struct srcu_struct {
> > > #define SRCU_STATE_SCAN2 2
> > >
> > > #define __SRCU_STRUCT_INIT(name, pcpu_name) \
> > > - { \
> > > - .sda = &pcpu_name, \
> > > - .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
> > > - .srcu_gp_seq_needed = 0 - 1, \
> > > - __SRCU_DEP_MAP_INIT(name) \
> > > - }
> > > +{ \
> > > + .sda = &pcpu_name, \
> > > + .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
> > > + .srcu_gp_seq_needed = 0 - 1, \
> >
> > Interesting initialization of -1. This was there before, but still
> > interesting none the less.
>
> If I recall correctly, this subterfuge suppresses compiler complaints
> about initializing an unsigned long with a negative number. :-/
>
> Thanx, Paul
>
> > > + .srcu_boot_entry = LIST_HEAD_INIT(name.srcu_boot_entry), \
> > > + __SRCU_DEP_MAP_INIT(name) \
> > > +}
> > >
> > >
> >
> > -- Steve
> >
next prev parent reply other threads:[~2018-08-14 21:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-14 16:24 [PATCH RFC] Make call_srcu() available during very early boot Paul E. McKenney
2018-08-14 16:49 ` Steven Rostedt
2018-08-14 17:06 ` Paul E. McKenney
2018-08-14 17:24 ` Steven Rostedt
2018-08-14 17:44 ` Paul E. McKenney
2018-08-14 18:34 ` Steven Rostedt
2018-08-14 18:41 ` Paul E. McKenney
2018-08-14 21:02 ` Paul E. McKenney [this message]
2018-08-17 16:08 ` Tejun Heo
2018-08-17 16:31 ` Paul E. McKenney
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=20180814210204.GA12851@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=joel@joelfernandes.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=tj@kernel.org \
/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.