[PATCH libX11] fix for Xlib 32-bit request number issues

Christian Linhart chris at demorecorder.com
Sat Mar 21 07:32:16 PDT 2015


I have made an alternative fix for the Xlib 32-bit
request number issue, that is described in the following bugreport.
https://bugs.freedesktop.org/show_bug.cgi?id=71338

The approach of this fix is to offer a 64-bit sequence number interface
in XCB for the relevant xcb-functions, and then adapt Xlib accordingly.

For the changes in XCB see my post on the XCB-mailinglist.
The changes in XCB are rather straightforward and easily
ABI and API compatible.

Changing Xlib was more challenging because several member
variables in structs that are exposed in the API and ABI
contain sequence numbers.

Therefore, maintaining ABI compliance requires some tricks.

For the two member variables "request" and "last_request_read"
of the Display-structure, the solution is as follows:
* define extra member variables at the end of struct _XDisplay
  these variables contain the upper 32 bit of the sequence number.
* define macros for read and write access to these member variables.

For all other exposed sequence variables, we use a new widen-macro
called X_DPY_WIDEN_UNSIGNED_LONG_SEQ.

This patch attempts to make all necessary adaptations in libX11.
Some more adaptations may be needed in extension libraries.
---
 include/X11/Xlib.h    |  11 ++++-
 include/X11/Xlibint.h | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ClDisplay.c       |   2 +-
 src/Font.c            |   8 ++--
 src/GetAtomNm.c       |  13 +++---
 src/GetWAttrs.c       |  13 +++---
 src/IntAtom.c         |  14 ++++---
 src/OpenDis.c         |   4 +-
 src/PutImage.c        |   2 +-
 src/ReconfWM.c        |   6 ++-
 src/XlibAsync.c       |  19 ++++++---
 src/XlibInt.c         |  31 ++++++++------
 src/Xxcbint.h         |   4 +-
 src/xcb_io.c          |  89 ++++++++++++++++++++-------------------
 src/xcms/cmsCmap.c    |   4 +-
 15 files changed, 237 insertions(+), 97 deletions(-)

diff --git a/include/X11/Xlib.h b/include/X11/Xlib.h
index 2bffa76..a553e33 100644
--- a/include/X11/Xlib.h
+++ b/include/X11/Xlib.h
@@ -37,9 +37,8 @@ in this Software without prior written authorization from The Open Group.
 
 #include <sys/types.h>
 
-#if defined(__SCO__) || defined(__UNIXWARE__)
 #include <stdint.h>
-#endif
+#include <limits.h>
 
 #include <X11/X.h>
 
@@ -58,6 +57,14 @@ typedef unsigned long wchar_t;
 #endif
 #endif
 
+/* determine the size of unsigned long */
+#if ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL
+#define X_UNSIGNED_LONG_IS_64BIT
+#elif ULONG_MAX == 0xFFFFFFFFUL
+#define X_UNSIGNED_LONG_IS_32BIT
+#else
+#error unsupported size of unsigned long
+#endif
 
 extern int
 _Xmblen(
diff --git a/include/X11/Xlibint.h b/include/X11/Xlibint.h
index 4431559..f374217 100644
--- a/include/X11/Xlibint.h
+++ b/include/X11/Xlibint.h
@@ -38,6 +38,7 @@ from The Open Group.
  *	Warning, there be dragons here....
  */
 
+#include <stdint.h>
 #include <X11/Xlib.h>
 #include <X11/Xproto.h>		/* to declare xEvent */
 #include <X11/XlibConf.h>	/* for configured options like XTHREADS */
@@ -205,10 +206,120 @@ struct _XDisplay
 		XGenericEventCookie *	/* in */,
 		XGenericEventCookie *   /* out*/);
 	void *cookiejar;  /* cookie events returned but not claimed */
+#ifdef X_UNSIGNED_LONG_IS_32BIT
+	unsigned long last_request_read_upper32bit;
+	unsigned long request_upper32bit;
+#endif
 };
 
 #define XAllocIDs(dpy,ids,n) (*(dpy)->idlist_alloc)(dpy,ids,n)
 
