From: Peter Zijlstra <peterz@infradead.org>
To: John Ogness <john.ogness@linutronix.de>
Cc: 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>,
Andrea Parri <andrea.parri@amarulasolutions.com>,
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: Thu, 27 Jun 2019 00:40:34 +0200 [thread overview]
Message-ID: <20190626224034.GK2490@worktop.programming.kicks-ass.net> (raw)
In-Reply-To: <87k1df28x4.fsf@linutronix.de>
On Fri, Jun 21, 2019 at 12:23:19AM +0200, John Ogness wrote:
> Hi Peter,
>
> This is a long response, but we are getting into some fine details about
> the memory barriers (as well as battling my communication skill level).
So I'm going to reply piecewise to this... so not such long emails, but
more of them.
> On 2019-06-18, Peter Zijlstra <peterz@infradead.org> wrote:
> >> +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;
> >> +
> >> + /* set as newest */
> >> + do {
> >> + /* MB5: synchronize add descr */
> >> + newest_id = smp_load_acquire(&l->newest);
> >> + newest_d = TO_DESCR(rb, newest_id);
> >> +
> >> + if (newest_id == EOL)
> >> + WRITE_ONCE(d->seq, 1);
> >> + else
> >> + WRITE_ONCE(d->seq, READ_ONCE(newest_d->seq) + 1);
> >> + /*
> >> + * MB5: synchronize add descr
> >> + *
> >> + * In particular: next written before cmpxchg
> >> + */
> >> + } while (cmpxchg_release(&l->newest, newest_id, e->id) != newest_id);
> >
> > What does this pair with? I find ->newest usage in:
>
> It is pairing with the smp_load_acquire() at the beginning of this loop
> (also labeled MB5) that is running simultaneously on another CPU. I am
> avoiding a possible situation that a new descriptor is added but the
> store of "next" from the previous descriptor is not yet visible and thus
> the cmpxchg following will fail, which is not allowed. (Note that "next"
> is set to EOL shortly before this function is called.)
>
> The litmus test for this is:
>
> P0(int *newest, int *d_next)
> {
> // set descr->next to EOL (terminates list)
> WRITE_ONCE(*d_next, 1);
>
> // set descr as newest
> smp_store_release(*newest, 1);
> }
>
> P1(int *newest, int *d_next)
> {
> int local_newest;
> int local_next;
>
> // get newest descriptor
> local_newest = smp_load_acquire(*newest);
>
> // a new descriptor is set as the newest
> // (not relevant here)
>
> // read descr->next of previous newest
> // (must be EOL!)
> local_next = READ_ONCE(*d_next);
> }
>
> exists (1:local_newest=1 /\ 1:local_next=0)
I'm having trouble connecting your P1's READ_ONCE() to the actual code.
You say that is in the same function, but I cannot find a LOAD there
that would care about the ACQUIRE.
Afaict prb_list is a list head not a list node (calling it just _list is
confusing at best).
You have a single linked list going from the tail to the head, while
adding to the head and removing from the tail. And that sounds like a
FIFO queue:
struct lqueue_head {
struct lqueue_node *head, *tail;
};
struct lqueue_node {
struct lqueue_node *next;
};
void lqueue_push(struct lqueue_head *h, struct lqueue_node *n)
{
struct lqueue_node *prev;
n->next = NULL;
/*
* xchg() implies RELEASE; and thereby ensures @n is
* complete before getting published.
*/
prev = xchg(&h->head, n);
/*
* xchg() implies ACQUIRE; and thereby ensures @tail is
* written after @head, see lqueue_pop()'s smp_rmb().
*/
if (prev)
WRITE_ONCE(prev->next, n);
else
WRITE_ONCE(h->tail, n);
}
struct lqueue_node *lqueue_pop(struct lqueue_head *h)
{
struct lqueue_node *head, *tail, *next;
do {
tail = READ_ONCE(h->tail);
/* If the list is empty, nothing to remove. */
if (!tail)
return NULL;
/*
* If we see @tail, we must then also see @head.
* Pairs with the xchg() in lqueue_push(),
* ensure no false positive on the singleton
* test below.
*/
smp_rmb();
head = READ_ONCE(h->head);
/* If there is but one item; fail to remove. */
if (head == tail)
return NULL;
next = smp_cond_load_relaxed(&tail->next, VAL);
} while (cmpxchg(h->tail, tail, next) != tail);
return tail;
}
Now, you appear to be using desc_ids instead of pointers, but since
you're not using the actual wrap value; I don't see the benefit of using
those IDs over straight pointers.
That is, unless I've overlooked some subtle ABA issue, but then, your
code doesn't seem to mention that, and I think we're good because if we
re-use an entry, it can never get back in the same location, since we
never allow an empty list (might also be fixable, haven't tought too
hard on this).
That said, the above has cmpxchg() vs WRITE_ONCE() and is therefore not
safe on a number of our architectures. We can either not care about
performance and use xchg() for the ->tail store, or use atomic_long_t
and suffer ugly casting.
But the above is, IMO, a more useful and readable abstraction. Let me
continue in another email (probably tomorrow).
next prev parent reply other threads:[~2019-06-26 22:41 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 [this message]
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
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=20190626224034.GK2490@worktop.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=andrea.parri@amarulasolutions.com \
--cc=gregkh@linuxfoundation.org \
--cc=john.ogness@linutronix.de \
--cc=linux-kernel@vger.kernel.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