[Xcb-commit] 6 commits - configure.ac src

Jamey Sharp jamey at kemper.freedesktop.org
Sun Mar 13 10:01:17 PDT 2011


 configure.ac  |    1 
 src/xcb_in.c  |  146 ++++++++++++++++++++++------------------------------------
 src/xcb_out.c |  108 +++++++++++++++++++++++-------------------
 src/xcbint.h  |    2 
 4 files changed, 118 insertions(+), 139 deletions(-)

New commits:
commit 29ab5aeb9b1b1daf7f0659b134a4cfe9f42ca71a
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sun Mar 13 09:41:10 2011 -0700

    Include XKB in ./configure's summary output.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>

diff --git a/configure.ac b/configure.ac
index b8d5471..5f91173 100644
--- a/configure.ac
+++ b/configure.ac
@@ -259,6 +259,7 @@ echo "    Xfixes..............: ${BUILD_XFIXES}"
 echo "    Xfree86-dri.........: ${BUILD_XFREE86_DRI}"
 echo "    xinerama............: ${BUILD_XINERAMA}"
 echo "    xinput..............: ${BUILD_XINPUT}"
+echo "    xkb.................: ${BUILD_XKB}"
 echo "    xprint..............: ${BUILD_XPRINT}"
 echo "    xtest...............: ${BUILD_XTEST}"
 echo "    xv..................: ${BUILD_XV}"
commit 2edfd5c375bf980b484b7cfbfc1f4fb751621859
Merge: ed37b08... 8c3325f...
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sun Mar 13 09:18:24 2011 -0700

    Merge branch 'master' of git+ssh://git.freedesktop.org/git/xcb/libxcb
    
    Apparently I forgot to push these months ago.

commit ed37b087519ecb9e74412e4df8f8a217ab6d12a9
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat Oct 9 17:13:45 2010 -0700

    xcb_in: Use 64-bit sequence numbers internally everywhere.
    
    Widen sequence numbers on entry to those public APIs that still take
    32-bit sequence numbers.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>

diff --git a/src/xcb_in.c b/src/xcb_in.c
index a4cfb3a..a084b3f 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -75,7 +75,7 @@ typedef struct pending_reply {
 } pending_reply;
 
 typedef struct reader_list {
-    unsigned int request;
+    uint64_t request;
     pthread_cond_t *data;
     struct reader_list *next;
 } reader_list;
@@ -208,10 +208,10 @@ static int read_packet(xcb_connection_t *c)
         c->in.current_reply_tail = &cur->next;
         for(reader = c->in.readers; 
 	    reader && 
-	    XCB_SEQUENCE_COMPARE_32(reader->request, <=, c->in.request_read);
+	    XCB_SEQUENCE_COMPARE(reader->request, <=, c->in.request_read);
 	    reader = reader->next)
 	{
-            if(XCB_SEQUENCE_COMPARE_32(reader->request, ==, c->in.request_read))
+            if(reader->request == c->in.request_read)
             {
                 pthread_cond_signal(reader->data);
                 break;
@@ -301,7 +301,7 @@ static int read_block(const int fd, void *buf, const ssize_t len)
     return len;
 }
 
-static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error)
+static int poll_for_reply(xcb_connection_t *c, uint64_t request, void **reply, xcb_generic_error_t **error)
 {
     struct reply_list *head;
 
@@ -310,7 +310,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
         head = 0;
     /* We've read requests past the one we want, so if it has replies we have
      * them all and they're in the replies map. */
-    else if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
+    else if(XCB_SEQUENCE_COMPARE(request, <, c->in.request_read))
     {
         head = _xcb_map_remove(c->in.replies, request);
         if(head && head->next)
@@ -318,7 +318,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     }
     /* We're currently processing the responses to the request we want, and we
      * have a reply ready to return. So just return it without blocking. */
-    else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
+    else if(request == c->in.request_read && c->in.current_reply)
     {
         head = c->in.current_reply;
         c->in.current_reply = head->next;
@@ -327,7 +327,7 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     }
     /* We know this request can't have any more replies, and we've already
      * established it doesn't have a reply now. Don't bother blocking. */
-    else if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_completed))
+    else if(request == c->in.request_completed)
         head = 0;
     /* We may have more replies on the way for this request: block until we're
      * sure. */
@@ -356,15 +356,12 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     return 1;
 }
 
