qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Fam Zheng <famz@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, stefanha@redhat.com, kwolf@redhat.com,
	berto@igalia.com
Subject: Re: [Qemu-devel] [PATCH 06/11] coroutine-lock: make CoMutex thread-safe
Date: Fri, 29 Apr 2016 14:26:46 +0800	[thread overview]
Message-ID: <20160429062646.GJ1421@ad.usersys.redhat.com> (raw)
In-Reply-To: <1460719926-12950-7-git-send-email-pbonzini@redhat.com>

On Fri, 04/15 13:32, Paolo Bonzini wrote:
> +/* The wait records are handled with a multiple-producer, single-consumer
> + * lock-free queue.  There cannot be two concurrent pop_waiter() calls
> + * because pop_waiter() can only come when mutex->handoff is zero.  This can
> + * happen in three cases:
> + * - in qemu_co_mutex_unlock, before the hand-off protocol has started.
> + *   In this case, qemu_co_mutex_lock will see mutex->handoff == 0 and
> + *   not take part in the handoff.
> + * - in qemu_co_mutex_lock, if it steals the hand-off responsibility from
> + *   qemu_co_mutex_unlock.  In this case, qemu_co_mutex_unlock will fail
> + *   the cmpxchg (it will see either 0 or the next sequence value) and
> + *   exit.  The next hand-off cannot begin until qemu_co_mutex_lock has
> + *   woken up someone.
> + * - in qemu_co_mutex_unlock, if it takes the hand-off token itself.
> + *   In this case another iterations starts with mutex->handoff == 0;

s/iterations/iteration/

> + *   a concurrent qemu_co_mutex_lock will fail the cmpxchg, and
> + *   qemu_co_mutex_unlock will go back to case (1).
> + *
> + * The following functions manage this queue.
> + */
> +typedef struct CoWaitRecord {
> +    Coroutine *co;
> +    QSLIST_ENTRY(CoWaitRecord) next;
> +} CoWaitRecord;
> +

<snip>

> @@ -132,12 +223,50 @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
>  
>      trace_qemu_co_mutex_unlock_entry(mutex, self);
>  
> -    assert(mutex->locked == true);
> +    assert(mutex->locked);
>      assert(qemu_in_coroutine());
>  
> -    mutex->locked = false;
> -    qemu_co_queue_next(&mutex->queue);
> +    if (atomic_fetch_dec(&mutex->locked) == 1) {
> +        /* No waiting qemu_co_mutex_lock().  Pfew, that was easy!  */
> +        return;
> +    }
> +
> +    for (;;) {
> +        CoWaitRecord *to_wake = pop_waiter(mutex);
> +        unsigned our_handoff;
> +
> +        if (to_wake) {
> +            Coroutine *co = to_wake->co;
> +            qemu_coroutine_wake(co->ctx, co);
> +            goto out;
> +        }
> +
> +        /* Some concurrent lock() is in progress (we know this because of
> +         * count) but it hasn't yet put itself on the wait queue.

Unlike OSv's lfmutex.cc, we don't seem to have count. Should the comment say
"locked" instead?

> +         * Pick a sequence number for the handoff protocol (not 0).
> +         */
> +        if (++mutex->sequence == 0) {
> +            mutex->sequence = 1;
> +        }
> +
> +        our_handoff = mutex->sequence;
> +        atomic_mb_set(&mutex->handoff, our_handoff);
> +        if (!has_waiters(mutex)) {
> +            /* The concurrent lock has not added itself yet, so it
> +             * will be able to pick our handoff.
> +             */
> +            goto out;
> +        }
> +
> +        /* Try to do the handoff protocol ourselves; if somebody else has
> +         * already taken it, however, we're done and they're responsible.
> +         */
> +        if (atomic_cmpxchg(&mutex->handoff, our_handoff, 0) != our_handoff) {
> +            goto out;
> +        }
> +    }
>  
> +out:
>      trace_qemu_co_mutex_unlock_return(mutex, self);
>  }
>  
> -- 
> 2.5.5
> 
> 

  reply	other threads:[~2016-04-29  6:26 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-15 11:31 [Qemu-devel] [RFC PATCH resend 00/11] Make CoMutex/CoQueue/CoRwlock thread-safe Paolo Bonzini
2016-04-15 11:31 ` [Qemu-devel] [PATCH 01/11] coroutine: use QSIMPLEQ instead of QTAILQ Paolo Bonzini
2016-04-19 13:45   ` Stefan Hajnoczi
2016-04-15 11:31 ` [Qemu-devel] [PATCH 02/11] throttle-groups: restart throttled requests from coroutine context Paolo Bonzini
2016-04-19 13:49   ` Stefan Hajnoczi
2016-04-15 11:31 ` [Qemu-devel] [PATCH 03/11] coroutine: delete qemu_co_enter_next Paolo Bonzini
2016-04-19 13:49   ` Stefan Hajnoczi
2016-04-15 11:31 ` [Qemu-devel] [PATCH 04/11] aio: introduce aio_co_schedule Paolo Bonzini
2016-04-19 14:31   ` Stefan Hajnoczi
2016-05-17 14:57     ` Paolo Bonzini
2016-05-26 19:19       ` Stefan Hajnoczi
2016-04-29  5:11   ` Fam Zheng
2016-05-17 14:38     ` Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 05/11] coroutine-lock: reschedule coroutine on the AioContext it was running on Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 06/11] coroutine-lock: make CoMutex thread-safe Paolo Bonzini
2016-04-29  6:26   ` Fam Zheng [this message]
2016-05-17 15:34     ` Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 07/11] coroutine-lock: add limited spinning to CoMutex Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 08/11] test-aio-multithread: add performance comparison with thread-based mutexes Paolo Bonzini
2016-04-29  6:52   ` Fam Zheng
2016-05-12 16:49     ` Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 09/11] coroutine-lock: place CoMutex before CoQueue in header Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 10/11] coroutine-lock: add mutex argument to CoQueue APIs Paolo Bonzini
2016-04-15 11:32 ` [Qemu-devel] [PATCH 11/11] coroutine-lock: make CoRwlock thread-safe and fair Paolo Bonzini
2016-04-26 10:54 ` [Qemu-devel] [RFC PATCH resend 00/11] Make CoMutex/CoQueue/CoRwlock thread-safe Stefan Hajnoczi
2016-04-27 15:42   ` Stefan Hajnoczi
2016-05-17 15:34   ` Paolo Bonzini

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=20160429062646.GJ1421@ad.usersys.redhat.com \
    --to=famz@redhat.com \
    --cc=berto@igalia.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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).