[Xcb-commit] 2 commits - src

Jamey Sharp jamey at kemper.freedesktop.org
Sun Oct 28 13:28:29 PDT 2007


 src/xcb_conn.c |   33 +++++++++++++++++++++++++++++++--
 src/xcb_out.c  |    4 ++--
 src/xcbint.h   |    1 +
 3 files changed, 34 insertions(+), 4 deletions(-)

New commits:
commit a29fbc2645fabb96d02c382ffef499b48fb1514a
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sun Oct 28 13:28:18 2007 -0700

    Don't hold the xlib-xcb lock while sleeping: that allows deadlock.
    
    With this patch, `ico -threads 2` runs without deadlock.
    
    Many thanks to Christoph Pfister <christophpfister at gmail.com> for
    pointing out the problem, providing detailed analyses, explaining it to
    me repeatedly until I understood what was going on, and proposing and
    reviewing possible solutions.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Acked-by: Christoph Pfister <christophpfister at gmail.com>

diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 9a58bff..e7856c3 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -290,12 +290,25 @@ void _xcb_unlock_io(xcb_connection_t *c)
 
 void _xcb_wait_io(xcb_connection_t *c, pthread_cond_t *cond)
 {
+    int xlib_locked = c->xlib.lock;
+    if(xlib_locked)
+    {
+        c->xlib.lock = 0;
+        pthread_cond_broadcast(&c->xlib.cond);
+    }
     pthread_cond_wait(cond, &c->iolock);
+    if(xlib_locked)
+    {
+        while(c->xlib.lock)
+            pthread_cond_wait(&c->xlib.cond, &c->iolock);
+        c->xlib.lock = 1;
+        c->xlib.thread = pthread_self();
+    }
 }
 
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
 {
-    int ret;
+    int ret, xlib_locked;
     fd_set rfds, wfds;
 
     /* If the thing I should be doing is already being done, wait for it. */
@@ -316,6 +329,12 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
         ++c->out.writing;
     }
 
+    xlib_locked = c->xlib.lock;
+    if(xlib_locked)
+    {
+        c->xlib.lock = 0;
+        pthread_cond_broadcast(&c->xlib.cond);
+    }
     _xcb_unlock_io(c);
     do {
 	ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
@@ -326,6 +345,11 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
 	ret = 0;
     }
     _xcb_lock_io(c);
+    if(xlib_locked)
+    {
+        c->xlib.lock = 1;
+        c->xlib.thread = pthread_self();
+    }
 
     if(ret)
     {
commit f6b75d6090dc40918196d2b902e9616d0199af42
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sun Oct 28 11:56:08 2007 -0700

    Factor pthread_cond_wait(iolock) to _xcb_wait_io.
    
    This parallels the _xcb_lock_io and _xcb_unlock_io factoring.

diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 827a12b..9a58bff 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -288,6 +288,11 @@ void _xcb_unlock_io(xcb_connection_t *c)
     pthread_mutex_unlock(&c->iolock);
 }
 
+void _xcb_wait_io(xcb_connection_t *c, pthread_cond_t *cond)
+{
+    pthread_cond_wait(cond, &c->iolock);
+}
+
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count)
 {
     int ret;
@@ -296,7 +301,7 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
     /* If the thing I should be doing is already being done, wait for it. */
     if(count ? c->out.writing : c->in.reading)
     {
-        pthread_cond_wait(cond, &c->iolock);
+        _xcb_wait_io(c, cond);
         return 1;
     }
 
diff --git a/src/xcb_out.c b/src/xcb_out.c
index caf8ef5..60226e5 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -190,7 +190,7 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
     _xcb_lock_io(c);
     /* wait for other writing threads to get out of my way. */
     while(c->out.writing)
-        pthread_cond_wait(&c->out.cond, &c->iolock);
+        _xcb_wait_io(c, &c->out.cond);
 
     request = ++c->out.request;
     /* send GetInputFocus (sync) when 64k-2 requests have been sent without
@@ -297,7 +297,7 @@ int _xcb_out_flush_to(xcb_connection_t *c, unsigned int request)
         return _xcb_out_send(c, &vec_ptr, &count);
     }
     while(c->out.writing)
-        pthread_cond_wait(&c->out.cond, &c->iolock);
+        _xcb_wait_io(c, &c->out.cond);
     assert(XCB_SEQUENCE_COMPARE(c->out.request_written, >=, request));
     return 1;
 }
diff --git a/src/xcbint.h b/src/xcbint.h
index ab692ee..ab0264f 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -183,6 +183,7 @@ struct xcb_connection_t {
 };
 
 void _xcb_conn_shutdown(xcb_connection_t *c);
+void _xcb_wait_io(xcb_connection_t *c, pthread_cond_t *cond);
 int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);
 
 


More information about the xcb-commit mailing list