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 "libvhost-user-glib.h"
18 #define container_of(ptr, type, member) \
20 void *__mptr = (void *)(ptr); \
21 ((type *)(__mptr - offsetof(type, member))); \
25 /* glib event loop integration for libvhost-user and misc callbacks */
27 G_STATIC_ASSERT((int)G_IO_IN
== (int)VU_WATCH_IN
);
28 G_STATIC_ASSERT((int)G_IO_OUT
== (int)VU_WATCH_OUT
);
29 G_STATIC_ASSERT((int)G_IO_PRI
== (int)VU_WATCH_PRI
);
30 G_STATIC_ASSERT((int)G_IO_ERR
== (int)VU_WATCH_ERR
);
31 G_STATIC_ASSERT((int)G_IO_HUP
== (int)VU_WATCH_HUP
);
33 typedef struct VugSrc
{
40 vug_src_prepare(GSource
*gsrc
, gint
*timeout
)
49 vug_src_check(GSource
*gsrc
)
51 VugSrc
*src
= (VugSrc
*)gsrc
;
55 return src
->gfd
.revents
& src
->gfd
.events
;
59 vug_src_dispatch(GSource
*gsrc
, GSourceFunc cb
, gpointer data
)
61 VugSrc
*src
= (VugSrc
*)gsrc
;
65 ((vu_watch_cb
)cb
)(src
->dev
, src
->gfd
.revents
, data
);
67 return G_SOURCE_CONTINUE
;
70 static GSourceFuncs vug_src_funcs
= {
78 vug_source_new(VugDev
*gdev
, int fd
, GIOCondition cond
,
79 vu_watch_cb vu_cb
, gpointer data
)
81 VuDev
*dev
= &gdev
->parent
;
90 gsrc
= g_source_new(&vug_src_funcs
, sizeof(VugSrc
));
91 g_source_set_callback(gsrc
, (GSourceFunc
)vu_cb
, data
, NULL
);
95 src
->gfd
.events
= cond
;
97 g_source_add_poll(gsrc
, &src
->gfd
);
98 id
= g_source_attach(gsrc
, g_main_context_get_thread_default());
105 set_watch(VuDev
*vu_dev
, int fd
, int vu_evt
, vu_watch_cb cb
, void *pvt
)
114 dev
= container_of(vu_dev
, VugDev
, parent
);
115 src
= vug_source_new(dev
, fd
, vu_evt
, cb
, pvt
);
116 g_hash_table_replace(dev
->fdmap
, GINT_TO_POINTER(fd
), src
);
120 remove_watch(VuDev
*vu_dev
, int fd
)
127 dev
= container_of(vu_dev
, VugDev
, parent
);
128 g_hash_table_remove(dev
->fdmap
, GINT_TO_POINTER(fd
));
132 static void vug_watch(VuDev
*dev
, int condition
, void *data
)
134 if (!vu_dispatch(dev
) != 0) {
135 dev
->panic(dev
, "Error processing vhost message");
139 void vug_source_destroy(GSource
*src
)
145 g_source_destroy(src
);
150 vug_init(VugDev
*dev
, uint16_t max_queues
, int socket
,
151 vu_panic_cb panic
, const VuDevIface
*iface
)
156 if (!vu_init(&dev
->parent
, max_queues
, socket
, panic
, NULL
, set_watch
,
157 remove_watch
, iface
)) {
161 dev
->fdmap
= g_hash_table_new_full(NULL
, NULL
, NULL
,
162 (GDestroyNotify
) vug_source_destroy
);
164 dev
->src
= vug_source_new(dev
, socket
, G_IO_IN
, vug_watch
, NULL
);
170 vug_deinit(VugDev
*dev
)
174 g_hash_table_unref(dev
->fdmap
);
175 vug_source_destroy(dev
->src
);