From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56150) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YK23q-00051A-3g for qemu-devel@nongnu.org; Sat, 07 Feb 2015 04:52:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YK23k-0003Zg-Lm for qemu-devel@nongnu.org; Sat, 07 Feb 2015 04:52:22 -0500 Received: from szxga01-in.huawei.com ([119.145.14.64]:7787) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YK23k-0003V1-30 for qemu-devel@nongnu.org; Sat, 07 Feb 2015 04:52:16 -0500 From: w00214312 Date: Sat, 7 Feb 2015 17:51:48 +0800 Message-ID: <1423302708-7900-2-git-send-email-wu.wubin@huawei.com> In-Reply-To: <1423302708-7900-1-git-send-email-wu.wubin@huawei.com> References: <1423302708-7900-1-git-send-email-wu.wubin@huawei.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH] qemu-coroutine-lock: fix co_queue multi-adding bug List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, pbonzini@redhat.com, famz@redhat.com, Bin Wu , stefanha@redhat.com From: Bin Wu When a coroutine holds a lock, other coroutines who want to get the lock must wait on a co_queue by adding themselves to the CoQueue. However, if a waiting coroutine is woken up with the lock still be holding by other coroutine, this waiting coroutine will add itself to the co_queue again. Latter, when the lock is released, a coroutine re-enter will occur. We need to determine whether a coroutine is alread in the co_queue before adding it to the waiting queue. Signed-off-by: Bin Wu --- include/block/coroutine_int.h | 1 + qemu-coroutine-lock.c | 6 +++++- qemu-coroutine.c | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/block/coroutine_int.h b/include/block/coroutine_int.h index f133d65..c524990 100644 --- a/include/block/coroutine_int.h +++ b/include/block/coroutine_int.h @@ -42,6 +42,7 @@ struct Coroutine { /* Coroutines that should be woken up when we yield or terminate */ QTAILQ_HEAD(, Coroutine) co_queue_wakeup; QTAILQ_ENTRY(Coroutine) co_queue_next; + bool in_co_queue; }; Coroutine *qemu_coroutine_new(void); diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c index e4860ae..d256f53 100644 --- a/qemu-coroutine-lock.c +++ b/qemu-coroutine-lock.c @@ -36,7 +36,10 @@ void qemu_co_queue_init(CoQueue *queue) void coroutine_fn qemu_co_queue_wait(CoQueue *queue) { Coroutine *self = qemu_coroutine_self(); - QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next); + if (!self->in_co_queue) { + QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next); + self->in_co_queue = true; + } qemu_coroutine_yield(); assert(qemu_in_coroutine()); } @@ -71,6 +74,7 @@ static bool qemu_co_queue_do_restart(CoQueue *queue, bool single) while ((next = QTAILQ_FIRST(&queue->entries)) != NULL) { QTAILQ_REMOVE(&queue->entries, next, co_queue_next); + next->in_co_queue = false; QTAILQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next); trace_qemu_co_queue_next(next); if (single) { diff --git a/qemu-coroutine.c b/qemu-coroutine.c index 525247b..a103721 100644 --- a/qemu-coroutine.c +++ b/qemu-coroutine.c @@ -75,6 +75,7 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry) } co->entry = entry; + co->in_co_queue = false; QTAILQ_INIT(&co->co_queue_wakeup); return co; } -- 1.7.12.4