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
  71static GSource *
  72vug_source_new(VuDev *dev, int fd, GIOCondition cond,
  73               vu_watch_cb vu_cb, gpointer data)
  74{
  75    GSource *gsrc;
  76    VugSrc *src;
  77    guint id;
  78
  79    g_assert(dev);
  80    g_assert(fd >= 0);
  81    g_assert(vu_cb);
  82
  83    gsrc = g_source_new(&vug_src_funcs, sizeof(VugSrc));
  84    g_source_set_callback(gsrc, (GSourceFunc)vu_cb, data, NULL);
  85    src = (VugSrc *)gsrc;
  86    src->dev = dev;
  87    src->gfd.fd = fd;
  88    src->gfd.events = cond;
  89
  90    g_source_add_poll(gsrc, &src->gfd);
  91    id = g_source_attach(gsrc, NULL);
  92    g_assert(id);
  93    g_source_unref(gsrc);
  94
  95    return gsrc;
  96}
  97
  98static void
  99set_watch(VuDev *vu_dev, int fd, int vu_evt, vu_watch_cb cb, void *pvt)
 100{
 101    GSource *src;
 102    VugDev *dev;
 103
 104    g_assert(vu_dev);
 105    g_assert(fd >= 0);
 106    g_assert(cb);
 107
 108    dev = container_of(vu_dev, VugDev, parent);
 109    src = vug_source_new(vu_dev, fd, vu_evt, cb, pvt);
 110    g_hash_table_replace(dev->fdmap, GINT_TO_POINTER(fd), src);
 111}
 112
 113static void
 114remove_watch(VuDev *vu_dev, int fd)
 115{
 116    VugDev *dev;
 117
 118    g_assert(vu_dev);
 119    g_assert(fd >= 0);
 120
 121    dev = container_of(vu_dev, VugDev, parent);
 122    g_hash_table_remove(dev->fdmap, GINT_TO_POINTER(fd));
 123}
 124
 125
 126static void vug_watch(VuDev *dev, int condition, void *data)
 127{
 128    if (!vu_dispatch(dev) != 0) {
 129        dev->panic(dev, "Error processing vhost message");
 130    }
 131}
 132
 133void
 134vug_init(VugDev *dev, int socket,
 135         vu_panic_cb panic, const VuDevIface *iface)
 136{
 137    g_assert(dev);
 138    g_assert(iface);
 139
 140    vu_init(&dev->parent, socket, panic, set_watch, remove_watch, iface);
 141    dev->fdmap = g_hash_table_new_full(NULL, NULL, NULL,
 142                                       (GDestroyNotify) g_source_destroy);
 143
 144    dev->src = vug_source_new(&dev->parent, socket, G_IO_IN, vug_watch, NULL);
 145}
 146
 147void
 148vug_deinit(VugDev *dev)
 149{
 150    g_assert(dev);
 151
 152    g_hash_table_unref(dev->fdmap);
 153    g_source_unref(dev->src);
 154}
 155