mirror of
https://github.com/qemu/qemu.git
synced 2026-02-04 02:24:38 +00:00
qio: Prepare NetListener to use AioContext
For ease of review, this patch adds an AioContext pointer to the QIONetListener struct, the code to trace it, and refactors listener->io_source to instead be an array of utility structs; but the aio_context pointer is always NULL until the next patch adds an API to set it. There should be no semantic change in this patch. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Message-ID: <20251113011625.878876-25-eblake@redhat.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(QIONetListener,
|
||||
QIO_NET_LISTENER)
|
||||
|
||||
typedef struct QIONetListenerSource QIONetListenerSource;
|
||||
|
||||
typedef void (*QIONetListenerClientFunc)(QIONetListener *listener,
|
||||
QIOChannelSocket *sioc,
|
||||
@@ -47,10 +48,11 @@ struct QIONetListener {
|
||||
Object parent;
|
||||
|
||||
char *name;
|
||||
QIOChannelSocket **sioc;
|
||||
GSource **io_source;
|
||||
QIONetListenerSource **source;
|
||||
size_t nsioc;
|
||||
/* At most one of context or aio_context will be set */
|
||||
GMainContext *context;
|
||||
AioContext *aio_context;
|
||||
|
||||
bool connected;
|
||||
|
||||
|
||||
@@ -24,8 +24,15 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/lockable.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "trace.h"
|
||||
|
||||
struct QIONetListenerSource {
|
||||
QIOChannelSocket *sioc;
|
||||
GSource *io_source;
|
||||
QIONetListener *listener;
|
||||
};
|
||||
|
||||
QIONetListener *qio_net_listener_new(void)
|
||||
{
|
||||
QIONetListener *listener;
|
||||
@@ -52,6 +59,7 @@ static gboolean qio_net_listener_channel_func(QIOChannel *ioc,
|
||||
QIONetListenerClientFunc io_func;
|
||||
gpointer io_data;
|
||||
GMainContext *context;
|
||||
AioContext *aio_context;
|
||||
|
||||
sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(ioc),
|
||||
NULL);
|
||||
@@ -63,9 +71,10 @@ static gboolean qio_net_listener_channel_func(QIOChannel *ioc,
|
||||
io_func = listener->io_func;
|
||||
io_data = listener->io_data;
|
||||
context = listener->context;
|
||||
aio_context = listener->aio_context;
|
||||
}
|
||||
|
||||
trace_qio_net_listener_callback(listener, io_func, context);
|
||||
trace_qio_net_listener_callback(listener, io_func, context, aio_context);
|
||||
if (io_func) {
|
||||
io_func(listener, sioc, io_data);
|
||||
}
|
||||
@@ -134,13 +143,23 @@ qio_net_listener_watch(QIONetListener *listener, size_t i, const char *caller)
|
||||
}
|
||||
|
||||
trace_qio_net_listener_watch(listener, listener->io_func,
|
||||
listener->context, caller);
|
||||
listener->context, listener->aio_context,
|
||||
caller);
|
||||
for ( ; i < listener->nsioc; i++) {
|
||||
object_ref(OBJECT(listener));
|
||||
listener->io_source[i] = qio_channel_add_watch_source(
|
||||
QIO_CHANNEL(listener->sioc[i]), G_IO_IN,
|
||||
qio_net_listener_channel_func,
|
||||
listener, (GDestroyNotify)object_unref, listener->context);
|
||||
if (!listener->aio_context) {
|
||||
/*
|
||||
* The user passed a GMainContext with the async callback;
|
||||
* they plan on running the default or their own g_main_loop.
|
||||
*/
|
||||
object_ref(OBJECT(listener));
|
||||
listener->source[i]->io_source = qio_channel_add_watch_source(
|
||||
QIO_CHANNEL(listener->source[i]->sioc), G_IO_IN,
|
||||
qio_net_listener_channel_func,
|
||||
listener, (GDestroyNotify)object_unref, listener->context);
|
||||
} else {
|
||||
/* The user passed an AioContext. Not supported yet. */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,12 +174,17 @@ qio_net_listener_unwatch(QIONetListener *listener, const char *caller)
|
||||
}
|
||||
|
||||
trace_qio_net_listener_unwatch(listener, listener->io_func,
|
||||
listener->context, caller);
|
||||
listener->context, listener->aio_context,
|
||||
caller);
|
||||
for (i = 0; i < listener->nsioc; i++) {
|
||||
if (listener->io_source[i]) {
|
||||
g_source_destroy(listener->io_source[i]);
|
||||
g_source_unref(listener->io_source[i]);
|
||||
listener->io_source[i] = NULL;
|
||||
if (!listener->aio_context) {
|
||||
if (listener->source[i]->io_source) {
|
||||
g_source_destroy(listener->source[i]->io_source);
|
||||
g_source_unref(listener->source[i]->io_source);
|
||||
listener->source[i]->io_source = NULL;
|
||||
}
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,13 +196,12 @@ void qio_net_listener_add(QIONetListener *listener,
|
||||
qio_channel_set_name(QIO_CHANNEL(sioc), listener->name);
|
||||
}
|
||||
|
||||
listener->sioc = g_renew(QIOChannelSocket *, listener->sioc,
|
||||
listener->nsioc + 1);
|
||||
listener->io_source = g_renew(typeof(listener->io_source[0]),
|
||||
listener->io_source,
|
||||
listener->nsioc + 1);
|
||||
listener->sioc[listener->nsioc] = sioc;
|
||||
listener->io_source[listener->nsioc] = NULL;
|
||||
listener->source = g_renew(typeof(listener->source[0]),
|
||||
listener->source,
|
||||
listener->nsioc + 1);
|
||||
listener->source[listener->nsioc] = g_new0(QIONetListenerSource, 1);
|
||||
listener->source[listener->nsioc]->sioc = sioc;
|
||||
listener->source[listener->nsioc]->listener = listener;
|
||||
|
||||
object_ref(OBJECT(sioc));
|
||||
listener->connected = true;
|
||||
@@ -189,15 +212,18 @@ void qio_net_listener_add(QIONetListener *listener,
|
||||
}
|
||||
|
||||
|
||||
void qio_net_listener_set_client_func_full(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify,
|
||||
GMainContext *context)
|
||||
static void
|
||||
qio_net_listener_set_client_func_internal(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify,
|
||||
GMainContext *context,
|
||||
AioContext *aio_context)
|
||||
{
|
||||
QEMU_LOCK_GUARD(&listener->lock);
|
||||
if (listener->io_func == func && listener->io_data == data &&
|
||||
listener->io_notify == notify && listener->context == context) {
|
||||
listener->io_notify == notify && listener->context == context &&
|
||||
listener->aio_context == aio_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -209,17 +235,28 @@ void qio_net_listener_set_client_func_full(QIONetListener *listener,
|
||||
listener->io_data = data;
|
||||
listener->io_notify = notify;
|
||||
listener->context = context;
|
||||
listener->aio_context = aio_context;
|
||||
|
||||
qio_net_listener_watch(listener, 0, "set_client_func");
|
||||
}
|
||||
|
||||
void qio_net_listener_set_client_func_full(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify,
|
||||
GMainContext *context)
|
||||
{
|
||||
qio_net_listener_set_client_func_internal(listener, func, data,
|
||||
notify, context, NULL);
|
||||
}
|
||||
|
||||
void qio_net_listener_set_client_func(QIONetListener *listener,
|
||||
QIONetListenerClientFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
qio_net_listener_set_client_func_full(listener, func, data,
|
||||
notify, NULL);
|
||||
qio_net_listener_set_client_func_internal(listener, func, data,
|
||||
notify, NULL, NULL);
|
||||
}
|
||||
|
||||
struct QIONetListenerClientWaitData {
|
||||
@@ -268,8 +305,8 @@ QIOChannelSocket *qio_net_listener_wait_client(QIONetListener *listener)
|
||||
|
||||
sources = g_new0(GSource *, listener->nsioc);
|
||||
for (i = 0; i < listener->nsioc; i++) {
|
||||
sources[i] = qio_channel_create_watch(QIO_CHANNEL(listener->sioc[i]),
|
||||
G_IO_IN);
|
||||
sources[i] = qio_channel_create_watch(
|
||||
QIO_CHANNEL(listener->source[i]->sioc), G_IO_IN);
|
||||
|
||||
g_source_set_callback(sources[i],
|
||||
(GSourceFunc)qio_net_listener_wait_client_func,
|
||||
@@ -305,7 +342,7 @@ void qio_net_listener_disconnect(QIONetListener *listener)
|
||||
QEMU_LOCK_GUARD(&listener->lock);
|
||||
qio_net_listener_unwatch(listener, "disconnect");
|
||||
for (i = 0; i < listener->nsioc; i++) {
|
||||
qio_channel_close(QIO_CHANNEL(listener->sioc[i]), NULL);
|
||||
qio_channel_close(QIO_CHANNEL(listener->source[i]->sioc), NULL);
|
||||
}
|
||||
listener->connected = false;
|
||||
}
|
||||
@@ -326,7 +363,7 @@ QIOChannelSocket *qio_net_listener_sioc(QIONetListener *listener, size_t n)
|
||||
if (n >= listener->nsioc) {
|
||||
return NULL;
|
||||
}
|
||||
return listener->sioc[n];
|
||||
return listener->source[n]->sioc;
|
||||
}
|
||||
|
||||
SocketAddress *
|
||||
@@ -354,10 +391,10 @@ static void qio_net_listener_finalize(Object *obj)
|
||||
}
|
||||
|
||||
for (i = 0; i < listener->nsioc; i++) {
|
||||
object_unref(OBJECT(listener->sioc[i]));
|
||||
object_unref(OBJECT(listener->source[i]->sioc));
|
||||
g_free(listener->source[i]);
|
||||
}
|
||||
g_free(listener->io_source);
|
||||
g_free(listener->sioc);
|
||||
g_free(listener->source);
|
||||
g_free(listener->name);
|
||||
qemu_mutex_destroy(&listener->lock);
|
||||
}
|
||||
|
||||
@@ -74,6 +74,6 @@ qio_channel_command_abort(void *ioc, int pid) "Command abort ioc=%p pid=%d"
|
||||
qio_channel_command_wait(void *ioc, int pid, int ret, int status) "Command abort ioc=%p pid=%d ret=%d status=%d"
|
||||
|
||||
# net-listener.c
|
||||
qio_net_listener_watch(void *listener, void *func, void *ctx, const char *extra) "Net listener=%p watch enabled func=%p ctx=%p by %s"
|
||||
qio_net_listener_unwatch(void *listener, void *func, void *ctx, const char *extra) "Net listener=%p watch disabled func=%p ctx=%p by %s"
|
||||
qio_net_listener_callback(void *listener, void *func, void *ctx) "Net listener=%p callback forwarding to func=%p ctx=%p"
|
||||
qio_net_listener_watch(void *listener, void *func, void *gctx, void *actx, const char *extra) "Net listener=%p watch enabled func=%p ctx=%p/%p by %s"
|
||||
qio_net_listener_unwatch(void *listener, void *func, void *gctx, void *actx, const char *extra) "Net listener=%p watch disabled func=%p ctx=%p/%p by %s"
|
||||
qio_net_listener_callback(void *listener, void *func, void *gctx, void *actx) "Net listener=%p callback forwarding to func=%p ctx=%p/%p"
|
||||
|
||||
Reference in New Issue
Block a user