All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
To: Davidlohr Bueso <dave@stgolabs.net>
Cc: linux-kernel@vger.kernel.org, George Spelvin <linux@horizon.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	Manfred Spraul <manfred@colorfullife.com>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH v2] ipc/msg: Implement lockless pipelined wakeups
Date: Tue, 3 Nov 2015 21:12:55 +0100	[thread overview]
Message-ID: <56391547.2040105@linutronix.de> (raw)
In-Reply-To: <20151103173021.GE1707@linux-uzut.site>

On 11/03/2015 06:30 PM, Davidlohr Bueso wrote:
> On Tue, 03 Nov 2015, Sebastian Andrzej Siewior wrote:
> 
>> @@ -577,26 +570,23 @@ static inline int pipelined_send(struct
>> msg_queue *msq, struct msg_msg *msg)
>>
>>             list_del(&msr->r_list);
>>             if (msr->r_maxsize < msg->m_ts) {
>> -                /* initialize pipelined send ordering */
>> -                msr->r_msg = NULL;
>> -                wake_up_process(msr->r_tsk);
>> -                /* barrier (B) see barrier comment below */
>> -                smp_wmb();
>> +                wake_q_add(wake_q, msr->r_tsk);
>>                 msr->r_msg = ERR_PTR(-E2BIG);
>>             } else {
>> -                msr->r_msg = NULL;
>>                 msq->q_lrpid = task_pid_vnr(msr->r_tsk);
>>                 msq->q_rtime = get_seconds();
>> -                wake_up_process(msr->r_tsk);
>> -                /*
>> -                 * Ensure that the wakeup is visible before
>> -                 * setting r_msg, as the receiving can otherwise
>> -                 * exit - once r_msg is set, the receiver can
>> -                 * continue. See lockless receive part 1 and 2
>> -                 * in do_msgrcv(). Barrier (B).
>> -                 */
>> -                smp_wmb();
>> +                wake_q_add(wake_q, msr->r_tsk);
>>                 msr->r_msg = msg;
>> +                /*
>> +                 * Rely on the implicit cmpxchg barrier from
>> +                 * wake_q_add such that we can ensure that
>> +                 * updating msr->r_msg is the last write
>> +                 * operation: As once set, the receiver can
>> +                 * continue, and if we don't have the reference
>> +                 * count from the wake_q, yet, at that point we
>> +                 * can later have a use-after-free condition and
>> +                 * bogus wakeup.
>> +                 */
> 
> Not sure why you placed the comment here. Why not between smp_wmb() and
> the r_msg
> write as we have it?

This follows the scheme we have in pipelined_send(). First wake_q_add()
then ->state (here we have the msg instead).

> 
> You might also want to add a reference to this comment in expunge_all(),
> which
> does the same thing.

okay.

>> [...]
>>
>>         /* Lockless receive, part 2:
>> -         * Wait until pipelined_send or expunge_all are outside of
>> -         * wake_up_process(). There is a race with exit(), see
>> -         * ipc/mqueue.c for the details. The correct serialization
>> -         * ensures that a receiver cannot continue without the wakeup
>> -         * being visibible _before_ setting r_msg:
>> +         * The work in pipelined_send() and expunge_all():
>> +         * - Set pointer to message
>> +         * - Queue the receiver task for later wakeup
>> +         * - Wake up the process after the lock is dropped.
>>          *
>> -         * CPU 0                             CPU 1
>> -         * <loop receiver>
>> -         *   smp_rmb(); (A) <-- pair -.      <waker thread>
>> -         *   <load ->r_msg>           |        msr->r_msg = NULL;
>> -         *                            |        wake_up_process();
>> -         * <continue>                 `------> smp_wmb(); (B)
>> -         *                                     msr->r_msg = msg;
>> -         *
>> -         * Where (A) orders the message value read and where (B) orders
>> -         * the write to the r_msg -- done in both pipelined_send and
>> -         * expunge_all.
>> +         * Should the process wake up before this wakeup (due to a
>> +         * signal) it will either see the message and continue ...
>>          */
>> -        for (;;) {
>> -            /*
>> -             * Pairs with writer barrier in pipelined_send
>> -             * or expunge_all.
>> -             */
>> -            smp_rmb(); /* barrier (A) */
>> -            msg = (struct msg_msg *)msr_d.r_msg;
>> -            if (msg)
>> -                break;
>>
>> -            /*
>> -             * The cpu_relax() call is a compiler barrier
>> -             * which forces everything in this loop to be
>> -             * re-loaded.
>> -             */
>> -            cpu_relax();
>> -        }
>> -
>> -        /* Lockless receive, part 3:
>> -         * If there is a message or an error then accept it without
>> -         * locking.
>> -         */
>> +        msg = msr_d.r_msg;
> 
> But you're getting rid of the barrier pairing (smp_rmb) we have in
> pipelined sends
> and expunge_all, which is necesary even if we don't busy wait on nil.

In pipelined_receive() (mqueue) there is the wake_q_add() with the
implicit cmpxchg barrier. The matching barrier pairing should be in
wq_sleep() but there is none. Why is it okay to have none there and I
need one here?

> Likewise,
> there's no need to remove the comment above that illustrates this.

I did not assume we need a barrier here. If we do, I keep it in the
comment / graphic but right I now, I think that it can go.

> Thanks,
> Davidlohr

Sebastian

  reply	other threads:[~2015-11-03 20:13 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-03 15:03 [PATCH v2] ipc/msg: Implement lockless pipelined wakeups Sebastian Andrzej Siewior
2015-11-03 17:30 ` Davidlohr Bueso
2015-11-03 20:12   ` Sebastian Andrzej Siewior [this message]
2015-11-04 18:11     ` Davidlohr Bueso
2015-11-04 11:55 ` Peter Zijlstra
2015-11-04 17:32   ` Davidlohr Bueso
2015-11-04 12:02 ` Peter Zijlstra

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=56391547.2040105@linutronix.de \
    --to=bigeasy@linutronix.de \
    --cc=akpm@linux-foundation.org \
    --cc=dave@stgolabs.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@horizon.com \
    --cc=manfred@colorfullife.com \
    --cc=peterz@infradead.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 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.