mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
io: make qio_channel_yield aware of AioContexts
Support separate coroutines for reading and writing, and place the read/write handlers on the AioContext that the QIOChannel is registered with. Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Fam Zheng <famz@redhat.com> Message-id: 20170213135235.12274-7-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
bf88c1247f
commit
c4c497d27f
2 changed files with 110 additions and 25 deletions
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "qemu-common.h"
|
||||
#include "qom/object.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "block/aio.h"
|
||||
|
||||
#define TYPE_QIO_CHANNEL "qio-channel"
|
||||
|
@ -81,6 +82,9 @@ struct QIOChannel {
|
|||
Object parent;
|
||||
unsigned int features; /* bitmask of QIOChannelFeatures */
|
||||
char *name;
|
||||
AioContext *ctx;
|
||||
Coroutine *read_coroutine;
|
||||
Coroutine *write_coroutine;
|
||||
#ifdef _WIN32
|
||||
HANDLE event; /* For use with GSource on Win32 */
|
||||
#endif
|
||||
|
@ -502,14 +506,51 @@ guint qio_channel_add_watch(QIOChannel *ioc,
|
|||
GDestroyNotify notify);
|
||||
|
||||
|
||||
/**
|
||||
* qio_channel_attach_aio_context:
|
||||
* @ioc: the channel object
|
||||
* @ctx: the #AioContext to set the handlers on
|
||||
*
|
||||
* Request that qio_channel_yield() sets I/O handlers on
|
||||
* the given #AioContext. If @ctx is %NULL, qio_channel_yield()
|
||||
* uses QEMU's main thread event loop.
|
||||
*
|
||||
* You can move a #QIOChannel from one #AioContext to another even if
|
||||
* I/O handlers are set for a coroutine. However, #QIOChannel provides
|
||||
* no synchronization between the calls to qio_channel_yield() and
|
||||
* qio_channel_attach_aio_context().
|
||||
*
|
||||
* Therefore you should first call qio_channel_detach_aio_context()
|
||||
* to ensure that the coroutine is not entered concurrently. Then,
|
||||
* while the coroutine has yielded, call qio_channel_attach_aio_context(),
|
||||
* and then aio_co_schedule() to place the coroutine on the new
|
||||
* #AioContext. The calls to qio_channel_detach_aio_context()
|
||||
* and qio_channel_attach_aio_context() should be protected with
|
||||
* aio_context_acquire() and aio_context_release().
|
||||
*/
|
||||
void qio_channel_attach_aio_context(QIOChannel *ioc,
|
||||
AioContext *ctx);
|
||||
|
||||
/**
|
||||
* qio_channel_detach_aio_context:
|
||||
* @ioc: the channel object
|
||||
*
|
||||
* Disable any I/O handlers set by qio_channel_yield(). With the
|
||||
* help of aio_co_schedule(), this allows moving a coroutine that was
|
||||
* paused by qio_channel_yield() to another context.
|
||||
*/
|
||||
void qio_channel_detach_aio_context(QIOChannel *ioc);
|
||||
|
||||
/**
|
||||
* qio_channel_yield:
|
||||
* @ioc: the channel object
|
||||
* @condition: the I/O condition to wait for
|
||||
*
|
||||
* Yields execution from the current coroutine until
|
||||
* the condition indicated by @condition becomes
|
||||
* available.
|
||||
* Yields execution from the current coroutine until the condition
|
||||
* indicated by @condition becomes available. @condition must
|
||||
* be either %G_IO_IN or %G_IO_OUT; it cannot contain both. In
|
||||
* addition, no two coroutine can be waiting on the same condition
|
||||
* and channel at the same time.
|
||||
*
|
||||
* This must only be called from coroutine context
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue