From: Fam Zheng <famz@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>
Subject: [Qemu-devel] [PULL 05/16] coroutine-lock: make qemu_co_enter_next thread-safe
Date: Thu, 8 Feb 2018 10:19:42 +0800 [thread overview]
Message-ID: <20180208021953.7354-6-famz@redhat.com> (raw)
In-Reply-To: <20180208021953.7354-1-famz@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
qemu_co_queue_next does not need to release and re-acquire the mutex,
because the queued coroutine does not run immediately. However, this
does not hold for qemu_co_enter_next. Now that qemu_co_queue_wait
can synchronize (via QemuLockable) with code that is not running in
coroutine context, it's important that code using qemu_co_enter_next
can easily use a standardized locking idiom.
First of all, qemu_co_enter_next must use aio_co_wake to restart the
coroutine. Second, the function gains a second argument, a QemuLockable*,
and the comments of qemu_co_queue_next and qemu_co_queue_restart_all
are adjusted to clarify the difference.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20180203153935.8056-5-pbonzini@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
---
fsdev/qemu-fsdev-throttle.c | 4 ++--
include/qemu/coroutine.h | 19 +++++++++++++------
util/qemu-coroutine-lock.c | 10 ++++++++--
3 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
index 49eebb5412..1dc07fbc12 100644
--- a/fsdev/qemu-fsdev-throttle.c
+++ b/fsdev/qemu-fsdev-throttle.c
@@ -20,13 +20,13 @@
static void fsdev_throttle_read_timer_cb(void *opaque)
{
FsThrottle *fst = opaque;
- qemu_co_enter_next(&fst->throttled_reqs[false]);
+ qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
}
static void fsdev_throttle_write_timer_cb(void *opaque)
{
FsThrottle *fst = opaque;
- qemu_co_enter_next(&fst->throttled_reqs[true]);
+ qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
}
void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 1e5f0957e6..6f8a487041 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -188,21 +188,28 @@ void qemu_co_queue_init(CoQueue *queue);
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
/**
- * Restarts the next coroutine in the CoQueue and removes it from the queue.
- *
- * Returns true if a coroutine was restarted, false if the queue is empty.
+ * Removes the next coroutine from the CoQueue, and wake it up.
+ * Returns true if a coroutine was removed, false if the queue is empty.
*/
bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
/**
- * Restarts all coroutines in the CoQueue and leaves the queue empty.
+ * Empties the CoQueue; all coroutines are woken up.
*/
void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
/**
- * Enter the next coroutine in the queue
+ * Removes the next coroutine from the CoQueue, and wake it up. Unlike
+ * qemu_co_queue_next, this function releases the lock during aio_co_wake
+ * because it is meant to be used outside coroutine context; in that case, the
+ * coroutine is entered immediately, before qemu_co_enter_next returns.
+ *
+ * If used in coroutine context, qemu_co_enter_next is equivalent to
+ * qemu_co_queue_next.
*/
-bool qemu_co_enter_next(CoQueue *queue);
+#define qemu_co_enter_next(queue, lock) \
+ qemu_co_enter_next_impl(queue, QEMU_MAKE_LOCKABLE(lock))
+bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock);
/**
* Checks if the CoQueue is empty.
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 2a66fc1467..78fb79acf8 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -132,7 +132,7 @@ void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue)
qemu_co_queue_do_restart(queue, false);
}
-bool qemu_co_enter_next(CoQueue *queue)
+bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock)
{
Coroutine *next;
@@ -142,7 +142,13 @@ bool qemu_co_enter_next(CoQueue *queue)
}
QSIMPLEQ_REMOVE_HEAD(&queue->entries, co_queue_next);
- qemu_coroutine_enter(next);
+ if (lock) {
+ qemu_lockable_unlock(lock);
+ }
+ aio_co_wake(next);
+ if (lock) {
+ qemu_lockable_lock(lock);
+ }
return true;
}
--
2.14.3
next prev parent reply other threads:[~2018-02-08 2:20 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-08 2:19 [Qemu-devel] [PULL 00/16] Docker and block patches Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 01/16] docker: change Fedora base image to fedora:27 Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 02/16] test-coroutine: add simple CoMutex test Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 03/16] lockable: add QemuLockable Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 04/16] coroutine-lock: convert CoQueue to use QemuLockable Fam Zheng
2018-02-08 2:19 ` Fam Zheng [this message]
2018-02-08 2:19 ` [Qemu-devel] [PULL 06/16] curl: convert to CoQueue Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 07/16] stubs: Add stubs for ram block API Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 08/16] util: Introduce vfio helpers Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 09/16] block: Add VFIO based NVMe driver Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 10/16] block: Introduce buf register API Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 11/16] block/nvme: Implement .bdrv_(un)register_buf Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 12/16] qemu-img: Map bench buffer Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 13/16] block: Move NVMe constants to a separate header Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 14/16] docs: Add section for NVMe VFIO driver Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 15/16] qapi: Add NVMe driver options to the schema Fam Zheng
2018-02-08 2:19 ` [Qemu-devel] [PULL 16/16] docs: Add docs/devel/testing.rst Fam Zheng
2018-02-08 16:17 ` [Qemu-devel] [PULL 00/16] Docker and block patches Peter Maydell
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=20180208021953.7354-6-famz@redhat.com \
--to=famz@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.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).