-static void *wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
+static void *wait_for_reply(xcb_connection_t *c, uint64_t request, xcb_generic_error_t **e)
 {
     void *ret = 0;
-    uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
-    if(widened_request > c->out.request)
-        widened_request -= UINT64_C(1) << 32;
 
     /* If this request has not been written yet, write it. */
-    if(c->out.return_socket || _xcb_out_flush_to(c, widened_request))
+    if(c->out.return_socket || _xcb_out_flush_to(c, request))
     {
         pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
         reader_list reader;
@@ -372,7 +369,7 @@ static void *wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_gener
 
         for(prev_reader = &c->in.readers; 
 	    *prev_reader && 
-	    XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
+	    XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request);
 	    prev_reader = &(*prev_reader)->next)
 	{
             /* empty */;
@@ -388,7 +385,7 @@ static void *wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_gener
 
         for(prev_reader = &c->in.readers;
 	    *prev_reader && 
-	    XCB_SEQUENCE_COMPARE_32((*prev_reader)->request, <=, request);
+	    XCB_SEQUENCE_COMPARE((*prev_reader)->request, <=, request);
 	    prev_reader = &(*prev_reader)->next)
 	{
             if(*prev_reader == &reader)
@@ -404,6 +401,14 @@ static void *wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_gener
     return ret;
 }
 
+static uint64_t widen(xcb_connection_t *c, unsigned int request)
+{
+    uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
+    if(widened_request > c->out.request)
+        widened_request -= UINT64_C(1) << 32;
+    return widened_request;
+}
+
 /* Public interface */
 
 void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
@@ -415,7 +420,7 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_
         return 0;
 
     pthread_mutex_lock(&c->iolock);
-    ret = wait_for_reply(c, request, e);
+    ret = wait_for_reply(c, widen(c, request), e);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -441,11 +446,10 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
         c->in.pending_replies_tail = &pend->next;
 }
 
-static void discard_reply(xcb_connection_t *c, unsigned int request)
+static void discard_reply(xcb_connection_t *c, uint64_t request)
 {
     void *reply;
     pending_reply **prev_pend;
-    uint64_t widened_request;
 
     /* Free any replies or errors that we've already read. Stop if
      * xcb_wait_for_reply would block or we've run out of replies. */
@@ -453,16 +457,16 @@ static void discard_reply(xcb_connection_t *c, unsigned int request)
         free(reply);
 
     /* If we've proven there are no more responses coming, we're done. */
-    if(XCB_SEQUENCE_COMPARE_32(request, <=, c->in.request_completed))
+    if(XCB_SEQUENCE_COMPARE(request, <=, c->in.request_completed))
         return;
 
     /* Walk the list of pending requests. Mark the first match for deletion. */
     for(prev_pend = &c->in.pending_replies; *prev_pend; prev_pend = &(*prev_pend)->next)
     {
-        if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, >, request))
+        if(XCB_SEQUENCE_COMPARE((*prev_pend)->first_request, >, request))
             break;
 
-        if(XCB_SEQUENCE_COMPARE_32((*prev_pend)->first_request, ==, request))
+        if((*prev_pend)->first_request == request)
         {
             /* Pending reply found. Mark for discard: */
             (*prev_pend)->flags |= XCB_REQUEST_DISCARD_REPLY;
@@ -471,11 +475,7 @@ static void discard_reply(xcb_connection_t *c, unsigned int request)
     }
 
     /* Pending reply not found (likely due to _unchecked request). Create one: */
-    widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
-    if(widened_request > c->out.request)
-        widened_request -= UINT64_C(1) << 32;
-
-    insert_pending_discard(c, prev_pend, widened_request);
+    insert_pending_discard(c, prev_pend, request);
 }
 
 void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
@@ -488,7 +488,7 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence)
         return;
 
     pthread_mutex_lock(&c->iolock);
-    discard_reply(c, sequence);
+    discard_reply(c, widen(c, sequence));
     pthread_mutex_unlock(&c->iolock);
 }
 
@@ -504,7 +504,7 @@ int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply,
     }
     assert(reply != 0);
     pthread_mutex_lock(&c->iolock);
-    ret = poll_for_reply(c, request, reply, error);
+    ret = poll_for_reply(c, widen(c, request), reply, error);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -542,18 +542,20 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
 
 xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
 {
+    uint64_t request;
     xcb_generic_error_t *ret = 0;
     void *reply;
     if(c->has_error)
         return 0;
     pthread_mutex_lock(&c->iolock);
-    if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected)
-       && XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
+    request = widen(c, cookie.sequence);
+    if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected)
+       && XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed))
     {
         _xcb_out_send_sync(c);
         _xcb_out_flush_to(c, c->out.request);
     }
