linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrea Parri <andrea.parri@amarulasolutions.com>
To: John Ogness <john.ogness@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>,
	linux-kernel@vger.kernel.org, Petr Mladek <pmladek@suse.com>,
	Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Subject: Re: [RFC PATCH v2 1/2] printk-rb: add a new printk ringbuffer implementation
Date: Sun, 30 Jun 2019 16:08:55 +0200	[thread overview]
Message-ID: <20190630140855.GA6005@andrea> (raw)
In-Reply-To: <87imsnaky1.fsf@linutronix.de>

On Sun, Jun 30, 2019 at 04:03:34AM +0200, John Ogness wrote:
> On 2019-06-29, Andrea Parri <andrea.parri@amarulasolutions.com> wrote:
> >> /**
> >>  * add_descr_list() - Add a descriptor to the descriptor list.
> >>  *
> >>  * @e: An entry that has already reserved data.
> >>  *
> >>  * The provided entry contains a pointer to a descriptor that has already
> >>  * been reserved for this entry. However, the reserved descriptor is not
> >>  * yet on the list. Add this descriptor as the newest item.
> >>  *
> >>  * A descriptor is added in two steps. The first step is to make this
> >>  * descriptor the newest. The second step is to update @next of the former
> >>  * newest descriptor to point to this one (or set @oldest to this one if
> >>  * this will be the first descriptor on the list).
> >>  */
> >> static void add_descr_list(struct prb_reserved_entry *e)
> >> {
> >> 	struct printk_ringbuffer *rb = e->rb;
> >> 	struct prb_list *l = &rb->descr_list;
> >> 	struct prb_descr *d = e->descr;
> >> 	struct prb_descr *newest_d;
> >> 	unsigned long newest_id;
> >> 
> >> 	WRITE_ONCE(d->next, EOL);
> >
> > /* C */
> >
> >
> >> 
> >> 	do {
> >> 		newest_id = READ_ONCE(l->newest);
> >
> > /* A */
> >
> >
> >> 		newest_d = TO_DESC(rb, newest_id);
> >> 
> >> 		if (newest_id == EOL) {
> >> 			WRITE_ONCE(d->seq, 1);
> >> 		} else {
> >> 			/*
> >> 			 * MB5-read: synchronize setting newest descr
> >> 			 *
> >> 			 * context-pair: 2 writers adding a descriptor via
> >> 			 * add_descr_list().
> >> 			 *
> >> 			 * @newest will load before @seq due to a data
> >> 			 * dependency, therefore, the stores of @seq
> >> 			 * and @next from the pairing MB5-write context
> >> 			 * will be visible.
> >> 			 *
> >> 			 * Although @next is not loaded by this context,
> >> 			 * this context must overwrite the stored @next
> >> 			 * value of the pairing MB5-write context.
> >> 			 */
> >> 			WRITE_ONCE(d->seq, READ_ONCE(newest_d->seq) + 1);
> >
> > /* B: this READ_ONCE() */
> >
> > Hence you're claiming a data dependency from A to B. (FWIW, the LKMM
> > would call "A ->dep B" an "address dependency.)
> >
> > This comment also claims that the "pairing MB5-write" orders "stores
> > of @seq and @next" (which are to different memory locations w.r.t. A
> > and B): I do not get why this access to @next (C above?, that's also
> > "unordered" w.r.t. A) can be relevant; can you elaborate?
> 
> I will add some more labels to complete the picture. All these events
> are within this function:
> 
> D: the WRITE_ONCE() to @seq
> 
> E: the STORE of a successful cmpxchg() for @newest (the MB5-write
> cmpxchg())
> 
> F: the STORE of a new @next (the last smp_store_release() of this
> function, note that the _release() is not relevant for this pair)
> 
> The significant events for 2 contexts that are accessing the same
> addresses of a descriptor are:
> 
> P0(struct desc *d0)
> {
>         // adding a new descriptor d0
> 
>         WRITE_ONCE(d0->next, EOL);               // C
>         WRITE_ONCE(d0->seq, X);                  // D
>         cmpxchg_release(newest, Y, indexof(d0)); // E
> }
> 
> P1(struct desc *d1)
> {
>         // adding a new descriptor d1 that comes after d0
> 
>         struct desc *d0;
>         int r0, r1;
> 
>         r0 = READ_ONCE(newest);                 // A
>         d0 = &array[r0];
>         r1 = READ_ONCE(d0->seq);                // B
>         WRITE_ONCE(d0->next, Z);                // F
> }
> 
> d0 is the same address for P0 and P1. (The values of EOL, X, Y, Z are
> unrelated and irrelevant.)
> 
> I am claiming that:
> 
> - B comes after D
> - F comes after C

I think these are both assuming that A is reading the value stored by E
(shortly, "A reads from E")?  If so, then the two claims become/are:

  - If A reads from E, then B comes after D

  - If A reads from E, then F comes after C

I think you could avoid the (ambiguous) "comes after" and say something
like:

  (1) If A reads from E, then B reads from D (or from another store
      to ->seq, not reported in the snippet, which overwrites D)

  (2) If A reads from E, then F overwrites C

This, IIUC, for the informal descriptions of the (intended) guarantees.
Back to the pairings in question: AFAICT,

  (a) For (1), we rely on the pairing:

        RELEASE from D to E  (matching)  ADDRESS DEP. from A to B

  (b) For (2), we rely on the pairing:

        RELEASE from C to E  (matching)  ADDRESS DEP. from A to F

Does this make sense?


> 
> >> 		}
> >> 
> >> 		/*
> >> 		 * MB5-write: synchronize setting newest descr
> >> 		 *
> >> 		 * context-pair: 2 writers adding a descriptor via
> >> 		 * add_descr_list().
> >> 		 *
> >> 		 * Ensure that @next and @seq are stored before @d is
> >> 		 * visible via @newest. The pairing MB5-read context
> >> 		 * must load this @seq value and must overwrite this
> >> 		 * @next value.
> >> 		 */
> >> 	} while (cmpxchg_release(&l->newest, newest_id, e->id) != newest_id);
> >> 
> >> 	if (unlikely(newest_id == EOL)) {
> >> 		/*
> >> 		 * MB0-write: synchronize adding first descr
> >> 		 *
> >> 		 * context-pair: 1 writer adding the first descriptor via
> >> 		 * add_descr_list(), 1 reader getting the beginning of
> >> 		 * the list via iter_peek_next_id().
> >> 		 *
> >> 		 * This context recently assigned new values for @id,
> >> 		 * @next, @seq. Ensure these are stored before the first
> >> 		 * store to @oldest so that the new values are visible
> >> 		 * to the reader in the pairing MB0-read context.
> >> 		 *
> >> 		 * Note: Before this store, the value of @oldest is EOL.
> >> 		 */
> >
> > My gmail-search foo is unable to locate MB0-read: what am I missing?
> > Also, can you maybe annotate the memory accesses to @id, @next, @seq
> > and @oldest (as I did above)? I find myself guessing their location.
> 
> Sorry. The MB0-read is a _new_ comment that would be added to the
> smp_rmb() of the reader functions. I didn't repost everything because I
> just wanted to get a feel if the comments for _this_ function are
> improving. Really all I care about right now is properly documenting
> MB5. It is a good example because MB5 is completely within this
> function. If I can satisfactorily document MB5, then I can post a new
> version with updated comments for everything.

Oh, I see, thanks for this clarification.


> 
> >> 		smp_store_release(&l->oldest, e->id);
> >> 	} else {
> >> 		/*
> >> 		 * MB6-write: synchronize linking new descr
> >> 		 *
> >> 		 * context-pair-1: 1 writer adding a descriptor via
> >> 		 * add_descr_list(), 1 writer removing a descriptor via
> >> 		 * remove_oldest_descr().
> >> 		 *
> >> 		 * If this is a recycled descriptor, this context
> >> 		 * recently stored a new @oldest value. Ensure that
> >> 		 * @oldest is stored before storing @next so that
> >> 		 * if the pairing MB6-read context sees a non-EOL
> >> 		 * @next value, it is ensured that it will also see
> >> 		 * an updated @oldest value.
> >> 		 *
> >> 		 * context-pair-2: 1 writer adding a descriptor via
> >> 		 * add_descr_list(), 1 reader iterating the list via
> >> 		 * prb_iter_next_valid_entry().
> >> 		 *
> >> 		 * This context recently assigned new values for @id,
> >> 		 * @next, @seq, @data, @data_next. Ensure these are
> >> 		 * stored before storing @next of the previously
> >> 		 * newest descriptor so that the new values are
> >> 		 * visible to the iterating reader in the pairing
> >> 		 * MB6-read context.
> >> 		 *
> >> 		 * Note: Before this store, the value of @next of the
> >> 		 * previously newest descriptor is EOL.
> >> 		 */
> >
> > Same as above but for MB6-read and the accesses to @id, @next, @seq,
> > @data, @data_next.
> >
> > In conclusion, I have been unable to produce litmus tests by reading
> > your comments (meaning I'm lost).
> 
> I feel like I'm stating all the information, but nobody understands it.
> If you can help me to correctly document MB5, I can submit a new version
> with all the memory barriers correctly documented.

IMO (and assuming that what I wrote above makes some sense), (a-b) and
(1-2) above, together with the associated annotations of the code/ops,
provide all the desired and necessary information to document MB5.

For readability purposes, it could be nice to also keep the snippet you
provided above (but let me stress, again, that such a snippet should be
integrated with additional information as suggested above).

As to "where to insert the memory barrier documentation", I really have
no suggestion ATM.  I guess someone would split it (say, before A and E)
while others could prefer to keep it within a same inline comment.

Thanks for this information (and for your patience!),

  Andrea

  reply	other threads:[~2019-06-30 14:09 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-07 16:23 [RFC PATCH v2 0/2] printk: new ringbuffer implementation John Ogness
2019-06-07 16:23 ` [RFC PATCH v2 1/2] printk-rb: add a new printk " John Ogness
2019-06-18  4:51   ` Sergey Senozhatsky
2019-06-18 22:12     ` John Ogness
2019-06-25  6:45       ` Sergey Senozhatsky
2019-06-25  7:15         ` Sergey Senozhatsky
2019-06-25  8:44           ` John Ogness
2019-06-25  9:06             ` Petr Mladek
2019-06-25 10:03               ` Sergey Senozhatsky
2019-06-25 12:03                 ` John Ogness
2019-06-26  2:08                   ` Sergey Senozhatsky
2019-06-26  7:16                     ` John Ogness
2019-06-26  7:45                       ` Sergey Senozhatsky
2019-06-26  7:47                       ` Petr Mladek
2019-06-26  7:59                         ` Sergey Senozhatsky
2019-06-25  9:09             ` Sergey Senozhatsky
2019-06-18 11:12   ` Peter Zijlstra
2019-06-18 22:18     ` John Ogness
2019-06-18 11:22   ` Peter Zijlstra
2019-06-18 22:30     ` John Ogness
2019-06-19 10:46       ` Andrea Parri
2019-06-20 22:50         ` John Ogness
2019-06-21 12:16           ` Andrea Parri
2019-06-19 11:08       ` Peter Zijlstra
2019-06-18 11:47   ` Peter Zijlstra
2019-06-20 22:23     ` John Ogness
2019-06-26 22:40       ` Peter Zijlstra
2019-06-26 22:53         ` Peter Zijlstra
2019-06-28  9:50         ` John Ogness
2019-06-28 15:44           ` Peter Zijlstra
2019-06-28 16:07             ` Peter Zijlstra
2019-07-01 10:39             ` John Ogness
2019-07-01 14:10               ` Peter Zijlstra
2019-07-01 14:11               ` Peter Zijlstra
2019-06-29 21:05           ` Andrea Parri
2019-06-30  2:03             ` John Ogness
2019-06-30 14:08               ` Andrea Parri [this message]
2019-07-02 14:13                 ` John Ogness
2019-06-26 22:47       ` Peter Zijlstra
2019-06-21 14:05   ` Petr Mladek
2019-06-24  8:33     ` John Ogness
2019-06-24 14:09       ` Petr Mladek
2019-06-25 13:29         ` John Ogness
2019-06-26  8:29           ` Petr Mladek
2019-06-26  9:09             ` John Ogness
2019-06-26 21:16       ` Peter Zijlstra
2019-06-26 21:43         ` John Ogness
2019-06-27  8:28           ` Petr Mladek
2019-07-04 10:33     ` [PATCH POC] printk_ringbuffer: Alternative implementation of lockless printk ringbuffer Petr Mladek
2019-07-04 14:59       ` John Ogness
2019-07-08 15:23         ` Petr Mladek
2019-07-09  1:34           ` John Ogness
2019-07-09  9:06             ` Petr Mladek
2019-07-09 10:21               ` John Ogness
2019-07-09 11:58                 ` Petr Mladek
2019-08-14  3:46                   ` John Ogness
2019-06-24 13:55   ` [RFC PATCH v2 1/2] printk-rb: add a new printk ringbuffer implementation John Ogness
2019-06-25  8:55   ` Sergey Senozhatsky
2019-06-25  9:19     ` John Ogness
2019-06-07 16:23 ` [RFC PATCH v2 2/2] printk-rb: add test module John Ogness
2019-06-17 21:09 ` [RFC PATCH v2 0/2] printk: new ringbuffer implementation Thomas Gleixner
2019-06-18  7:15   ` Petr Mladek

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=20190630140855.GA6005@andrea \
    --to=andrea.parri@amarulasolutions.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=sergey.senozhatsky.work@gmail.com \
    --cc=sergey.senozhatsky@gmail.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.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 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).