aboutsummaryrefslogtreecommitdiff
path: root/chardev
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2018-01-04 22:18:35 +0800
committerPaolo Bonzini <pbonzini@redhat.com>2018-01-12 13:22:02 +0100
commit2c716ba1506769c9be2caa02f0f6d6e7c00f4304 (patch)
tree233189ca8b845f83871b104d50dcdedcb264484c /chardev
parent938eb9e9c83d34d90cac6ec5c5388e7998840e4e (diff)
downloadqemu-2c716ba1506769c9be2caa02f0f6d6e7c00f4304.zip
qemu-2c716ba1506769c9be2caa02f0f6d6e7c00f4304.tar.gz
qemu-2c716ba1506769c9be2caa02f0f6d6e7c00f4304.tar.bz2
chardev: introduce qemu_chr_timeout_add_ms()
It's a replacement of g_timeout_add[_seconds]() for chardevs. Chardevs now can have dedicated gcontext, we should always bind chardev tasks onto those gcontext rather than the default main context. Since there are quite a few of g_timeout_add[_seconds]() callers, a new function qemu_chr_timeout_add_ms() is introduced. One thing to mention is that, terminal3270 is still always running on main gcontext. However let's convert that as well since it's still part of chardev codes and in case one day we'll miss that when we move it out of main gcontext too. Also, convert all the timers from GSource tags into GSource pointers. Gsource tag IDs and g_source_remove()s can only work with default gcontext, while now these GSources can logically be attached to other contexts. So let's use explicit g_source_destroy() plus another g_source_unref() to remove a timer. Note: when in the timer handler, we don't need the g_source_destroy() any more since that'll be done automatically if the timer handler returns false (and that's what all the current handlers do). Yet another note: in pty_chr_rearm_timer() we take special care for ms=1000. This patch merged the two cases into one. Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <20180104141835.17987-4-peterx@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'chardev')
-rw-r--r--chardev/char-pty.c43
-rw-r--r--chardev/char-socket.c28
-rw-r--r--chardev/char.c18
3 files changed, 55 insertions, 34 deletions
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 8248e36..89315e6 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -42,7 +42,7 @@ typedef struct {
/* Protected by the Chardev chr_write_lock. */
int connected;
- guint timer_tag;
+ GSource *timer_src;
GSource *open_source;
} PtyChardev;
@@ -57,7 +57,8 @@ static gboolean pty_chr_timer(gpointer opaque)
PtyChardev *s = PTY_CHARDEV(opaque);
qemu_mutex_lock(&chr->chr_write_lock);
- s->timer_tag = 0;
+ s->timer_src = NULL;
+ g_source_unref(s->open_source);
s->open_source = NULL;
if (!s->connected) {
/* Next poll ... */
@@ -67,25 +68,25 @@ static gboolean pty_chr_timer(gpointer opaque)
return FALSE;
}
+static void pty_chr_timer_cancel(PtyChardev *s)
+{
+ if (s->timer_src) {
+ g_source_destroy(s->timer_src);
+ g_source_unref(s->timer_src);
+ s->timer_src = NULL;
+ }
+}
+
/* Called with chr_write_lock held. */
static void pty_chr_rearm_timer(Chardev *chr, int ms)
{
PtyChardev *s = PTY_CHARDEV(chr);
char *name;
- if (s->timer_tag) {
- g_source_remove(s->timer_tag);
- s->timer_tag = 0;
- }
-
- if (ms == 1000) {
- name = g_strdup_printf("pty-timer-secs-%s", chr->label);
- s->timer_tag = g_timeout_add_seconds(1, pty_chr_timer, chr);
- } else {
- name = g_strdup_printf("pty-timer-ms-%s", chr->label);
- s->timer_tag = g_timeout_add(ms, pty_chr_timer, chr);
- }
- g_source_set_name_by_id(s->timer_tag, name);
+ pty_chr_timer_cancel(s);
+ name = g_strdup_printf("pty-timer-%s", chr->label);
+ s->timer_src = qemu_chr_timeout_add_ms(chr, ms, pty_chr_timer, chr);
+ g_source_set_name(s->timer_src, name);
g_free(name);
}
@@ -206,10 +207,7 @@ static void pty_chr_state(Chardev *chr, int connected)
* the virtual device linked to our pty. */
pty_chr_rearm_timer(chr, 1000);
} else {
- if (s->timer_tag) {
- g_source_remove(s->timer_tag);
- s->timer_tag = 0;
- }
+ pty_chr_timer_cancel(s);
if (!s->connected) {
g_assert(s->open_source == NULL);
s->open_source = g_idle_source_new();
@@ -236,10 +234,7 @@ static void char_pty_finalize(Object *obj)
qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_state(chr, 0);
object_unref(OBJECT(s->ioc));
- if (s->timer_tag) {
- g_source_remove(s->timer_tag);
- s->timer_tag = 0;
- }
+ pty_chr_timer_cancel(s);
qemu_mutex_unlock(&chr->chr_write_lock);
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
@@ -272,7 +267,7 @@ static void char_pty_open(Chardev *chr,
name = g_strdup_printf("chardev-pty-%s", chr->label);
qio_channel_set_name(QIO_CHANNEL(s->ioc), name);
g_free(name);
- s->timer_tag = 0;
+ s->timer_src = NULL;
*be_opened = false;
}
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 630a7f2..77cdf48 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -57,7 +57,7 @@ typedef struct {
bool is_telnet;
bool is_tn3270;
- guint reconnect_timer;
+ GSource *reconnect_timer;
int64_t reconnect_time;
bool connect_err_reported;
} SocketChardev;
@@ -67,16 +67,27 @@ typedef struct {
static gboolean socket_reconnect_timeout(gpointer opaque);
+static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
+{
+ if (s->reconnect_timer) {
+ g_source_destroy(s->reconnect_timer);
+ g_source_unref(s->reconnect_timer);
+ s->reconnect_timer = NULL;
+ }
+}
+
static void qemu_chr_socket_restart_timer(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
char *name;
assert(s->connected == 0);
- s->reconnect_timer = g_timeout_add_seconds(s->reconnect_time,
- socket_reconnect_timeout, chr);
name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
- g_source_set_name_by_id(s->reconnect_timer, name);
+ s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
+ s->reconnect_time * 1000,
+ socket_reconnect_timeout,
+ chr);
+ g_source_set_name(s->reconnect_timer, name);
g_free(name);
}
@@ -781,11 +792,7 @@ static void char_socket_finalize(Object *obj)
SocketChardev *s = SOCKET_CHARDEV(obj);
tcp_chr_free_connection(chr);
-
- if (s->reconnect_timer) {
- g_source_remove(s->reconnect_timer);
- s->reconnect_timer = 0;
- }
+ tcp_chr_reconn_timer_cancel(s);
qapi_free_SocketAddress(s->addr);
if (s->listener) {
qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
@@ -824,7 +831,8 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
SocketChardev *s = SOCKET_CHARDEV(opaque);
QIOChannelSocket *sioc;
- s->reconnect_timer = 0;
+ g_source_unref(s->reconnect_timer);
+ s->reconnect_timer = NULL;
if (chr->be_open) {
return false;
diff --git a/chardev/char.c b/chardev/char.c
index 8c3765e..3e14de1 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -1084,6 +1084,24 @@ void qmp_chardev_send_break(const char *id, Error **errp)
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
}
+/*
+ * Add a timeout callback for the chardev (in milliseconds), return
+ * the GSource object created. Please use this to add timeout hook for
+ * chardev instead of g_timeout_add() and g_timeout_add_seconds(), to
+ * make sure the gcontext that the task bound to is correct.
+ */
+GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms,
+ GSourceFunc func, void *private)
+{
+ GSource *source = g_timeout_source_new(ms);
+
+ assert(func);
+ g_source_set_callback(source, func, private, NULL);
+ g_source_attach(source, chr->gcontext);
+
+ return source;
+}
+
void qemu_chr_cleanup(void)
{
object_unparent(get_chardevs_root());