-    reply = wait_for_reply(c, cookie.sequence, &ret);
+    reply = wait_for_reply(c, request, &ret);
     assert(!reply);
     pthread_mutex_unlock(&c->iolock);
     return ret;
diff --git a/src/xcbint.h b/src/xcbint.h
index 0c5e55e..096576c 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -54,7 +54,6 @@ enum lazy_reply_tag
 #define XCB_PAD(i) (-(i) & 3)
 
 #define XCB_SEQUENCE_COMPARE(a,op,b)	((int64_t) ((a) - (b)) op 0)
-#define XCB_SEQUENCE_COMPARE_32(a,op,b)	(((int) (a) - (int) (b)) op 0)
 
 #ifndef offsetof
 #define offsetof(type,member) ((size_t) &((type *)0)->member)
commit 6c8b539c2a2e53bf3deb0e749a941ab52b7e8834
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat Oct 9 13:19:05 2010 -0700

    xcb_discard_reply: Simplify by re-using poll_for_reply helper.
    
    If you discard a sequence number that has multiple responses already
    read, this will do more allocations than necessary. But nobody cares
    about ListFontsWithInfo.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>

diff --git a/src/xcb_in.c b/src/xcb_in.c
index 6fb9e3d..a4cfb3a 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -443,56 +443,18 @@ static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_nex
 
 static void discard_reply(xcb_connection_t *c, unsigned int request)
 {
-    pending_reply *pend = 0;
+    void *reply;
     pending_reply **prev_pend;
     uint64_t widened_request;
 
-    /* We've read requests past the one we want, so if it has replies we have
-     * them all and they're in the replies map. */
-    if(XCB_SEQUENCE_COMPARE_32(request, <, c->in.request_read))
-    {
-        struct reply_list *head;
-        head = _xcb_map_remove(c->in.replies, request);
-        while (head)
-        {
-            struct reply_list *next = head->next;
-            free(head->reply);
-            free(head);
-            head = next;
-        }
-        return;
-    }
-
-    /* We're currently processing the responses to the request we want, and we
-     * have a reply ready to return. Free it, and mark the pend to free any further
-     * replies. */
-    if(XCB_SEQUENCE_COMPARE_32(request, ==, c->in.request_read) && c->in.current_reply)
-    {
-        struct reply_list *head;
-        head = c->in.current_reply;
-        c->in.current_reply = NULL;
-        c->in.current_reply_tail = &c->in.current_reply;
-        while (head)
-        {
-            struct reply_list *next = head->next;
-            free(head->reply);
-            free(head);
-            head = next;
-        }
-
-        pend = c->in.pending_replies;
-        if(pend &&
-            !(XCB_SEQUENCE_COMPARE(pend->first_request, <=, c->in.request_read) &&
-             (pend->workaround == WORKAROUND_EXTERNAL_SOCKET_OWNER ||
-              XCB_SEQUENCE_COMPARE(c->in.request_read, <=, pend->last_request))))
-            pend = 0;
-        if(pend)
-            pend->flags |= XCB_REQUEST_DISCARD_REPLY;
-        else
-            insert_pending_discard(c, &c->in.pending_replies, c->in.request_read);
+    /* Free any replies or errors that we've already read. Stop if
+     * xcb_wait_for_reply would block or we've run out of replies. */
+    while(poll_for_reply(c, request, &reply, 0) && reply)
+        free(reply);
 
+    /* If we've proven there are no more responses coming, we're done. */
+    if(XCB_SEQUENCE_COMPARE_32(request, <=, c->in.request_completed))
         return;
-    }
 
     /* Walk the list of pending requests. Mark the first match for deletion. */
     for(prev_pend = &c->in.pending_replies; *prev_pend; prev_pend = &(*prev_pend)->next)
commit 3a74b5e7a1aab0619b7e34d90d2b8b2b1e386129
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat Oct 9 12:32:05 2010 -0700

    xcb_request_check: Hold the I/O lock while deciding to sync.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>

diff --git a/src/xcb_in.c b/src/xcb_in.c
index 57d7e01..6fb9e3d 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -356,20 +356,10 @@ static int poll_for_reply(xcb_connection_t *c, unsigned int request, void **repl
     return 1;
 }
 
-/* Public interface */
-
-void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
+static void *wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
 {
-    uint64_t widened_request;
     void *ret = 0;
-    if(e)
-        *e = 0;
-    if(c->has_error)
-        return 0;
-
-    pthread_mutex_lock(&c->iolock);
-
-    widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
+    uint64_t widened_request = (c->out.request & UINT64_C(0xffffffff00000000)) | request;
     if(widened_request > c->out.request)
         widened_request -= UINT64_C(1) << 32;
 
@@ -411,6 +401,21 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_
     }
 
     _xcb_in_wake_up_next_reader(c);
+    return ret;
+}
+
+/* Public interface */
+
+void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e)
+{
+    void *ret;
+    if(e)
+        *e = 0;
+    if(c->has_error)
+        return 0;
+
+    pthread_mutex_lock(&c->iolock);
+    ret = wait_for_reply(c, request, e);
     pthread_mutex_unlock(&c->iolock);
     return ret;
 }
