Updated to use the Thread affinity patch that we tried to upstream
authorJørgen Lind <jorgen.lind@nokia.com>
Mon, 12 Mar 2012 13:58:51 +0000 (14:58 +0100)
committerLaszlo Agocs <laszlo.p.agocs@nokia.com>
Mon, 12 Mar 2012 17:56:20 +0000 (18:56 +0100)
Change-Id: I11138634f4c3d5e673d764cdcb36e7b503aafca0
Reviewed-by: Laszlo Agocs <laszlo.p.agocs@nokia.com>
patches/0001-Add-thread-affinity-to-wayland-clients.patch [new file with mode: 0644]
patches/0001-Removed-superfluous-call-to-wl_copy_connection.patch [deleted file]
patches/0002-Fix-for-issues-with-threaded-GL-drivers.patch [deleted file]
src/plugins/platforms/wayland/qwaylanddisplay.cpp

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 (file)
index 0000000..3838a22
--- /dev/null
@@ -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 (file)
index 4a9ebf4..0000000
+++ /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 (file)
index 902d7f4..0000000
+++ /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
-
index 73b46c4..fb3e947 100644 (file)
@@ -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()));