+/* access "last_request_read" and "request" with 64bit
+   warning: the value argument of the SET-macros must not
+   have any side-effects because it may get called twice.
+*/
+#ifdef X_UNSIGNED_LONG_IS_32BIT
+/* accessors for 32-bit unsigned long */
+
+#define X_DPY_GET_REQUEST(dpy) \
+    ( \
+        ((uint64_t)(((struct _XDisplay*)dpy)->request)) \
+	+ (((uint64_t)(((struct _XDisplay*)dpy)->request_upper32bit)) << 32) \
+    )
+
+#define X_DPY_SET_REQUEST(dpy, value) \
+    ( \
+        (((struct _XDisplay*)dpy)->request = \
+            (value) & 0xFFFFFFFFUL), \
+        (((struct _XDisplay*)dpy)->request_upper32bit = \
+            ((uint64_t)(value)) >> 32), \
+	(void)0 /* don't use the result */ \
+    )
+
+#define X_DPY_GET_LAST_REQUEST_READ(dpy) \
+    ( \
+        ((uint64_t)(((struct _XDisplay*)dpy)->last_request_read)) \
+        + ( \
+            ((uint64_t)( \
+                ((struct _XDisplay*)dpy)->last_request_read_upper32bit \
+            )) << 32 \
+        ) \
+    )
+
+#define X_DPY_SET_LAST_REQUEST_READ(dpy, value) \
+    ( \
+        (((struct _XDisplay*)dpy)->last_request_read = \
+            (value) & 0xFFFFFFFFUL), \
+        (((struct _XDisplay*)dpy)->last_request_read_upper32bit = \
+            ((uint64_t)(value)) >> 32), \
+	(void)0 /* don't use the result */ \
+    )
+
+/* widen a 32-bit sequence number to a 64 sequence number.
+   This macro makes the following assumptions:
+   - ulseq refers to a sequence that has already been sent
+   - ulseq means the most recent possible sequence number
+     with these lower 32 bits.
+
+   The following optimization is used:
+   The comparision result is taken a 0 or 1 to avoid a branch.
+*/
+#define X_DPY_WIDEN_UNSIGNED_LONG_SEQ(dpy, ulseq) \
+    ( \
+        ((uint64_t)ulseq) \
+        + \
+        (( \
+            ((uint64_t)(((struct _XDisplay*)dpy)->request_upper32bit)) \
+            - (uint64_t)( \
+                (ulseq) > (((struct _XDisplay*)dpy)->request) \
+	    ) \
+        ) << 32) \
+    )
+
+#define X_DPY_REQUEST_INCREMENT(dpy) \
+    ( \
+        ((struct _XDisplay*)dpy)->request++, \
+        ( \
+            (((struct _XDisplay*)dpy)->request == 0) ? ( \
+                ((struct _XDisplay*)dpy)->request_upper32bit++ \
+	    ) : 0 \
+        ), \
+	(void)0 /* don't use the result */ \
+    )
+
+
+#define X_DPY_REQUEST_DECREMENT(dpy) \
+    ( \
+	( \
+            (((struct _XDisplay*)dpy)->request == 0) ? (\
+                ((struct _XDisplay*)dpy)->request--, /* wrap */ \
+                ((struct _XDisplay*)dpy)->request_upper32bit-- \
+            ) : ( \
+                ((struct _XDisplay*)dpy)->request-- \
+            ) \
+	), \
+	(void)0 /* don't use the result */ \
+    )
+
+#else
+/* accessors for 64-bit unsigned long */
+#define X_DPY_GET_REQUEST(dpy) \
+    (((struct _XDisplay*)dpy)->request)
+#define X_DPY_SET_REQUEST(dpy, value) \
+    ((struct _XDisplay*)dpy)->request = (value)
+
+#define X_DPY_GET_LAST_REQUEST_READ(dpy) \
+    (((struct _XDisplay*)dpy)->last_request_read)
+#define X_DPY_SET_LAST_REQUEST_READ(dpy, value) \
+    ((struct _XDisplay*)dpy)->last_request_read = (value)
+
+#define X_DPY_WIDEN_UNSIGNED_LONG_SEQ(dpy, ulseq) ulseq
+
+#define X_DPY_REQUEST_INCREMENT(dpy) ((struct _XDisplay*)dpy)->request++
+#define X_DPY_REQUEST_DECREMENT(dpy) ((struct _XDisplay*)dpy)->request--
+#endif
+
+
 #ifndef _XEVENT_
 /*
  * _QEvent datatype for use in input queueing.
@@ -673,6 +784,9 @@ typedef struct _XInternalAsync {
     XPointer data;
 } _XAsyncHandler;
 
+/* This struct is part of the ABI and is defined by value
+   in user-code. This means that we cannot make
+   the sequence-numbers 64bit. */
 typedef struct _XAsyncEState {
     unsigned long min_sequence_number;
     unsigned long max_sequence_number;
diff --git a/src/ClDisplay.c b/src/ClDisplay.c
index bddd773..aa904e5 100644
--- a/src/ClDisplay.c
+++ b/src/ClDisplay.c
@@ -65,7 +65,7 @@ XCloseDisplay (
 		    (*ext->close_display)(dpy, &ext->codes);
 	    }
 	    /* if the closes generated more protocol, sync them up */
-	    if (dpy->request != dpy->last_request_read)
+	    if (X_DPY_GET_REQUEST(dpy) != X_DPY_GET_LAST_REQUEST_READ(dpy))
 		XSync(dpy, 1);
 	}
 	xcb_disconnect(dpy->xcb->connection);
