4 * Copyright (c) 2016 Nutanix Inc. All rights reserved.
5 * Copyright (c) 2017 Red Hat, Inc.
8 * Marc-André Lureau <mlureau@redhat.com>
9 * Felipe Franciosi <felipe@nutanix.com>
11 * This work is licensed under the terms of the GNU GPL, version 2 or
12 * later. See the COPYING file in the top-level directory.
15 #include "qemu/osdep.h"
17 #include "libvhost-user-glib.h"
19 /* glib event loop integration for libvhost-user and misc callbacks */
21 G_STATIC_ASSERT((int)G_IO_IN
== (int)VU_WATCH_IN
);
22 G_STATIC_ASSERT((int)G_IO_OUT
== (int)VU_WATCH_OUT
);
23 G_STATIC_ASSERT((int)G_IO_PRI
== (int)VU_WATCH_PRI
);
24 G_STATIC_ASSERT((int)G_IO_ERR
== (int)VU_WATCH_ERR
);
25 G_STATIC_ASSERT((int)G_IO_HUP
== (int)VU_WATCH_HUP
);
27 typedef struct VugSrc
{
34 vug_src_prepare(GSource
*gsrc
, gint
*timeout
)
43 vug_src_check(GSource
*gsrc
)
45 VugSrc
*src
= (VugSrc
*)gsrc
;
49 return src
->gfd
.revents
& src
->gfd
.events
;
53 vug_src_dispatch(GSource
*gsrc
, GSourceFunc cb
, gpointer data
)
55 VugSrc
*src
= (VugSrc
*)gsrc
;
59 ((vu_watch_cb
)cb
)(src
->dev
, src
->gfd
.revents
, data
);
61 return G_SOURCE_CONTINUE
;
64 static GSourceFuncs vug_src_funcs
= {
72 vug_source_new(VugDev
*gdev
, int fd
, GIOCondition cond
,
73 vu_watch_cb vu_cb
, gpointer data
)
75 VuDev
*dev
= &gdev
->parent
;
84 gsrc
= g_source_new(&vug_src_funcs
, sizeof(VugSrc
));
85 g_source_set_callback(gsrc
, (GSourceFunc
)vu_cb
, data
, NULL
);
89 src
->gfd
.events
= cond
;
91 g_source_add_poll(gsrc
, &src
->gfd
);
92 id
= g_source_attach(gsrc
, g_main_context_get_thread_default());
99 set_watch(VuDev
*vu_dev
, int fd
, int vu_evt
, vu_watch_cb cb
, void *pvt
)
108 dev
= container_of(vu_dev
, VugDev
, parent
);
109 src
= vug_source_new(dev
, fd
, vu_evt
, cb
, pvt
);
110 g_hash_table_replace(dev
->fdmap
, GINT_TO_POINTER(fd
), src
);
114 remove_watch(VuDev
*vu_dev
, int fd
)
121 dev
= container_of(vu_dev
, VugDev
, parent
);
122 g_hash_table_remove(dev
->fdmap
, GINT_TO_POINTER(fd
));
126 static void vug_watch(VuDev
*dev
, int condition
, void *data
)
128 if (!vu_dispatch(dev
) != 0) {
129 dev
->panic(dev
, "Error processing vhost message");
133 void vug_source_destroy(GSource
*src
)
139 g_source_destroy(src
);
144 vug_init(VugDev
*dev
, uint16_t max_queues
, int socket
,
145 vu_panic_cb panic
, const VuDevIface
*iface
)
150 if (!vu_init(&dev
->parent
, max_queues
, socket
, panic
, set_watch
,
151 remove_watch
, iface
)) {
155 dev
->fdmap
= g_hash_table_new_full(NULL
, NULL
, NULL
,
156 (GDestroyNotify
) vug_source_destroy
);
158 dev
->src
= vug_source_new(dev
, socket
, G_IO_IN
, vug_watch
, NULL
);
164 vug_deinit(VugDev
*dev
)
168 g_hash_table_unref(dev
->fdmap
);
169 vug_source_destroy(dev
->src
);