--
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
>From 856d2e3906a9a3f1ea55249f43e1ea1310f22d2d Mon Sep 17 00:00:00 2001
From: Tiago Vignatti <[EMAIL PROTECTED]>
Date: Wed, 1 Oct 2008 21:13:26 -0300
Subject: [PATCH] The input-thread core file implementation.
Signed-off-by: Tiago Vignatti <[EMAIL PROTECTED]>
---
os/inputthread.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 280 insertions(+), 0 deletions(-)
create mode 100644 os/inputthread.c
diff --git a/os/inputthread.c b/os/inputthread.c
new file mode 100644
index 0000000..e2eb15f
--- /dev/null
+++ b/os/inputthread.c
@@ -0,0 +1,280 @@
+/* inputthread.c -- The input thread implementation.
+ *
+ * Copyright 2007-2008 Tiago Vignatti <[EMAIL PROTECTED]>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+#include <X11/Xpoll.h>
+
+#include "inputstr.h"
+#include "opaque.h"
+
+
+static int WaitForInput(void* argument);
+
+typedef struct _InputDeviceFunc {
+ void (*f) (void *);
+ int fd;
+ void *closure;
+} InputDeviceFunc;
+
+InputDeviceFunc DevFunc[MAX_DEVICES];
+
+fd_set InputThreadFd; /* Devices monitored by the input thread */
+int MainThreadReadPipe = -1;
+int MainThreadWritePipe = -1;
+int InputThreadReadPipe = -1;
+int InputThreadWritePipe = -1;
+
+pthread_t tid_input;
+
+
+void
+InitInputThread(void)
+{
+ int i, main_to_input[2], input_to_main[2];
+
+ /* The "communication channel" between the input and main thread in
+ * both ways.*/
+ if (pipe(main_to_input) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+ if (pipe(input_to_main) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+
+ /* Make the pipes nonblocking */
+ fcntl(main_to_input[0], F_SETFL, O_NONBLOCK);
+ fcntl(main_to_input[1], F_SETFL, O_NONBLOCK);
+ fcntl(input_to_main[0], F_SETFL, O_NONBLOCK);
+ fcntl(input_to_main[1], F_SETFL, O_NONBLOCK);
+
+ MainThreadReadPipe = main_to_input[0];
+ MainThreadWritePipe = main_to_input[1];
+ InputThreadReadPipe = input_to_main[0];
+ InputThreadWritePipe = input_to_main[1];
+
+
+ FD_ZERO(&InputThreadFd);
+
+ for (i = 0; i < MAX_DEVICES; i++)
+ DevFunc[i].fd = 0;
+}
+
+/*
+ * Called by the dix to create the input thread.
+ */
+void
+CreateInputThread (void)
+{
+ pthread_t input_thread;
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+
+ /* In OSes that differentiates processes and threads this could have some
+ * sense. Linux uses 1:1 thread model. The scheduler handles every thread
+ * as if it were a process. Therefore this bellow have no meaning if your
+ * OS is Linux.
+ */
+ if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0)
+ perror("error setting input thread scope");
+
+ if (pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN) != 0)
+ perror("error setting input thread stack size");
+
+ pthread_create(&input_thread, &attr, (void *)&WaitForInput, NULL);
+ pthread_attr_destroy (&attr);
+}
+
+/*
+ * Called by the dix to close the input thread cleanly.
+ *
+ * TODO: This is a blinded implementation due X server regenaration
+ * is currently broken.
+ */
+void
+CloseInputThread (void)
+{
+ RemoveEnabledDevice(MainThreadReadPipe);
+ FD_ZERO(&InputThreadFd);
+
+ pthread_kill(tid_input, SIGKILL);
+}
+
+/*
+ * Create connections in the input thread. Must be called by the
+ * DDX implementation.
+ */
+void
+AddEnabledDeviceThreaded(int fd, void (*f)(void *), void *closure)
+{
+ int i;
+
+ FD_SET(fd, &InputThreadFd);
+
+ for (i = 0; DevFunc[i].fd != 0; i++)
+ ; /* intentional */
+
+ DevFunc[i].fd = fd;
+ DevFunc[i].f = f;
+ DevFunc[i].closure = closure;
+
+#ifdef THREAD_DEBUG
+ ErrorF("Input thread: Using PTHREAD for input device %d\n", fd);
+#endif
+
+ /* wake up input thread to notify the new device */
+ PipeWrite(InputThreadWritePipe);
+}
+
+/*
+ * Destroy device connection.
+ */
+void
+RemoveEnabledDeviceThreaded(int fd)
+{
+ int i = 0;
+
+ FD_CLR(fd, &InputThreadFd);
+
+ while (DevFunc[i].fd != fd && i < MAX_DEVICES)
+ i++;
+
+ if (i < MAX_DEVICES)
+ DevFunc[i].fd = 0;
+ /*else TODO: things can be wrong */
+
+ /* wake up input thread to notify the new device */
+ PipeWrite(InputThreadWritePipe);
+}
+
+/*
+ * Input events routed through another thread/process can have bad effects on
+ * latency because we canât guarantee that it will get scheduled at the right
+ * moment. Although this is hard to see happening with the current
+ * implementation, we must design something to avoid it. One way to improve
+ * the responsiveness is to give a high priority to the input thread and also
+ * adjust the CPU scheduling.
+ * A detailed discussion can be found here:
+ * http://vignatti.wordpress.com/2008/08/07/priorities-and-scheduling-hints-for-x-server-threads/
+ *
+ * TODO: incorporate this with cgroup, a feature which allows to limit the
+ * amount of CPU time real-time processes and threads may consume.
+ */
+#if 0
+static void
+AdjustThreadScheduling(int tid)
+{
+ struct sched_param param;
+ int policy = SCHED_FIFO;
+
+
+ pthread_t p_tid = pthread_self();
+
+ param.sched_priority = sched_get_priority_max(policy);
+
+ if (pthread_setschedparam(p_tid, policy, ¶m) != 0)
+ perror("error setting thread scheduling");
+
+#ifdef THREAD_DEBUG
+ sched_getparam(tid, ¶m);
+ ErrorF("thread %d: policy: %d, priority: %d\n", tid,
+ sched_getscheduler(tid_generation), param.sched_priority);
+#endif
+}
+#endif
+
+/*
+ * The 'WaitForSomething' of the input thread.
+ *
+ * @return exit code for the child process which currently is none. The child
+ * process exits only when the main thread (parent) send a signal or a
+ * fatal error occurs.
+ */
+static int
+WaitForInput(void* argument)
+{
+ int i;
+ fd_set InputDevices;
+
+ tid_input = pthread_self();
+
+/* AdjustThreadScheduling(tid_generation); */
+
+ FD_ZERO(&InputDevices);
+
+ ErrorF("Input thread present\n");
+ while (1)
+ {
+ /* Empty the signaling pipe */
+ if (PipeRead(InputThreadReadPipe) > 0)
+ FD_SET(InputThreadReadPipe, &InputThreadFd);
+
+ XFD_COPYSET (&InputThreadFd, &InputDevices);
+ i = Select(MaxInputDevices, &InputDevices, NULL, NULL, NULL);
+#ifdef THREAD_DEBUG
+ fprintf(stderr, "thread (input generation)\n");
+#endif
+ if (i <= 0) /* An error or timeout occurred */
+ {
+ if (i < 0) /* This logic are stolen from WaitFor.c */
+ {
+ if (errno == EINVAL)
+ {
+ FatalError("WaitForInput(): select: %s\n",
+ strerror(errno));
+ }
+ else if (errno != EINTR && errno != EAGAIN)
+ {
+ ErrorF("WaitForInput(): select: %s\n",
+ strerror(errno));
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i <= MAX_DEVICES; i++)
+ if (DevFunc[i].fd != 0 &&
+ FD_ISSET(DevFunc[i].fd, &InputThreadFd) &&
+ DevFunc[i].f)
+ (*DevFunc[i].f)(DevFunc[i].closure);
+
+ }
+
+ /* Send a null byte to the main thread so it wakes select up to
+ * process the events in mieqProcessInputEvents() */
+ PipeWrite(MainThreadWritePipe);
+ }
+}
--
1.5.4.3
_______________________________________________
xorg mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/xorg