diff --git a/src/Font.c b/src/Font.c
index 650bc6f..1c2345c 100644
--- a/src/Font.c
+++ b/src/Font.c
@@ -96,7 +96,7 @@ XFontStruct *XLoadQueryFont(
     register long nbytes;
     Font fid;
     xOpenFontReq *req;
-    unsigned long seq;
+    uint64_t seq;
 #ifdef USE_XF86BIGFONT
     XF86BigfontCodes *extcodes = _XF86BigfontCodes(dpy);
 #endif
@@ -105,7 +105,7 @@ XFontStruct *XLoadQueryFont(
       return font_result;
     LockDisplay(dpy);
     GetReq(OpenFont, req);
-    seq = dpy->request;
+    seq = X_DPY_GET_REQUEST(dpy);
     nbytes = req->nbytes  = name ? strlen(name) : 0;
     req->fid = fid = XAllocID(dpy);
     req->length += (nbytes+3)>>2;
@@ -436,8 +436,8 @@ _XF86BigfontQueryFont (
     /* The function _XQueryFont benefits from a "magic" error handler for
        BadFont coming from a X_QueryFont request. (See function _XReply.)
        We have to establish an error handler ourselves. */
-    async2_state.min_sequence_number = dpy->request;
-    async2_state.max_sequence_number = dpy->request;
+    async2_state.min_sequence_number = X_DPY_GET_REQUEST(dpy);
+    async2_state.max_sequence_number = X_DPY_GET_REQUEST(dpy);
     async2_state.error_code = BadFont;
     async2_state.major_opcode = extcodes->codes->major_opcode;
     async2_state.minor_opcode = X_XF86BigfontQueryFont;
diff --git a/src/GetAtomNm.c b/src/GetAtomNm.c
index 32de50d..d7f06e3 100644
--- a/src/GetAtomNm.c
+++ b/src/GetAtomNm.c
@@ -87,8 +87,8 @@ char *XGetAtomName(
 }
 
 typedef struct {
-    unsigned long start_seq;
-    unsigned long stop_seq;
+    uint64_t start_seq;
+    uint64_t stop_seq;
     Atom *atoms;
     char **names;
     int idx;
@@ -107,10 +107,11 @@ Bool _XGetAtomNameHandler(
     register _XGetAtomNameState *state;
     xGetAtomNameReply replbuf;
     register xGetAtomNameReply *repl;
+    uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
 
     state = (_XGetAtomNameState *)data;
-    if (dpy->last_request_read < state->start_seq ||
-	dpy->last_request_read > state->stop_seq)
+    if (last_request_read < state->start_seq ||
+	last_request_read > state->stop_seq)
 	return False;
     while (state->idx < state->count && state->names[state->idx])
 	state->idx++;
@@ -152,7 +153,7 @@ XGetAtomNames (
     int missed = -1;
 
     LockDisplay(dpy);
-    async_state.start_seq = dpy->request + 1;
+    async_state.start_seq = X_DPY_GET_REQUEST(dpy) + 1;
     async_state.atoms = atoms;
     async_state.names = names_return;
     async_state.idx = 0;
@@ -165,7 +166,7 @@ XGetAtomNames (
     for (i = 0; i < count; i++) {
 	if (!(names_return[i] = _XGetAtomName(dpy, atoms[i]))) {
 	    missed = i;
-	    async_state.stop_seq = dpy->request;
+	    async_state.stop_seq = X_DPY_GET_REQUEST(dpy);
 	}
     }
     if (missed >= 0) {
diff --git a/src/GetWAttrs.c b/src/GetWAttrs.c
index c10824c..0f5f7bb 100644
--- a/src/GetWAttrs.c
+++ b/src/GetWAttrs.c
@@ -30,8 +30,8 @@ in this Software without prior written authorization from The Open Group.
 #include "Xlibint.h"
 
 typedef struct _WAttrsState {
-    unsigned long attr_seq;
-    unsigned long geom_seq;
+    uint64_t attr_seq;
+    uint64_t geom_seq;
     XWindowAttributes *attr;
 } _XWAttrsState;
 
@@ -47,10 +47,11 @@ _XWAttrsHandler(
     xGetWindowAttributesReply replbuf;
     register xGetWindowAttributesReply *repl;
     register XWindowAttributes *attr;
+    uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
 
     state = (_XWAttrsState *)data;
-    if (dpy->last_request_read != state->attr_seq) {
-	if (dpy->last_request_read == state->geom_seq &&
+    if (last_request_read != state->attr_seq) {
+	if (last_request_read == state->geom_seq &&
 	    !state->attr &&
 	    rep->generic.type == X_Error &&
 	    rep->error.errorCode == BadDrawable)
@@ -99,7 +100,7 @@ _XGetWindowAttributes(
 
     GetResReq(GetWindowAttributes, w, req);
 
-    async_state.attr_seq = dpy->request;
+    async_state.attr_seq = X_DPY_GET_REQUEST(dpy);
     async_state.geom_seq = 0;
     async_state.attr = attr;
     async.next = dpy->async_handlers;
@@ -109,7 +110,7 @@ _XGetWindowAttributes(
 
     GetResReq(GetGeometry, w, req);
 
-    async_state.geom_seq = dpy->request;
+    async_state.geom_seq = X_DPY_GET_REQUEST(dpy);
 
     if (!_XReply (dpy, (xReply *)&rep, 0, xTrue)) {
 	DeqAsyncHandler(dpy, &async);
diff --git a/src/IntAtom.c b/src/IntAtom.c
index 3042b65..d9c6c58 100644
--- a/src/IntAtom.c
+++ b/src/IntAtom.c
@@ -188,8 +188,8 @@ XInternAtom (
 }
 
 typedef struct {
-    unsigned long start_seq;
-    unsigned long stop_seq;
+    uint64_t start_seq;
+    uint64_t stop_seq;
     char **names;
     Atom *atoms;
     int count;
@@ -208,10 +208,12 @@ Bool _XIntAtomHandler(
     register int i, idx = 0;
     xInternAtomReply replbuf;
     register xInternAtomReply *repl;
+    uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
 
     state = (_XIntAtomState *)data;
-    if (dpy->last_request_read < state->start_seq ||
-	dpy->last_request_read > state->stop_seq)
+
+    if (last_request_read < state->start_seq ||
+	last_request_read > state->stop_seq)
 	return False;
     for (i = 0; i < state->count; i++) {
 	if (state->atoms[i] & 0x80000000) {
@@ -252,7 +254,7 @@ XInternAtoms (
     xInternAtomReply rep;
 
     LockDisplay(dpy);
-    async_state.start_seq = dpy->request + 1;
+    async_state.start_seq = X_DPY_GET_REQUEST(dpy) + 1;
     async_state.atoms = atoms_return;
     async_state.names = names;
     async_state.count = count - 1;
@@ -266,7 +268,7 @@ XInternAtoms (
 					     &sig, &idx, &n))) {
 	    missed = i;
 	    atoms_return[i] = ~((Atom)idx);
-	    async_state.stop_seq = dpy->request;
+	    async_state.stop_seq = X_DPY_GET_REQUEST(dpy);
 	}
     }
     if (missed >= 0) {
diff --git a/src/OpenDis.c b/src/OpenDis.c
index 636860e..8272357 100644
--- a/src/OpenDis.c
+++ b/src/OpenDis.c
@@ -197,8 +197,8 @@ XOpenDisplay (
 	dpy->idlist_alloc = _XAllocIDs;
 	dpy->synchandler = NULL;
 	dpy->savedsynchandler = NULL;
-	dpy->request = 0;
-	dpy->last_request_read = 0;
+	X_DPY_SET_REQUEST(dpy, 0);
+	X_DPY_SET_LAST_REQUEST_READ(dpy, 0);
 	dpy->default_screen = iscreen;  /* Value returned by ConnectDisplay */
 	dpy->last_req = (char *)&_dummy_request;
 
diff --git a/src/PutImage.c b/src/PutImage.c
index de085bc..13cbba3 100644
--- a/src/PutImage.c
+++ b/src/PutImage.c
@@ -602,7 +602,7 @@ static int const HalfOrderWord[12] = {
 
 #define UnGetReq(name)\
     dpy->bufptr -= SIZEOF(x##name##Req);\
-    dpy->request--
+    X_DPY_REQUEST_DECREMENT(dpy)
 
 static void
 SendXYImage(
diff --git a/src/ReconfWM.c b/src/ReconfWM.c
index 8dc3534..1704d77 100644
--- a/src/ReconfWM.c
+++ b/src/ReconfWM.c
@@ -70,11 +70,13 @@ Status XReconfigureWMWindow (
 	register unsigned long *value = values;
 	long nvalues;
 	register xConfigureWindowReq *req;
+	uint64_t dpy_request;
 
 	GetReq(ConfigureWindow, req);
 
-	async_state.min_sequence_number = dpy->request;
-	async_state.max_sequence_number = dpy->request;
+	dpy_request = X_DPY_GET_REQUEST(dpy);
+	async_state.min_sequence_number = dpy_request;
+	async_state.max_sequence_number = dpy_request;
 	async_state.error_code = BadMatch;
 	async_state.major_opcode = X_ConfigureWindow;
 	async_state.minor_opcode = 0;
diff --git a/src/XlibAsync.c b/src/XlibAsync.c
index eb2b819..0d4bdce 100644
--- a/src/XlibAsync.c
+++ b/src/XlibAsync.c
@@ -41,9 +41,16 @@ _XAsyncErrorHandler(
     int len,
     XPointer data)
 {
-    register _XAsyncErrorState *state;
+    register _XAsyncErrorState *state = (_XAsyncErrorState *)data;
+    uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
+    uint64_t min_sequence_number =
+	X_DPY_WIDEN_UNSIGNED_LONG_SEQ(
+	    dpy, state->min_sequence_number);
+    uint64_t max_sequence_number =
+	X_DPY_WIDEN_UNSIGNED_LONG_SEQ(
+	    dpy, state->max_sequence_number);
+
 
-    state = (_XAsyncErrorState *)data;
     if (rep->generic.type == X_Error &&
 	(!state->error_code ||
 	 rep->error.errorCode == state->error_code) &&
@@ -51,10 +58,10 @@ _XAsyncErrorHandler(
 	 rep->error.majorCode == state->major_opcode) &&
 	(!state->minor_opcode ||
 	 rep->error.minorCode == state->minor_opcode) &&
-	(!state->min_sequence_number ||
-	 (state->min_sequence_number <= dpy->last_request_read)) &&
-	(!state->max_sequence_number ||
-	 (state->max_sequence_number >= dpy->last_request_read))) {
+	(!state->min_sequence_number || /* FIXME: if 32-bit wraparound results in a 0 we have a problem here */
+	 (min_sequence_number <= last_request_read)) &&
+	(!state->max_sequence_number || /* FIXME: if 32-bit wraparound results in a 0 we have a problem here */
+	 (max_sequence_number >= last_request_read))) {
 	state->last_error_received = rep->error.errorCode;
 	state->error_count++;
 	return True;
diff --git a/src/XlibInt.c b/src/XlibInt.c
index 80c1298..5a7e341 100644
--- a/src/XlibInt.c
+++ b/src/XlibInt.c
@@ -167,8 +167,10 @@ void _XPollfdCacheDel(
 
 static int sync_hazard(Display *dpy)
 {
-    unsigned long span = dpy->request - dpy->last_request_read;
-    unsigned long hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
+    /* "span" and "hazard" need to be signed such that the ">=" comparision
+       works correctly in the case that hazard is greater than 65525 */
+    int64_t span = X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy);
+    int64_t hazard = min((dpy->bufmax - dpy->buffer) / SIZEOF(xReq), 65535 - 10);
     return span >= 65535 - hazard - 10;
 }
 
@@ -194,7 +196,9 @@ void _XSeqSyncFunction(
     xGetInputFocusReply rep;
     register xReq *req;
 
-    if ((dpy->request - dpy->last_request_read) >= (65535 - BUFSIZE/SIZEOF(xReq))) {
+    if ((X_DPY_GET_REQUEST(dpy) - X_DPY_GET_LAST_REQUEST_READ(dpy))
+        >= (65535 - BUFSIZE/SIZEOF(xReq))
+    ) {
 	GetEmptyReq(GetInputFocus, req);
 	(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
 	sync_while_locked(dpy);
@@ -276,9 +280,9 @@ _XSetLastRequestRead(
     register Display *dpy,
     register xGenericReply *rep)
 {
-    register unsigned long	newseq, lastseq;
+    register uint64_t	newseq, lastseq;
 
-    lastseq = dpy->last_request_read;
+    lastseq = X_DPY_GET_LAST_REQUEST_READ(dpy);
     /*
      * KeymapNotify has no sequence number, but is always guaranteed
      * to immediately follow another event, except when generated via
@@ -287,20 +291,21 @@ _XSetLastRequestRead(
     if ((rep->type & 0x7f) == KeymapNotify)
 	return(lastseq);
 
-    newseq = (lastseq & ~((unsigned long)0xffff)) | rep->sequenceNumber;
+    newseq = (lastseq & ~((uint64_t)0xffff)) | rep->sequenceNumber;
 
     if (newseq < lastseq) {
 	newseq += 0x10000;
-	if (newseq > dpy->request) {
+	if (newseq > X_DPY_GET_REQUEST(dpy)) {
 	    (void) fprintf (stderr,
-	    "Xlib: sequence lost (0x%lx > 0x%lx) in reply type 0x%x!\n",
-			    newseq, dpy->request,
+	    "Xlib: sequence lost (0x%llx > 0x%llx) in reply type 0x%x!\n",
+			    (unsigned long long)newseq,
+			    (unsigned long long)(X_DPY_GET_REQUEST(dpy)),
 			    (unsigned int) rep->type);
 	    newseq -= 0x10000;
 	}
     }
 
-    dpy->last_request_read = newseq;
+    X_DPY_SET_LAST_REQUEST_READ(dpy, newseq);
     return(newseq);
 }
 
@@ -1363,10 +1368,10 @@ static int _XPrintDefaultError(
 			  mesg, BUFSIZ);
     fputs("  ", fp);
     (void) fprintf(fp, mesg, event->serial);
-    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
+    XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%lld",
 			  mesg, BUFSIZ);
     fputs("\n  ", fp);
-    (void) fprintf(fp, mesg, dpy->request);
+    (void) fprintf(fp, mesg, (unsigned long long)(X_DPY_GET_REQUEST(dpy)));
     fputs("\n", fp);
     if (event->error_code == BadImplementation) return 0;
     return 1;
@@ -1720,7 +1725,7 @@ void *_XGetRequest(Display *dpy, CARD8 type, size_t len)
     req->reqType = type;
     req->length = len / 4;
     dpy->bufptr += len;
-    dpy->request++;
+    X_DPY_REQUEST_INCREMENT(dpy);
     return req;
 }
 
diff --git a/src/Xxcbint.h b/src/Xxcbint.h
index bf41c23..20a6386 100644
--- a/src/Xxcbint.h
+++ b/src/Xxcbint.h
@@ -13,12 +13,12 @@
 #include <X11/Xlib-xcb.h>
 #include "locking.h"
 
-#define XLIB_SEQUENCE_COMPARE(a,op,b)	(((long) (a) - (long) (b)) op 0)
+#define XLIB_SEQUENCE_COMPARE(a,op,b)	(((int64_t) (a) - (int64_t) (b)) op 0)
 
 typedef struct PendingRequest PendingRequest;
 struct PendingRequest {
 	PendingRequest *next;
-	unsigned long sequence;
+	uint64_t sequence;
 	unsigned reply_waiter;
 };
 
diff --git a/src/xcb_io.c b/src/xcb_io.c
index 5987329..25955a8 100644
--- a/src/xcb_io.c
+++ b/src/xcb_io.c
@@ -46,6 +46,7 @@
 	xcb_fail_assert(_message, _var); \
 }
 
+
 static void return_socket(void *closure)
 {
 	Display *dpy = closure;
@@ -59,31 +60,18 @@ static void require_socket(Display *dpy)
 {
 	if(dpy->bufmax == dpy->buffer)
 	{
-		uint64_t sent;
+		uint64_t xcb_sent;
+		/* unsigned long xlib_sent; */
 		int flags = 0;
 		/* if we don't own the event queue, we have to ask XCB
 		 * to set our errors aside for us. */
 		if(dpy->xcb->event_owner != XlibOwnsEventQueue)
 			flags = XCB_REQUEST_CHECKED;
 		if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy,
-		                    flags, &sent))
+		                    flags, &xcb_sent))
 			_XIOError(dpy);
-		/* Xlib uses unsigned long for sequence numbers.  XCB
-		 * uses 64-bit internally, but currently exposes an
-		 * unsigned int API.  If these differ, Xlib cannot track
-		 * the full 64-bit sequence number if 32-bit wrap
-		 * happens while Xlib does not own the socket.  A
-		 * complete fix would be to make XCB's public API use
-		 * 64-bit sequence numbers. */
-		if (sizeof(unsigned long) > sizeof(unsigned int) &&
-		    dpy->xcb->event_owner == XlibOwnsEventQueue &&
-		    (sent - dpy->last_request_read >= (UINT64_C(1) << 32))) {
-			throw_thread_fail_assert("Sequence number wrapped "
-			                         "beyond 32 bits while Xlib "
-						 "did not own the socket",
-			                         xcb_xlib_seq_number_wrapped);
-		}
-		dpy->xcb->last_flushed = dpy->request = sent;
+		dpy->xcb->last_flushed = xcb_sent;
+		X_DPY_SET_REQUEST(dpy, xcb_sent);
 		dpy->bufmax = dpy->xcb->real_bufmax;
 	}
 }
@@ -145,7 +133,7 @@ static void check_internal_connections(Display *dpy)
 		}
 }
 
-static PendingRequest *append_pending_request(Display *dpy, unsigned long sequence)
+static PendingRequest *append_pending_request(Display *dpy, uint64_t sequence)
 {
 	PendingRequest *node = malloc(sizeof(PendingRequest));
 	assert(node);
@@ -214,14 +202,13 @@ static int handle_error(Display *dpy, xError *err, Bool in_XReply)
 	return 0;
 }
 
-/* Widen a 32-bit sequence number into a native-word-size (unsigned long)
- * sequence number.  Treating the comparison as a 1 and shifting it avoids a
- * conditional branch, and shifting by 16 twice avoids a compiler warning when
- * sizeof(unsigned long) == 4. */
-static void widen(unsigned long *wide, unsigned int narrow)
+/* Widen a 32-bit sequence number into a 64bit (uint64_t) sequence number.
+ * Treating the comparison as a 1 and shifting it avoids a conditional branch.
+ */
+static void widen(uint64_t *wide, unsigned int narrow)
 {
-	unsigned long new = (*wide & ~0xFFFFFFFFUL) | narrow;
-	*wide = new + ((unsigned long) (new < *wide) << 16 << 16);
+	uint64_t new = (*wide & ~((uint64_t)0xFFFFFFFFUL)) | narrow;
+	*wide = new + (((uint64_t)(new < *wide)) << 32);
 }
 
 /* Thread-safety rules:
@@ -260,20 +247,20 @@ static xcb_generic_reply_t *poll_for_event(Display *dpy)
 	{
 		PendingRequest *req = dpy->xcb->pending_requests;
 		xcb_generic_event_t *event = dpy->xcb->next_event;
-		unsigned long event_sequence = dpy->last_request_read;
+		uint64_t event_sequence = X_DPY_GET_LAST_REQUEST_READ(dpy);
 		widen(&event_sequence, event->full_sequence);
 		if(!req || XLIB_SEQUENCE_COMPARE(event_sequence, <, req->sequence)
 		        || (event->response_type != X_Error && event_sequence == req->sequence))
 		{
-			if (XLIB_SEQUENCE_COMPARE(event_sequence, >,
-			                          dpy->request))
+			uint64_t request = X_DPY_GET_REQUEST(dpy);
+			if (XLIB_SEQUENCE_COMPARE(event_sequence, >, request))
 			{
 				throw_thread_fail_assert("Unknown sequence "
 				                         "number while "
 							 "processing queue",
 				                xcb_xlib_threads_sequence_lost);
 			}
-			dpy->last_request_read = event_sequence;
+			X_DPY_SET_LAST_REQUEST_READ(dpy, event_sequence);
 			dpy->xcb->next_event = NULL;
 			return (xcb_generic_reply_t *) event;
 		}
@@ -289,15 +276,16 @@ static xcb_generic_reply_t *poll_for_response(Display *dpy)
 	while(!(response = poll_for_event(dpy)) &&
 	      (req = dpy->xcb->pending_requests) &&
 	      !req->reply_waiter &&
-	      xcb_poll_for_reply(dpy->xcb->connection, req->sequence, &response, &error))
+	      xcb_poll_for_reply64(dpy->xcb->connection, req->sequence, &response, &error))
 	{
-		if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy->request))
+		uint64_t request = X_DPY_GET_REQUEST(dpy);
+		if(XLIB_SEQUENCE_COMPARE(req->sequence, >, request))
 		{
 			throw_thread_fail_assert("Unknown sequence number "
 			                         "while awaiting reply",
 			                        xcb_xlib_threads_sequence_lost);
 		}
-		dpy->last_request_read = req->sequence;
+		X_DPY_SET_LAST_REQUEST_READ(dpy, req->sequence);
 		if(response)
 			break;
 		dequeue_pending_request(dpy, req);
@@ -456,6 +444,7 @@ void _XSend(Display *dpy, const char *data, long size)
 	static char const pad[3];
 	struct iovec vec[3];
 	uint64_t requests;
+	uint64_t dpy_request;
 	_XExtension *ext;
 	xcb_connection_t *c = dpy->xcb->connection;
 	if(dpy->flags & XlibDisplayIOError)
@@ -464,6 +453,9 @@ void _XSend(Display *dpy, const char *data, long size)
 	if(dpy->bufptr == dpy->buffer && !size)
 		return;
 
+	/* append_pending_request does not alter the dpy request number
+	   therefore we can get it outside of the loop and the if*/
+	dpy_request = X_DPY_GET_REQUEST(dpy);
 	/* iff we asked XCB to set aside errors, we must pick those up
 	 * eventually. iff there are async handlers, we may have just
 	 * issued requests that will generate replies. in either case,
@@ -471,11 +463,15 @@ void _XSend(Display *dpy, const char *data, long size)
 	if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers)
 	{
 		uint64_t sequence;
-		for(sequence = dpy->xcb->last_flushed + 1; sequence <= dpy->request; ++sequence)
+		for(
+			sequence = dpy->xcb->last_flushed + 1;
+			sequence <= dpy_request;
+			++sequence
+		)
 			append_pending_request(dpy, sequence);
 	}
-	requests = dpy->request - dpy->xcb->last_flushed;
-	dpy->xcb->last_flushed = dpy->request;
+	requests = dpy_request - dpy->xcb->last_flushed;
+	dpy->xcb->last_flushed = dpy_request;
 
 	vec[0].iov_base = dpy->buffer;
 	vec[0].iov_len = dpy->bufptr - dpy->buffer;
@@ -570,6 +566,7 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
 	xcb_connection_t *c = dpy->xcb->connection;
 	char *reply;
 	PendingRequest *current;
+	uint64_t dpy_request;
 
 	if (dpy->xcb->reply_data)
 		throw_extlib_fail_assert("Extra reply data still left in queue",
@@ -579,10 +576,12 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
 		return 0;
 
 	_XSend(dpy, NULL, 0);
-	if(dpy->xcb->pending_requests_tail && dpy->xcb->pending_requests_tail->sequence == dpy->request)
+	dpy_request = X_DPY_GET_REQUEST(dpy);
+	if(dpy->xcb->pending_requests_tail
+	   && dpy->xcb->pending_requests_tail->sequence == dpy_request)
 		current = dpy->xcb->pending_requests_tail;
 	else
-		current = append_pending_request(dpy, dpy->request);
+		current = append_pending_request(dpy, dpy_request);
 	/* Don't let any other thread get this reply. */
 	current->reply_waiter = 1;
 
@@ -599,9 +598,9 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
 		}
 		req->reply_waiter = 1;
 		UnlockDisplay(dpy);
-		response = xcb_wait_for_reply(c, req->sequence, &error);
+		response = xcb_wait_for_reply64(c, req->sequence, &error);
 		/* Any user locks on another thread must have been taken
-		 * while we slept in xcb_wait_for_reply. Classic Xlib
+		 * while we slept in xcb_wait_for_reply64. Classic Xlib
 		 * ignored those user locks in this case, so we do too. */
 		InternalLockDisplay(dpy, /* ignore user locks */ 1);
 
@@ -629,12 +628,13 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
 
 		req->reply_waiter = 0;
 		ConditionBroadcast(dpy, dpy->xcb->reply_notify);
-		if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy->request)) {
+		dpy_request = X_DPY_GET_REQUEST(dpy);
+		if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy_request)) {
 			throw_thread_fail_assert("Unknown sequence number "
 			                         "while processing reply",
 			                        xcb_xlib_threads_sequence_lost);
 		}
-		dpy->last_request_read = req->sequence;
+		X_DPY_SET_LAST_REQUEST_READ(dpy, req->sequence);
 		if(!response)
 			dequeue_pending_request(dpy, req);
 
@@ -654,9 +654,10 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
 	if(dpy->xcb->next_event && dpy->xcb->next_event->response_type == X_Error)
 	{
 		xcb_generic_event_t *event = dpy->xcb->next_event;
-		unsigned long event_sequence = dpy->last_request_read;
+		uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
+		uint64_t event_sequence = last_request_read;
 		widen(&event_sequence, event->full_sequence);
-		if(event_sequence == dpy->last_request_read)
+		if(event_sequence == last_request_read)
 		{
 			error = (xcb_generic_error_t *) event;
 			dpy->xcb->next_event = NULL;
diff --git a/src/xcms/cmsCmap.c b/src/xcms/cmsCmap.c
index c5401c0..47a5f9d 100644
--- a/src/xcms/cmsCmap.c
+++ b/src/xcms/cmsCmap.c
@@ -157,8 +157,8 @@ CmapRecForColormap(
 		register xCreateWindowReq *req;
 
 		GetReq(CreateWindow, req);
-		async_state.min_sequence_number = dpy->request;
-		async_state.max_sequence_number = dpy->request;
+		async_state.min_sequence_number = X_DPY_GET_REQUEST(dpy);
+		async_state.max_sequence_number = X_DPY_GET_REQUEST(dpy);
 		async_state.error_count = 0;
 		async.next = dpy->async_handlers;
 		async.handler = _XAsyncErrorHandler;
-- 
2.1.4



More information about the xorg-devel mailing list