From bd4ea39dec291dba9e8b6ad845e80cd534a21eaf Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Thu, 19 Aug 2010 13:45:03 +0800 Subject: [PATCH] Use VT_WAITEVENT if available to avoid spawn too many threads Starting from linux kernel 2.6.32 there is a new ioctl VT_WAITEVENT which can monitor vt switches and return new vt number. https://bugs.freedesktop.org/show_bug.cgi?id=17720 --- Please CC me on any replies (non-subscriber) src/ck-sysdeps-unix.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/ck-sysdeps.h | 2 ++ src/ck-vt-monitor.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/ck-sysdeps-unix.c b/src/ck-sysdeps-unix.c index e4ab16b..90c514d 100644 --- a/src/ck-sysdeps-unix.c +++ b/src/ck-sysdeps-unix.c @@ -296,6 +296,50 @@ ck_wait_for_active_console_num (int console_fd, return ret; } +#ifdef VT_WAITEVENT +gboolean +ck_wait_for_console_switch (int console_fd, + guint *num) +{ + gboolean ret; + int res; + struct vt_event vt; + + g_assert (console_fd != -1); + + again: + ret = FALSE; + errno = 0; + vt.event = VT_EVENT_SWITCH; + vt.oldev = num; + res = ioctl (console_fd, VT_WAITEVENT, &vt); + + if (res == ERROR) { + const char *errmsg; + + errmsg = g_strerror (errno); + + if (errno == EINTR) { + g_debug ("Interrupted waiting for native console event: %s", + errmsg); + goto again; + } else if (errno == ENOTSUP) { + g_debug ("Console event not supported on this system"); + } else { + g_warning ("Error waiting for native console event: %s", + errmsg); + } + goto out; + } + + ret = TRUE; + *num = vt.newev; + + out: + return ret; +} +#endif + gboolean ck_activate_console_num (int console_fd, guint num) diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h index 8f22d52..5dd573f 100644 --- a/src/ck-sysdeps.h +++ b/src/ck-sysdeps.h @@ -72,6 +72,8 @@ gboolean ck_activate_console_num (int console_fd, guint num); gboolean ck_wait_for_active_console_num (int console_fd, guint num); +gboolean ck_wait_for_console_switch (int console_fd, + guint *num); G_END_DECLS diff --git a/src/ck-vt-monitor.c b/src/ck-vt-monitor.c index 67a1f49..414bdbb 100644 --- a/src/ck-vt-monitor.c +++ b/src/ck-vt-monitor.c @@ -40,7 +40,7 @@ #include "ck-sysdeps.h" #include "ck-marshal.h" -#if defined (__sun) && defined (HAVE_SYS_VT_H) +#ifdef HAVE_SYS_VT_H #include #include #include @@ -163,7 +163,7 @@ ck_vt_monitor_get_active (CkVtMonitor *vt_monitor, return TRUE; } -#if defined (__sun) && defined (HAVE_SYS_VT_H) +#ifdef HAVE_SYS_VT_H static void handle_vt_active (void) { @@ -318,6 +318,26 @@ vt_thread_start (ThreadData *data) vt_monitor = data->vt_monitor; num = data->num; +#ifdef VT_WAITEVENT + for (;;) { + res = ck_wait_for_console_switch (vt_monitor->priv->vfd, &num); + if (! res) { + break; + } else { + EventData *event; + + /* add event to queue */ + event = g_new0 (EventData, 1); + event->num = num; + g_debug ("Pushing activation event for VT %d onto queue", num); + + g_async_queue_push (vt_monitor->priv->event_queue, event); + + /* schedule processing of queue */ + schedule_process_queue (vt_monitor); + } + } +#else res = ck_wait_for_active_console_num (vt_monitor->priv->vfd, num); if (! res) { /* FIXME: what do we do if it fails? */ @@ -334,6 +354,7 @@ vt_thread_start (ThreadData *data) /* schedule processing of queue */ schedule_process_queue (vt_monitor); } +#endif G_LOCK (hash_lock); if (vt_monitor->priv->vt_thread_hash != NULL) { @@ -398,6 +419,13 @@ vt_add_watches (CkVtMonitor *vt_monitor) sigaction (SIGPOLL, &act, NULL); ioctl (vt_monitor->priv->vfd, I_SETSIG, S_MSG); +#elif defined (VT_WAITEVENT) + G_LOCK (hash_lock); + gpointer id; + id = GINT_TO_POINTER (1); + if (g_hash_table_lookup (vt_monitor->priv->vt_thread_hash, id) == NULL) + vt_add_watch_unlocked (vt_monitor, 1); + G_UNLOCK (hash_lock); #else G_LOCK (hash_lock); -- 1.7.1