summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@nokia.com>2012-03-12 14:58:51 +0100
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>2012-03-12 18:56:20 +0100
commite2d22eebca3b2dc11279e6e6fd46aa3d60db8c6b (patch)
treea5bacd5ddbc6a5b94ce166d07dc670b47e3e6cd5
parenta2401ec66dfa18a8788079211fc422db4298e8b3 (diff)
Updated to use the Thread affinity patch that we tried to upstream
Change-Id: I11138634f4c3d5e673d764cdcb36e7b503aafca0 Reviewed-by: Laszlo Agocs <laszlo.p.agocs@nokia.com>
-rw-r--r--patches/0001-Add-thread-affinity-to-wayland-clients.patch253
-rw-r--r--patches/0001-Removed-superfluous-call-to-wl_copy_connection.patch31
-rw-r--r--patches/0002-Fix-for-issues-with-threaded-GL-drivers.patch171
-rw-r--r--src/plugins/platforms/wayland/qwaylanddisplay.cpp2
4 files changed, 254 insertions, 203 deletions
diff --git a/patches/0001-Add-thread-affinity-to-wayland-clients.patch b/patches/0001-Add-thread-affinity-to-wayland-clients.patch
new file mode 100644
index 000000000..3838a22b7
--- /dev/null
+++ b/patches/0001-Add-thread-affinity-to-wayland-clients.patch
@@ -0,0 +1,253 @@
+From 24b8dccb2f48bc8595d40288106d51d3f4605544 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com>
+Date: Mon, 5 Mar 2012 12:44:37 +0100
+Subject: [PATCH 1/2] Add thread affinity to wayland clients
+
+This makes it possible to marshal requests from more than 1 thread in
+wayland clients. However, its not possible to run wl_display_iterate
+from other threads than the thread that made the wl_display.
+---
+ src/Makefile.am | 2 +
+ src/wayland-client.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++--
+ src/wayland-client.h | 6 +++
+ 3 files changed, 112 insertions(+), 5 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index f356b54..9aab9de 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -24,6 +24,8 @@ libwayland_server_la_SOURCES = \
+ event-loop.c
+
+ libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt
++libwayland_client_la_LDFLAGS = -pthread
++libwayland_client_la_CFLAGS = -pthread
+ libwayland_client_la_SOURCES = \
+ wayland-protocol.c \
+ wayland-client.c
+diff --git a/src/wayland-client.c b/src/wayland-client.c
+index 498a429..9eb4b25 100644
+--- a/src/wayland-client.c
++++ b/src/wayland-client.c
+@@ -34,6 +34,7 @@
+ #include <assert.h>
+ #include <fcntl.h>
+ #include <sys/poll.h>
++#include <sys/eventfd.h>
+
+ #include "wayland-util.h"
+ #include "wayland-client.h"
+@@ -62,6 +63,9 @@ struct wl_display {
+ struct wl_proxy proxy;
+ struct wl_connection *connection;
+ int fd;
++ int write_notification_event_fd;
++ pthread_t thread_id;
++ pthread_mutex_t marshalling_mutex;
+ uint32_t mask;
+ struct wl_map objects;
+ struct wl_list global_listener_list;
+@@ -191,7 +195,11 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
+ {
+ struct wl_closure *closure;
+ va_list ap;
++ int write_notification_event_fd;
++ uint64_t write_notification_value;
++ ssize_t success;
+
++ pthread_mutex_lock(&proxy->display->marshalling_mutex);
+ va_start(ap, opcode);
+ closure = wl_connection_vmarshal(proxy->display->connection,
+ &proxy->object, opcode, ap,
+@@ -212,6 +220,18 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
+ wl_closure_print(closure, &proxy->object, true);
+
+ wl_closure_destroy(closure);
++
++ write_notification_event_fd = proxy->display->write_notification_event_fd;
++ write_notification_value = 1;
++ success = write(write_notification_event_fd,&write_notification_value,8);
++ if (success < 0) {
++ fprintf(stderr,
++ "Error writing to eventfd %d: %s\n",
++ write_notification_event_fd,
++ strerror(errno));
++ }
++
++ pthread_mutex_unlock(&proxy->display->marshalling_mutex);
+ }
+
+ /* Can't do this, there may be more than one instance of an
+@@ -347,6 +367,7 @@ wl_display_connect(const char *name)
+ const char *debug;
+ char *connection, *end;
+ int flags;
++ int success;
+
+ debug = getenv("WAYLAND_DEBUG");
+ if (debug)
+@@ -396,6 +417,21 @@ wl_display_connect(const char *name)
+ return NULL;
+ }
+
++ display->write_notification_event_fd = eventfd(0, EFD_CLOEXEC);
++ if (display->write_notification_event_fd < 0) {
++ fprintf(stderr, "Failed to create eventfd\n");
++ }
++
++ display->thread_id = pthread_self();
++ pthread_mutexattr_t mutex_attr;
++ success = pthread_mutexattr_init(&mutex_attr);
++ success += pthread_mutexattr_settype(&mutex_attr,PTHREAD_MUTEX_RECURSIVE);
++ success += pthread_mutex_init(&display->marshalling_mutex, &mutex_attr);
++ success += pthread_mutexattr_destroy(&mutex_attr);
++
++ if (success)
++ fprintf(stderr, "Threading setup was unsuccessfull\n");
++
+ return display;
+ }
+
+@@ -432,6 +468,18 @@ wl_display_get_fd(struct wl_display *display,
+ return display->fd;
+ }
+
++WL_EXPORT int
++wl_display_get_write_notification_fd(struct wl_display *display)
++{
++ return display->write_notification_event_fd;
++}
++
++WL_EXPORT pthread_t
++wl_display_thread(struct wl_display *display)
++{
++ return display->thread_id;
++}
++
+ static void
+ sync_callback(void *data, struct wl_callback *callback, uint32_t time)
+ {
+@@ -445,18 +493,46 @@ static const struct wl_callback_listener sync_listener = {
+ sync_callback
+ };
+
++static void
++threaded_sync_callback(void *data, struct wl_callback *callback, uint32_t time)
++{
++ fprintf(stderr, "threaded_sync_callback\n");
++ pthread_cond_t *wait_condition = data;
++
++ pthread_cond_broadcast(wait_condition);
++ wl_callback_destroy(callback);
++}
++
++static const struct wl_callback_listener threaded_sync_listener = {
++ threaded_sync_callback
++};
++
+ WL_EXPORT void
+ wl_display_roundtrip(struct wl_display *display)
+ {
+ struct wl_callback *callback;
+ int done;
++ pthread_cond_t wait_cond;
++ pthread_mutex_t wait_mutex;
+
+- done = 0;
+ callback = wl_display_sync(display);
+- wl_callback_add_listener(callback, &sync_listener, &done);
+- wl_display_flush(display);
+- while (!done)
+- wl_display_iterate(display, WL_DISPLAY_READABLE);
++
++ if (wl_display_thread(display) == pthread_self()) {
++ done = 0;
++ wl_callback_add_listener(callback, &sync_listener, &done);
++ wl_display_flush(display);
++ while (!done)
++ wl_display_iterate(display, WL_DISPLAY_READABLE);
++ } else {
++ pthread_mutex_init(&wait_mutex,NULL);
++ pthread_cond_init(&wait_cond, NULL);
++ pthread_mutex_lock(&wait_mutex);
++
++ wl_callback_add_listener(callback, &threaded_sync_listener, &wait_cond);
++ pthread_cond_wait(&wait_cond,&wait_mutex);
++ pthread_cond_destroy(&wait_cond);
++ pthread_mutex_destroy(&wait_mutex);
++ }
+ }
+
+ static void
+@@ -500,7 +576,11 @@ WL_EXPORT void
+ wl_display_iterate(struct wl_display *display, uint32_t mask)
+ {
+ uint32_t p[2], object, opcode, size;
++ uint64_t write_fd;
+ int len;
++ ssize_t success;
++
++ pthread_mutex_lock(&display->marshalling_mutex);
+
+ mask &= display->mask;
+ if (mask == 0) {
+@@ -509,6 +589,23 @@ wl_display_iterate(struct wl_display *display, uint32_t mask)
+ return;
+ }
+
++ if (mask & WL_DISPLAY_WRITABLE) {
++ if (pthread_self() != display->thread_id) {
++ fprintf(stderr,
++ "wl_display_iterate called with WL_DISPLAY_WRITABLE"
++ "from another thread than the thead that created "
++ "wl_display. This will result in events being dispatched"
++ "in other threads\n");
++ }
++ success = read(display->write_notification_event_fd, &write_fd, 8);
++ if (success < 0) {
++ fprintf(stderr,
++ "wl_display_iterate eventfd %d error at read: %s\n",
++ display->write_notification_event_fd,
++ strerror(errno));
++ }
++ }
++
+ len = wl_connection_data(display->connection, mask);
+
+ while (len > 0) {
+@@ -526,6 +623,8 @@ wl_display_iterate(struct wl_display *display, uint32_t mask)
+ len -= size;
+ }
+
++ pthread_mutex_unlock(&display->marshalling_mutex);
++
+ if (len < 0) {
+ fprintf(stderr, "read error: %m\n");
+ exit(EXIT_FAILURE);
+diff --git a/src/wayland-client.h b/src/wayland-client.h
+index b04a7ef..a680cab 100644
+--- a/src/wayland-client.h
++++ b/src/wayland-client.h
+@@ -25,6 +25,9 @@
+
+ #include "wayland-util.h"
+
++#include <pthread.h>
++#define WAYLAND_CLIENT_THREAD_AFFINITY
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+@@ -94,6 +97,9 @@ uint32_t
+ wl_display_get_global(struct wl_display *display,
+ const char *interface, uint32_t version);
+
++int wl_display_get_write_notification_fd(struct wl_display *display);
++pthread_t wl_display_thread(struct wl_display *display);
++
+ #ifdef __cplusplus
+ }
+ #endif
+--
+1.7.5.4
+
diff --git a/patches/0001-Removed-superfluous-call-to-wl_copy_connection.patch b/patches/0001-Removed-superfluous-call-to-wl_copy_connection.patch
deleted file mode 100644
index 4a9ebf4cf..000000000
--- a/patches/0001-Removed-superfluous-call-to-wl_copy_connection.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 42a5ccf0f6e42c1487fef1d5422939bc6836044d Mon Sep 17 00:00:00 2001
-From: Andy Nichols <andy.nichols@nokia.com>
-Date: Thu, 24 Nov 2011 10:19:18 +0100
-Subject: [PATCH 1/2] Removed superfluous call to wl_copy_connection
-
-The only purpose those code seems to serve is to introduce a buffer
-overflow when events contain more than 128 bytes of data.
----
- src/wayland-client.c | 2 --
- 1 files changed, 0 insertions(+), 2 deletions(-)
-
-diff --git a/src/wayland-client.c b/src/wayland-client.c
-index 939c17d..fd5a8fa 100644
---- a/src/wayland-client.c
-+++ b/src/wayland-client.c
-@@ -445,12 +445,10 @@ static void
- handle_event(struct wl_display *display,
- uint32_t id, uint32_t opcode, uint32_t size)
- {
-- uint32_t p[32];
- struct wl_proxy *proxy;
- struct wl_closure *closure;
- const struct wl_message *message;
-
-- wl_connection_copy(display->connection, p, size);
- proxy = wl_map_lookup(&display->objects, id);
-
- if (proxy == WL_ZOMBIE_OBJECT) {
---
-1.7.8.rc2
-
diff --git a/patches/0002-Fix-for-issues-with-threaded-GL-drivers.patch b/patches/0002-Fix-for-issues-with-threaded-GL-drivers.patch
deleted file mode 100644
index 902d7f4bf..000000000
--- a/patches/0002-Fix-for-issues-with-threaded-GL-drivers.patch
+++ /dev/null
@@ -1,171 +0,0 @@
-From d0fb8027cea418531f25be8750c8da1d7fcfe5e2 Mon Sep 17 00:00:00 2001
-From: Paul Olav Tvete <paul.tvete@nokia.com>
-Date: Wed, 16 Nov 2011 16:55:33 +0100
-Subject: [PATCH 2/2] Fix for issues with threaded GL drivers
-
-Two problems arise with asynchronous GL drivers that allow issuing
-GL commands for the next frame before the GPU is done with the current frame:
-
-1. The client code never knows when it is necessary to call wl_display_iterate.
-
-Solution: Write to a pipe when there is data to be sent. The client can then select() on
-the pipe's fd.
-
-2. The GL library might call wl_surface_attach/wl_surface_damage while the main thread is
-doing wl_display_iterate.
-
-Solution: Protect wl_display_iterate and wl_proxy_marshal with a mutex
----
- src/wayland-client.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++-
- src/wayland-client.h | 9 +++++++
- 2 files changed, 69 insertions(+), 1 deletions(-)
-
-diff --git a/src/wayland-client.c b/src/wayland-client.c
-index fd5a8fa..979dadf 100644
---- a/src/wayland-client.c
-+++ b/src/wayland-client.c
-@@ -34,6 +34,7 @@
- #include <assert.h>
- #include <fcntl.h>
- #include <sys/poll.h>
-+#include <pthread.h>
-
- #include "wayland-util.h"
- #include "wayland-client.h"
-@@ -62,6 +63,9 @@ struct wl_display {
- struct wl_proxy proxy;
- struct wl_connection *connection;
- int fd;
-+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+ int pipefd[2];
-+#endif
- uint32_t mask;
- struct wl_map objects;
- struct wl_list global_listener_list;
-@@ -186,9 +190,42 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
- return 0;
- }
-
-+static void
-+display_signal_flush_needed(struct wl_display *display)
-+{
-+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+ const char data = '!';
-+ if (display->pipefd[1])
-+ write(display->pipefd[1], &data, 1);
-+#endif
-+}
-+
-+
-+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
-+static pthread_t foo_locker;
-+
-+#define FOO_MUTEX_LOCK \
-+ int foo_needLock = (pthread_self() != foo_locker); \
-+ if (foo_needLock) { \
-+ pthread_mutex_lock(&foo_mutex); \
-+ foo_locker = pthread_self(); \
-+ }
-+
-+#define FOO_MUTEX_UNLOCK \
-+ if (foo_needLock) { \
-+ foo_locker = 0; \
-+ pthread_mutex_unlock(&foo_mutex); \
-+ }
-+#else
-+#define FOO_MUTEX_LOCK
-+#define FOO_MUTEX_UNLOCK
-+#endif
-+
- WL_EXPORT void
- wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
- {
-+ FOO_MUTEX_LOCK;
- struct wl_closure *closure;
- va_list ap;
-
-@@ -204,6 +241,8 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
- wl_closure_print(closure, &proxy->object, true);
-
- wl_closure_destroy(closure);
-+ display_signal_flush_needed(proxy->display);
-+ FOO_MUTEX_UNLOCK;
- }
-
- /* Can't do this, there may be more than one instance of an
-@@ -414,6 +453,17 @@ wl_display_get_fd(struct wl_display *display,
- return display->fd;
- }
-
-+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+WL_EXPORT int
-+wl_display_get_write_notification_fd(struct wl_display *display)
-+{
-+ if (!display->pipefd[0]) {
-+ pipe2(display->pipefd, O_CLOEXEC | O_NONBLOCK);
-+ }
-+ return display->pipefd[0];
-+}
-+#endif
-+
- static void
- sync_callback(void *data, struct wl_callback *callback, uint32_t time)
- {
-@@ -482,16 +532,24 @@ handle_event(struct wl_display *display,
- WL_EXPORT void
- wl_display_iterate(struct wl_display *display, uint32_t mask)
- {
-+ FOO_MUTEX_LOCK;
- uint32_t p[2], object, opcode, size;
- int len;
--
-+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+ if ((mask & WL_DISPLAY_WRITABLE) && display->pipefd[0]) {
-+ char buf[80];
-+ int n = read(display->pipefd[0], buf, 80);
-+ }
-+#endif
- mask &= display->mask;
- if (mask == 0) {
- fprintf(stderr,
- "wl_display_iterate called with unsolicited flags");
-+ FOO_MUTEX_UNLOCK;
- return;
- }
-
-+
- len = wl_connection_data(display->connection, mask);
-
- while (len > 0) {
-@@ -513,6 +571,7 @@ wl_display_iterate(struct wl_display *display, uint32_t mask)
- fprintf(stderr, "read error: %m\n");
- exit(EXIT_FAILURE);
- }
-+ FOO_MUTEX_UNLOCK;
- }
-
- WL_EXPORT void
-diff --git a/src/wayland-client.h b/src/wayland-client.h
-index efeee4a..050f7f2 100644
---- a/src/wayland-client.h
-+++ b/src/wayland-client.h
-@@ -94,6 +94,15 @@ uint32_t
- wl_display_get_global(struct wl_display *display,
- const char *interface, uint32_t version);
-
-+
-+
-+#define QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+
-+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
-+int wl_display_get_write_notification_fd(struct wl_display *display);
-+#endif
-+
-+
- #ifdef __cplusplus
- }
- #endif
---
-1.7.8.rc2
-
diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
index 73b46c459..fb3e947ce 100644
--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp
+++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp
@@ -132,7 +132,7 @@ QWaylandDisplay::QWaylandDisplay(void)
mFd = wl_display_get_fd(mDisplay, dummyUpdate, 0);
-#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+#ifdef WAYLAND_CLIENT_THREAD_AFFINITY
mWritableNotificationFd = wl_display_get_write_notification_fd(mDisplay);
QSocketNotifier *wn = new QSocketNotifier(mWritableNotificationFd, QSocketNotifier::Read, this);
connect(wn, SIGNAL(activated(int)), this, SLOT(flushRequests()));