4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include "qemu/osdep.h"
25 #include "chardev/char-io.h"
27 typedef struct IOWatchPoll
{
33 IOCanReadHandler
*fd_can_read
;
36 GMainContext
*context
;
39 static IOWatchPoll
*io_watch_poll_from_source(GSource
*source
)
41 return container_of(source
, IOWatchPoll
, parent
);
44 static gboolean
io_watch_poll_prepare(GSource
*source
,
47 IOWatchPoll
*iwp
= io_watch_poll_from_source(source
);
48 bool now_active
= iwp
->fd_can_read(iwp
->opaque
) > 0;
49 bool was_active
= iwp
->src
!= NULL
;
50 if (was_active
== now_active
) {
55 * We do not register the QIOChannel watch as a child GSource.
56 * The 'prepare' function on the parent GSource will be
57 * skipped if a child GSource's 'prepare' function indicates
58 * readiness. We need this prepare function be guaranteed
59 * to run on *every* iteration of the main loop, because
60 * it is critical to ensure we remove the QIOChannel watch
61 * if 'fd_can_read' indicates the frontend cannot receive
65 iwp
->src
= qio_channel_create_watch(
66 iwp
->ioc
, G_IO_IN
| G_IO_ERR
| G_IO_HUP
| G_IO_NVAL
);
67 g_source_set_callback(iwp
->src
, iwp
->fd_read
, iwp
->opaque
, NULL
);
68 g_source_attach(iwp
->src
, iwp
->context
);
70 g_source_destroy(iwp
->src
);
71 g_source_unref(iwp
->src
);
77 static gboolean
io_watch_poll_check(GSource
*source
)
82 static gboolean
io_watch_poll_dispatch(GSource
*source
, GSourceFunc callback
,
88 static void io_watch_poll_finalize(GSource
*source
)
91 * Due to a glib bug, removing the last reference to a source
92 * inside a finalize callback causes recursive locking (and a
93 * deadlock). This is not a problem inside other callbacks,
94 * including dispatch callbacks, so we call io_remove_watch_poll
95 * to remove this source. At this point, iwp->src must
96 * be NULL, or we would leak it.
98 IOWatchPoll
*iwp
= io_watch_poll_from_source(source
);
99 assert(iwp
->src
== NULL
);
102 static GSourceFuncs io_watch_poll_funcs
= {
103 .prepare
= io_watch_poll_prepare
,
104 .check
= io_watch_poll_check
,
105 .dispatch
= io_watch_poll_dispatch
,
106 .finalize
= io_watch_poll_finalize
,
109 GSource
*io_add_watch_poll(Chardev
*chr
,
111 IOCanReadHandler
*fd_can_read
,
112 QIOChannelFunc fd_read
,
114 GMainContext
*context
)
119 iwp
= (IOWatchPoll
*) g_source_new(&io_watch_poll_funcs
,
120 sizeof(IOWatchPoll
));
121 iwp
->fd_can_read
= fd_can_read
;
122 iwp
->opaque
= user_data
;
124 iwp
->fd_read
= (GSourceFunc
) fd_read
;
126 iwp
->context
= context
;
128 name
= g_strdup_printf("chardev-iowatch-%s", chr
->label
);
129 g_source_set_name((GSource
*)iwp
, name
);
132 g_source_attach(&iwp
->parent
, context
);
133 g_source_unref(&iwp
->parent
);
134 return (GSource
*)iwp
;
137 static void io_remove_watch_poll(GSource
*source
)
141 iwp
= io_watch_poll_from_source(source
);
143 g_source_destroy(iwp
->src
);
144 g_source_unref(iwp
->src
);
147 g_source_destroy(&iwp
->parent
);
150 void remove_fd_in_watch(Chardev
*chr
)
153 io_remove_watch_poll(chr
->gsource
);
158 int io_channel_send_full(QIOChannel
*ioc
,
159 const void *buf
, size_t len
,
160 int *fds
, size_t nfds
)
164 while (offset
< len
) {
166 struct iovec iov
= { .iov_base
= (char *)buf
+ offset
,
167 .iov_len
= len
- offset
};
169 ret
= qio_channel_writev_full(
172 if (ret
== QIO_CHANNEL_ERR_BLOCK
) {
179 } else if (ret
< 0) {
190 int io_channel_send(QIOChannel
*ioc
, const void *buf
, size_t len
)
192 return io_channel_send_full(ioc
, buf
, len
, NULL
, 0);