/* * QEMU I/O channels watch helper APIs * * Copyright (c) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . * */ #include "io/channel-watch.h" typedef struct QIOChannelFDSource QIOChannelFDSource; struct QIOChannelFDSource { GSource parent; GPollFD fd; QIOChannel *ioc; GIOCondition condition; }; typedef struct QIOChannelFDPairSource QIOChannelFDPairSource; struct QIOChannelFDPairSource { GSource parent; GPollFD fdread; GPollFD fdwrite; QIOChannel *ioc; GIOCondition condition; }; static gboolean qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED, gint *timeout) { *timeout = -1; return FALSE; } static gboolean qio_channel_fd_source_check(GSource *source) { QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; return ssource->fd.revents & ssource->condition; } static gboolean qio_channel_fd_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { QIOChannelFunc func = (QIOChannelFunc)callback; QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; return (*func)(ssource->ioc, ssource->fd.revents & ssource->condition, user_data); } static void qio_channel_fd_source_finalize(GSource *source) { QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; object_unref(OBJECT(ssource->ioc)); } static gboolean qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED, gint *timeout) { *timeout = -1; return FALSE; } static gboolean qio_channel_fd_pair_source_check(GSource *source) { QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; GIOCondition poll_condition = ssource->fdread.revents | ssource->fdwrite.revents; return poll_condition & ssource->condition; } static gboolean qio_channel_fd_pair_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { QIOChannelFunc func = (QIOChannelFunc)callback; QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; GIOCondition poll_condition = ssource->fdread.revents | ssource->fdwrite.revents; return (*func)(ssource->ioc, poll_condition & ssource->condition, user_data); } static void qio_channel_fd_pair_source_finalize(GSource *source) { QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; object_unref(OBJECT(ssource->ioc)); } GSourceFuncs qio_channel_fd_source_funcs = { qio_channel_fd_source_prepare, qio_channel_fd_source_check, qio_channel_fd_source_dispatch, qio_channel_fd_source_finalize }; GSourceFuncs qio_channel_fd_pair_source_funcs = { qio_channel_fd_pair_source_prepare, qio_channel_fd_pair_source_check, qio_channel_fd_pair_source_dispatch, qio_channel_fd_pair_source_finalize }; GSource *qio_channel_create_fd_watch(QIOChannel *ioc, int fd, GIOCondition condition) { GSource *source; QIOChannelFDSource *ssource; source = g_source_new(&qio_channel_fd_source_funcs, sizeof(QIOChannelFDSource)); ssource = (QIOChannelFDSource *)source; ssource->ioc = ioc; object_ref(OBJECT(ioc)); ssource->condition = condition; ssource->fd.fd = fd; ssource->fd.events = condition; g_source_add_poll(source, &ssource->fd); return source; } GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc, int fdread, int fdwrite, GIOCondition condition) { GSource *source; QIOChannelFDPairSource *ssource; source = g_source_new(&qio_channel_fd_pair_source_funcs, sizeof(QIOChannelFDPairSource)); ssource = (QIOChannelFDPairSource *)source; ssource->ioc = ioc; object_ref(OBJECT(ioc)); ssource->condition = condition; ssource->fdread.fd = fdread; ssource->fdread.events = condition & G_IO_IN; ssource->fdwrite.fd = fdwrite; ssource->fdwrite.events = condition & G_IO_OUT; g_source_add_poll(source, &ssource->fdread); g_source_add_poll(source, &ssource->fdwrite); return source; }