[ConsoleKit] [PATCH] Use VT_WAITEVENT if available to avoid spawn too many threads
Kan-Ru Chen
koster at debian.org
Thu Aug 19 02:35:05 PDT 2010
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 <sys/vt.h>
#include <signal.h>
#include <stropts.h>
@@ -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
More information about the ConsoleKit
mailing list