qemu/contrib/libvhost-user/libvhost-user-glib.c
<<
>>
Prefs
   1/*
   2 * Vhost User library
   3 *
   4 * Copyright (c) 2016 Nutanix Inc. All rights reserved.
   5 * Copyright (c) 2017 Red Hat, Inc.
   6 *
   7 * Authors:
   8 *  Marc-André Lureau <mlureau@redhat.com>
   9 *  Felipe Franciosi <felipe@nutanix.com>
  10 *
  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.
  13 */
  14
  15#include "qemu/osdep.h"
  16
  17#include "libvhost-user-glib.h"
  18
  19/* glib event loop integration for libvhost-user and misc callbacks */
  20
  21G_STATIC_ASSERT((int)G_IO_IN == (int)VU_WATCH_IN);
  22G_STATIC_ASSERT((int)G_IO_OUT == (int)VU_WATCH_OUT);
  23G_STATIC_ASSERT((int)G_IO_PRI == (int)VU_WATCH_PRI);
  24G_STATIC_ASSERT((int)G_IO_ERR == (int)VU_WATCH_ERR);
  25G_STATIC_ASSERT((int)G_IO_HUP == (int)VU_WATCH_HUP);
  26
  27typedef struct VugSrc {
  28    GSource parent;
  29    VuDev *dev;
  30    GPollFD gfd;
  31} VugSrc;
  32
  33static gboolean
  34vug_src_prepare(GSource *gsrc, gint *timeout)
  35{
  36    g_assert(timeout);
  37
  38    *timeout = -1;
  39    return FALSE;
  40}
  41
  42static gboolean
  43vug_src_check(GSource *gsrc)
  44{
  45    VugSrc *src = (VugSrc *)gsrc;
  46
  47    g_assert(src);
  48
  49    return src->gfd.revents & src->gfd.events;
  50}
  51
  52static gboolean
  53vug_src_dispatch(GSource *gsrc, GSourceFunc cb, gpointer data)
  54{
  55    VugSrc *src = (VugSrc *)gsrc;
  56
  57    g_assert(src);
  58
  59    ((vu_watch_cb)cb)(src->dev, src->gfd.revents, data);
  60
  61    return G_SOURCE_CONTINUE;
  62}
  63
  64static GSourceFuncs vug_src_funcs = {
  65    vug_src_prepare,
  66    vug_src_check,
  67    vug_src_dispatch,
  68    NULL
  69};
  70
  71GSource *
  72vug_source_new(VugDev *gdev, int fd, GIOCondition cond,
  73               vu_watch_cb vu_cb, gpointer data)
  74{
  75    VuDev *dev = &gdev->parent;
  76    GSource *gsrc;
  77    VugSrc *src;
  78    guint id;
  79
  80    g_assert(gdev);
  81    g_assert(fd >= 0);
  82    g_assert(vu_cb);
  83
  84    gsrc = g_source_new(&vug_src_funcs, sizeof(VugSrc));
  85    g_source_set_callback(gsrc, (GSourceFunc)vu_cb, data, NULL);
  86    src = (VugSrc *)gsrc;
  87    src->dev = dev;
  88    src->gfd.fd = fd;
  89    src->gfd.events = cond;
  90
  91    g_source_add_poll(gsrc, &src->gfd);
  92    id = g_source_attach(gsrc, NULL);
  93    g_assert(id);
  94    g_source_unref(gsrc);
  95
  96    return gsrc;
  97}
  98
  99static void
 100set_watch(VuDev *vu_dev, int fd, int vu_evt, vu_watch_cb cb, void *pvt)
 101{
 102    GSource *src;
 103    VugDev *dev;
 104
 105    g_assert(vu_dev);
 106    g_assert(fd >= 0);
 107    g_assert(cb);
 108
 109    dev = container_of(vu_dev, VugDev, parent);
 110    src = vug_source_new(dev, fd, vu_evt, cb, pvt);
 111    g_hash_table_replace(dev->fdmap, GINT_TO_POINTER(fd), src);
 112}
 113
 114static void
 115remove_watch(VuDev *vu_dev, int fd)
 116{
 117    VugDev *dev;
 118
 119    g_assert(vu_dev);
 120    g_assert(fd >= 0);
 121
 122    dev = container_of(vu_dev, VugDev, parent);
 123    g_hash_table_remove(dev->fdmap, GINT_TO_POINTER(fd));
 124}
 125
 126
 127static void vug_watch(VuDev *dev, int condition, void *data)
 128{
 129    if (!vu_dispatch(dev) != 0) {
 130        dev->panic(dev, "Error processing vhost message");
 131    }
 132}
 133
 134bool
 135vug_init(VugDev *dev, uint16_t max_queues, int socket,
 136         vu_panic_cb panic, const VuDevIface *iface)
 137{
 138    g_assert(dev);
 139    g_assert(iface);
 140
 141    if (!vu_init(&dev->parent, max_queues, socket, panic, set_watch,
 142                 remove_watch, iface)) {
 143        return false;
 144    }
 145
 146    dev->fdmap = g_hash_table_new_full(NULL, NULL, NULL,
 147                                       (GDestroyNotify) g_source_destroy);
 148
 149    dev->src = vug_source_new(dev, socket, G_IO_IN, vug_watch, NULL);
 150
 151    return true;
 152}
 153
 154void
 155vug_deinit(VugDev *dev)
 156{
 157    g_assert(dev);
 158
 159    g_hash_table_unref(dev->fdmap);
 160    g_source_unref(dev->src);
 161}
 162