From: Petr Mladek <pmladek@suse.com>
To: John Ogness <john.ogness@linutronix.de>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>,
Steven Rostedt <rostedt@goodmis.org>,
Thomas Gleixner <tglx@linutronix.de>,
linux-kernel@vger.kernel.org,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: Re: simplify: was: Re: [PATCH printk v1 06/18] printk: nobkl: Add acquire/release logic
Date: Tue, 21 Mar 2023 16:36:49 +0100 [thread overview]
Message-ID: <ZBnPEaJKdHyTtUNS@alley> (raw)
In-Reply-To: <ZBSkoKCdG5uiVNPq@alley>
On Fri 2023-03-17 18:34:30, Petr Mladek wrote:
> Hi,
>
> I send this before reading today's answers about the basic rules.
>
> I have spent on this answer few days and I do not want to delay
> it indefinitely. It documents my initial feelings about the code.
> Also it describes some ideas that might or need not be useful
> anyway.
>
> Also there is a POC that slightly modifies the logic. But the basic
> approach remains the same.
I looked at this with a "fresh" mind. I though if there was any real
advantage in the proposed change of the cons_release() logic. I mean
to just clear .cpu and .cur_prio and let cons_try_acquire() to take
over the lock.
I tried to describe my view below.
> > +/**
> > + * __cons_release - Release the console after output is done
> > + * @ctxt: The acquire context that contains the state
> > + * at cons_try_acquire()
> > + *
> > + * Returns: True if the release was regular
> > + *
> > + * False if the console is in unusable state or was handed over
> > + * with handshake or taken over hostile without handshake.
> > + *
> > + * The return value tells the caller whether it needs to evaluate further
> > + * printing.
> > + */
> > +static bool __cons_release(struct cons_context *ctxt)
> > +{
> > + struct console *con = ctxt->console;
> > + short flags = console_srcu_read_flags(con);
> > + struct cons_state hstate;
> > + struct cons_state old;
> > + struct cons_state new;
> > +
> > + if (WARN_ON_ONCE(!(flags & CON_NO_BKL)))
> > + return false;
> > +
> > + cons_state_read(con, CON_STATE_CUR, &old);
> > +again:
> > + if (!cons_state_bits_match(old, ctxt->state))
> > + return false;
> > +
> > + /* Release it directly when no handover request is pending. */
> > + if (!old.req_prio)
> > + goto unlock;
> > +
> > + /* Read the handover target state */
> > + cons_state_read(con, CON_STATE_REQ, &hstate);
> > +
> > + /* If the waiter gave up hstate is 0 */
> > + if (!hstate.atom)
> > + goto unlock;
> > +
> > + /*
> > + * If a higher priority waiter raced against a lower priority
> > + * waiter then unlock instead of handing over to either. The
> > + * higher priority waiter will notice the updated state and
> > + * retry.
> > + */
> > + if (hstate.cur_prio != old.req_prio)
> > + goto unlock;
The above check might cause that CUR will be completely unlocked
even when there is a request. It is a corner case. It would happen
when a higher priority context is in the middle of over-ridding
an older request (already took REQ but have not updated
CUR.req_prio yet).
As a result any context might take CUR while the higher priority
context is re-starting the request and tries to get the lock with
the updated CUR.
It is a bit pity but it is not end of the world. The higher priority
context would just need to wait for another context.
That said, my proposal would solve this a bit cleaner way.
CUR would stay blocked for the .req_prio context. As a result,
the being-overridden REQ owner would become CUR owner.
And the higher priority context would then need to setup
new REQ against the previous REQ owner.
> > +
> > + /* Switch the state and preserve the sequence on 64bit */
> > + copy_bit_state(new, hstate);
> > + copy_seq_state64(new, old);
> > + if (!cons_state_try_cmpxchg(con, CON_STATE_CUR, &old, &new))
> > + goto again;
The other difference is that the above code will do just half of
the request-related manipulation. It will assing CUR to the REQ owner.
The REQ owner will need to realize that it got the lock and
clean up REQ part.
Or by other words, there are 3 pieces of information:
+ CUR owner is defined by CUR.cpu and CUR.cur_prio
+ REQ owner is defined by REQ.cpu and REQ.cur_prio
+ CUR knows about the request by CUR.req_prio
The current code modifies the pieces in thie order:
CPU0 CPU1
// take a free lock
set CUR.cpu
set CUR.cur_prio
// set request
set REQ.cpu
set REQ.cur_prio
// notify CUR
set CUR.req_prio
// re-assign the lock to CPU1
set CUR.cpu = REQ.cpu
set CUR.cur_prio = REQ.cur_prio
set CUR.req_prio = 0
// clean REQ
REQ.cpu =0;
REQ.cur_prio = 0;
In this case, CPU0 has to read REQ and does a job for CPU1.
Instead, my proposal does:
CPU0 CPU1
// take a free lock
set CUR.cpu
set cur.prio
// set request
set REQ.cpu
set REQ,cur_prio
// notify CUR
set CUR.req_prio
// unlock CPU0
set CUR.cpu = 0
set CUR.cur_prio = 0;
keep CUR.req_prio == REQ.cur_prio
// take the lock and clean notification
set CUR.cpu = REQ.cpu
set CUR.cur_prio = REQ.cur_prio
set CUR.req_prio = 0
// clean REQ
REQ.cpu =0;
REQ.cur_prio = 0;
In this case:
+ CPU0: It manipulates only CUR. And it keeps CUR.req_prio value.
It does not check REQ at all.
+ CPU1: Manipulates all REQ-related variables and fields.
It modifies SEQ.cpu and SEQ.cur_prio only when
they are free.
It looks a bit cleaner. Also it might help to think about barriers
because each side touches only its variables and fields. We might
need less explicit barriers that might be needed when one CPU
does a change for the other.
My view:
I would prefer to do the logic change. It might help with review
and also with the long term maintenance.
But I am not 100% sure if it is worth it. The original approach might
be good enough. The important thing is that it modifies CUR and REQ
variables and fields in the right order. And I do not see any
chicken-and-egg problems. Also the barriers should be doable.
Best Regards,
Petr
next prev parent reply other threads:[~2023-03-21 15:37 UTC|newest]
Thread overview: 92+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-02 19:56 [PATCH printk v1 00/18] threaded/atomic console support John Ogness
2023-03-02 19:56 ` [PATCH printk v1 01/18] kdb: do not assume write() callback available John Ogness
2023-03-07 14:57 ` Petr Mladek
2023-03-07 16:34 ` Doug Anderson
2023-03-09 10:52 ` Daniel Thompson
2023-03-09 11:26 ` Petr Mladek
2023-03-09 11:30 ` Daniel Thompson
2023-03-02 19:56 ` [PATCH printk v1 02/18] printk: Add NMI check to down_trylock_console_sem() John Ogness
2023-03-07 16:05 ` Petr Mladek
2023-03-17 11:37 ` John Ogness
2023-04-13 13:42 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 03/18] printk: Consolidate console deferred printing John Ogness
2023-03-08 13:15 ` Petr Mladek
2023-03-17 13:05 ` John Ogness
2023-04-13 15:15 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 04/18] printk: Add per-console suspended state John Ogness
2023-03-08 14:40 ` Petr Mladek
2023-03-17 13:22 ` John Ogness
2023-04-14 9:56 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 05/18] printk: Add non-BKL console basic infrastructure John Ogness
2023-03-09 14:08 ` global states: was: " Petr Mladek
2023-03-17 13:29 ` John Ogness
2023-03-09 15:32 ` naming: " Petr Mladek
2023-03-17 13:39 ` John Ogness
2023-03-21 16:04 ` union: was: " Petr Mladek
2023-03-27 16:28 ` John Ogness
2023-03-28 8:20 ` Petr Mladek
2023-03-28 9:42 ` John Ogness
2023-03-28 12:52 ` Petr Mladek
2023-03-28 13:47 ` Steven Rostedt
2023-03-02 19:56 ` [PATCH printk v1 06/18] printk: nobkl: Add acquire/release logic John Ogness
2023-03-06 9:07 ` Dan Carpenter
2023-03-06 9:39 ` John Ogness
2023-03-13 16:07 ` Petr Mladek
2023-03-17 14:56 ` John Ogness
2023-03-20 16:10 ` Petr Mladek
2023-03-17 17:34 ` simplify: was: " Petr Mladek
2023-03-21 15:36 ` Petr Mladek [this message]
2023-04-02 18:39 ` John Ogness
2023-03-02 19:56 ` [PATCH printk v1 07/18] printk: nobkl: Add buffer management John Ogness
2023-03-21 16:38 ` Petr Mladek
2023-03-23 13:38 ` John Ogness
2023-03-23 15:25 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 08/18] printk: nobkl: Add sequence handling John Ogness
2023-03-27 15:45 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 09/18] printk: nobkl: Add print state functions John Ogness
2023-03-29 13:58 ` buffer write race: " Petr Mladek
2023-03-29 14:33 ` John Ogness
2023-03-30 11:54 ` Petr Mladek
2023-03-29 14:05 ` misc details: was: " Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 10/18] printk: nobkl: Add emit function and callback functions for atomic printing John Ogness
2023-03-03 0:19 ` kernel test robot
2023-03-03 10:55 ` John Ogness
2023-03-31 10:29 ` dropped handling: was: " Petr Mladek
2023-03-31 10:36 ` semantic: " Petr Mladek
[not found] ` <87edp29kvq.fsf@jogness.linutronix.de>
[not found] ` <ZCraqrkqFtsfLWuP@alley>
[not found] ` <87ilecsrvl.fsf@jogness.linutronix.de>
2023-04-04 14:09 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 11/18] printk: nobkl: Introduce printer threads John Ogness
2023-03-03 1:23 ` kernel test robot
2023-03-03 10:56 ` John Ogness
2023-04-05 10:48 ` boot console: was: " Petr Mladek
2023-04-06 8:09 ` wakeup synchronization: " Petr Mladek
2023-04-06 9:46 ` port lock: " Petr Mladek
2023-04-20 9:55 ` Petr Mladek
2023-04-20 10:33 ` John Ogness
2023-04-20 13:33 ` Petr Mladek
2023-04-21 16:15 ` Petr Mladek
2023-04-06 13:19 ` misc: " Petr Mladek
2023-04-13 13:28 ` (k)thread: " Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 12/18] printk: nobkl: Add printer thread wakeups John Ogness
2023-04-12 9:38 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 13/18] printk: nobkl: Add write context storage for atomic writes John Ogness
2023-03-02 19:56 ` [PATCH printk v1 14/18] printk: nobkl: Provide functions for atomic write enforcement John Ogness
2023-04-12 14:53 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 15/18] printk: nobkl: Stop threads on shutdown/reboot John Ogness
2023-04-13 9:03 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 16/18] kernel/panic: Add atomic write enforcement to warn/panic John Ogness
2023-04-13 10:08 ` Petr Mladek
2023-04-13 12:13 ` John Ogness
2023-04-14 10:10 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 17/18] rcu: Add atomic write enforcement for rcu stalls John Ogness
2023-04-13 12:10 ` Petr Mladek
2023-03-02 19:56 ` [PATCH printk v1 18/18] printk: Perform atomic flush in console_flush_on_panic() John Ogness
2023-04-13 12:20 ` Petr Mladek
2023-03-02 19:58 ` [PATCH printk v1 00/18] serial: 8250: implement non-BKL console John Ogness
2023-03-28 13:33 ` locking API: was: " Petr Mladek
2023-03-28 13:57 ` John Ogness
2023-03-28 15:10 ` Petr Mladek
2023-03-28 21:47 ` John Ogness
2023-03-29 8:03 ` Petr Mladek
2023-03-28 13:59 ` [PATCH printk v1 00/18] POC: serial: 8250: implement nbcon console John Ogness
2023-03-09 10:55 ` [PATCH printk v1 00/18] threaded/atomic console support Daniel Thompson
2023-03-09 11:14 ` John Ogness
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=ZBnPEaJKdHyTtUNS@alley \
--to=pmladek@suse.com \
--cc=gregkh@linuxfoundation.org \
--cc=john.ogness@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=senozhatsky@chromium.org \
--cc=tglx@linutronix.de \
/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