@@ -575,21 +580,20 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c)
 
 xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t cookie)
 {
-    /* FIXME: this could hold the lock to avoid syncing unnecessarily, but
-     * that would require factoring the locking out of xcb_get_input_focus,
-     * xcb_get_input_focus_reply, and xcb_wait_for_reply. */
-    xcb_generic_error_t *ret;
+    xcb_generic_error_t *ret = 0;
     void *reply;
     if(c->has_error)
         return 0;
+    pthread_mutex_lock(&c->iolock);
     if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected)
        && XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
     {
-        free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret));
-        assert(!ret);
+        _xcb_out_send_sync(c);
+        _xcb_out_flush_to(c, c->out.request);
     }
-    reply = xcb_wait_for_reply(c, cookie.sequence, &ret);
+    reply = wait_for_reply(c, cookie.sequence, &ret);
     assert(!reply);
+    pthread_mutex_unlock(&c->iolock);
     return ret;
 }
 
diff --git a/src/xcb_out.c b/src/xcb_out.c
index fe71193..5eb1e42 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -343,6 +343,15 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
     return ret;
 }
 
+void _xcb_out_send_sync(xcb_connection_t *c)
+{
+    /* wait for other writing threads to get out of my way. */
+    while(c->out.writing)
+        pthread_cond_wait(&c->out.cond, &c->iolock);
+    get_socket_back(c);
+    send_sync(c);
+}
+
 int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request)
 {
     assert(XCB_SEQUENCE_COMPARE(request, <=, c->out.request));
diff --git a/src/xcbint.h b/src/xcbint.h
index 6991238..0c5e55e 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -107,6 +107,7 @@ int _xcb_out_init(_xcb_out *out);
 void _xcb_out_destroy(_xcb_out *out);
 
 int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count);
+void _xcb_out_send_sync(xcb_connection_t *c);
 int _xcb_out_flush_to(xcb_connection_t *c, uint64_t request);
 
 
commit ee1bc1d28a1bda0526db90139edc1304d2ef3d7c
Author: Jamey Sharp <jamey at minilop.net>
Date:   Sat Oct 9 04:08:18 2010 -0700

    xcb_send_request: Send all requests using a common internal send_request.
    
    This simplifies the critical section of xcb_send_request and fixes a
    couple of subtle bugs:
    
    - It's possible for xcb_send_request to need to issue two sync requests
      before it can issue the real request. Previously, we counted sequence
      numbers as if both were issued, but only one went out on the wire.
    
    - The test for whether to sync at 32-bit sequence number wrap has been
      incorrect since we switched to 64-bit sequence numbers internally.
    
    This change means that if the output queue was already full and the
    current request is bigger than the output queue, XCB will do one more
    write syscall than it did before. But syncs are rare and small requests
    are the norm, so this shouldn't be a measurable difference.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>

diff --git a/src/xcb_out.c b/src/xcb_out.c
index fbce7a0..fe71193 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -35,8 +35,17 @@
 #include "xcbint.h"
 #include "bigreq.h"
 
