summaryrefslogtreecommitdiffstats
path: root/meta/recipes-graphics/xorg-lib/libxcb/ensure-xcb-owns-socket-and-no-other-threads-are-writ.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-graphics/xorg-lib/libxcb/ensure-xcb-owns-socket-and-no-other-threads-are-writ.patch')
-rw-r--r--meta/recipes-graphics/xorg-lib/libxcb/ensure-xcb-owns-socket-and-no-other-threads-are-writ.patch121
1 files changed, 121 insertions, 0 deletions
diff --git a/meta/recipes-graphics/xorg-lib/libxcb/ensure-xcb-owns-socket-and-no-other-threads-are-writ.patch b/meta/recipes-graphics/xorg-lib/libxcb/ensure-xcb-owns-socket-and-no-other-threads-are-writ.patch
new file mode 100644
index 0000000000..14cefa3f29
--- /dev/null
+++ b/meta/recipes-graphics/xorg-lib/libxcb/ensure-xcb-owns-socket-and-no-other-threads-are-writ.patch
@@ -0,0 +1,121 @@
1From be0fe56c3bcad5124dcc6c47a2fad01acd16f71a Mon Sep 17 00:00:00 2001
2From: Keith Packard <keithp@keithp.com>
3Date: Mon, 23 Dec 2013 21:15:20 -0800
4Subject: [PATCH] Ensure xcb owns socket and no other threads are writing
5 before send_request
6
7send_request may only write to out.queue if no other thread is busy
8writing to the network (as that thread may be writing from out.queue).
9
10send_request may only allocate request sequence numbers if XCB owns
11the socket.
12
13Therefore, send_request must make sure that both conditions are true
14when it holds iolock, which can only be done by looping until both
15conditions are true without having dropped the lock waiting for the
16second condition.
17
18We choose to get the socket back from Xlib first as get_socket_back
19has a complicated test and checking for other threads writing is a
20simple in-lined check.
21
22This also changes the sequence number checks (64k requests with no
23reply, 4M request wrapping) to ensure that both conditions are true
24before queueing the request.
25
26Signed-off-by: Keith Packard <keithp@keithp.com>
27Reviewed-by: Uli Schlachter <psychon@znc.in>
28---
29 src/xcb_out.c | 57 ++++++++++++++++++++++++++++++++++++++++-----------------
30 1 file changed, 40 insertions(+), 17 deletions(-)
31
32diff --git a/src/xcb_out.c b/src/xcb_out.c
33index 18bb5f9..dc42954 100644
34--- a/src/xcb_out.c
35+++ b/src/xcb_out.c
36@@ -103,6 +103,33 @@ static void get_socket_back(xcb_connection_t *c)
37 _xcb_in_replies_done(c);
38 }
39
40+static void prepare_socket_request(xcb_connection_t *c)
41+{
42+ /* We're about to append data to out.queue, so we need to
43+ * atomically test for an external socket owner *and* some other
44+ * thread currently writing.
45+ *
46+ * If we have an external socket owner, we have to get the socket back
47+ * before we can use it again.
48+ *
49+ * If some other thread is writing to the socket, we assume it's
50+ * writing from out.queue, and so we can't stick data there.
51+ *
52+ * We satisfy this condition by first calling get_socket_back
53+ * (which may drop the lock, but will return when XCB owns the
54+ * socket again) and then checking for another writing thread and
55+ * escaping the loop if we're ready to go.
56+ */
57+ for (;;) {
58+ if(c->has_error)
59+ return;
60+ get_socket_back(c);
61+ if (!c->out.writing)
62+ break;
63+ pthread_cond_wait(&c->out.cond, &c->iolock);
64+ }
65+}
66+
67 /* Public interface */
68
69 void xcb_prefetch_maximum_request_length(xcb_connection_t *c)
70@@ -236,24 +263,23 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
71
72 /* get a sequence number and arrange for delivery. */
73 pthread_mutex_lock(&c->iolock);
74- /* wait for other writing threads to get out of my way. */
75- while(c->out.writing)
76- pthread_cond_wait(&c->out.cond, &c->iolock);
77- get_socket_back(c);
78+
79+ prepare_socket_request(c);
80
81 /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
82- * a reply. */
83- if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2)
84- send_sync(c);
85- /* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
86+ * a reply.
87+ * Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
88 * applications see sequence 0 as that is used to indicate
89- * an error in sending the request */
90- if((unsigned int) (c->out.request + 1) == 0)
91+ * an error in sending the request
92+ */
93+
94+ while ((req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) ||
95+ (unsigned int) (c->out.request + 1) == 0)
96+ {
97 send_sync(c);
98+ prepare_socket_request(c);
99+ }
100
101- /* The above send_sync calls could drop the I/O lock, but this
102- * thread will still exclude any other thread that tries to write,
103- * so the sequence number postconditions still hold. */
104 send_request(c, req->isvoid, workaround, flags, vector, veclen);
105 request = c->has_error ? 0 : c->out.request;
106 pthread_mutex_unlock(&c->iolock);
107@@ -373,10 +399,7 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
108
109 void _xcb_out_send_sync(xcb_connection_t *c)
110 {
111- /* wait for other writing threads to get out of my way. */
112- while(c->out.writing)
113- pthread_cond_wait(&c->out.cond, &c->iolock);
114- get_socket_back(c);
115+ prepare_socket_request(c);
116 send_sync(c);
117 }
118
119--
1201.9.1
121