-static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
+static inline void send_request(xcb_connection_t *c, int isvoid, enum workarounds workaround, int flags, struct iovec *vector, int count)
 {
+    if(c->has_error)
+        return;
+
+    ++c->out.request;
+    if(!isvoid)
+        c->in.request_expected = c->out.request;
+    if(workaround != WORKAROUND_NONE || flags != 0)
+        _xcb_in_expect_reply(c, c->out.request, workaround, flags);
+
     while(count && c->out.queue_len + vector[0].iov_len <= sizeof(c->out.queue))
     {
         memcpy(c->out.queue + c->out.queue_len, vector[0].iov_base, vector[0].iov_len);
@@ -46,13 +55,29 @@ static int write_block(xcb_connection_t *c, struct iovec *vector, int count)
         ++vector, --count;
     }
     if(!count)
-        return 1;
+        return;
 
     --vector, ++count;
     vector[0].iov_base = c->out.queue;
     vector[0].iov_len = c->out.queue_len;
     c->out.queue_len = 0;
-    return _xcb_out_send(c, vector, count);
+    _xcb_out_send(c, vector, count);
+}
+
+static void send_sync(xcb_connection_t *c)
+{
+    static const union {
+        struct {
+            uint8_t major;
+            uint8_t pad;
+            uint16_t len;
+        } fields;
+        uint32_t packet;
+    } sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
+    struct iovec vector[2];
+    vector[1].iov_base = (char *) &sync_req;
+    vector[1].iov_len = sizeof(sync_req);
+    send_request(c, 0, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY, vector + 1, 1);
 }
 
 static void get_socket_back(xcb_connection_t *c)
@@ -123,16 +148,8 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
 
 unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
 {
-    static const union {
-        struct {
-            uint8_t major;
-            uint8_t pad;
-            uint16_t len;
-        } fields;
-        uint32_t packet;
-    } sync_req = { { /* GetInputFocus */ 43, 0, 1 } };
     uint64_t request;
-    uint32_t prefix[3] = { 0 };
+    uint32_t prefix[2];
     int veclen = req->count;
     enum workarounds workaround = WORKAROUND_NONE;
 
@@ -193,7 +210,15 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
         /* set the length field. */
         ((uint16_t *) vector[0].iov_base)[1] = shortlen;
         if(!shortlen)
-            prefix[2] = ++longlen;
+        {
+            prefix[0] = ((uint32_t *) vector[0].iov_base)[0];
+            prefix[1] = ++longlen;
+            vector[0].iov_base = (uint32_t *) vector[0].iov_base + 1;
+            vector[0].iov_len -= sizeof(uint32_t);
+            --vector, ++veclen;
+            vector[0].iov_base = prefix;
+            vector[0].iov_len = sizeof(prefix);
+        }
     }
     flags &= ~XCB_REQUEST_RAW;
 
@@ -212,45 +237,21 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
         pthread_cond_wait(&c->out.cond, &c->iolock);
     get_socket_back(c);
 
-    request = ++c->out.request;
     /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
-     * a reply.
-     * Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
+     * a reply. */
+    if(req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2)
+        send_sync(c);
+    /* Also send sync_req (could use NoOp) at 32-bit wrap to avoid having
      * applications see sequence 0 as that is used to indicate
      * an error in sending the request */
-    while((req->isvoid &&
-	c->out.request == c->in.request_expected + (1 << 16) - 1) ||
-       request == 0)
-    {
-        prefix[0] = sync_req.packet;
-        _xcb_in_expect_reply(c, request, WORKAROUND_NONE, XCB_REQUEST_DISCARD_REPLY);
-        c->in.request_expected = c->out.request;
-	request = ++c->out.request;
-    }
-
-    if(workaround != WORKAROUND_NONE || flags != 0)
-        _xcb_in_expect_reply(c, request, workaround, flags);
-    if(!req->isvoid)
-        c->in.request_expected = c->out.request;
-
-    if(prefix[0] || prefix[2])
-    {
-        --vector, ++veclen;
-        if(prefix[2])
-        {
-            prefix[1] = ((uint32_t *) vector[1].iov_base)[0];
-            vector[1].iov_base = (uint32_t *) vector[1].iov_base + 1;
-            vector[1].iov_len -= sizeof(uint32_t);
-        }
-        vector[0].iov_len = sizeof(uint32_t) * ((prefix[0] ? 1 : 0) + (prefix[2] ? 2 : 0));
-        vector[0].iov_base = prefix + !prefix[0];
-    }
-
-    if(!write_block(c, vector, veclen))
-    {
-        _xcb_conn_shutdown(c);
-        request = 0;
-    }
+    if((unsigned int) (c->out.request + 1) == 0)
+        send_sync(c);
+
+    /* The above send_sync calls could drop the I/O lock, but this
+     * thread will still exclude any other thread that tries to write,
+     * so the sequence number postconditions still hold. */
+    send_request(c, req->isvoid, workaround, flags, vector, veclen);
+    request = c->has_error ? 0 : c->out.request;
     pthread_mutex_unlock(&c->iolock);
     return request;
 }


More information about the xcb-commit mailing list