Home | History | Annotate | Line # | Download | only in src
      1 /* Copyright (C) 2003-2006 Jamey Sharp, Josh Triplett
      2  * This file is licensed under the MIT license. See the file COPYING. */
      3 
      4 #ifdef HAVE_CONFIG_H
      5 #include <config.h>
      6 #endif
      7 
      8 #include "Xlibint.h"
      9 #include "locking.h"
     10 #include "Xprivate.h"
     11 #include "Xxcbint.h"
     12 #include <xcb/xcbext.h>
     13 
     14 #include <assert.h>
     15 #ifdef HAVE_INTTYPES_H
     16 #include <inttypes.h>
     17 #endif
     18 #include <stdio.h>
     19 #include <stdint.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <limits.h>
     23 #ifdef HAVE_SYS_SELECT_H
     24 #include <sys/select.h>
     25 #endif
     26 
     27 #define xcb_fail_assert(_message, _var) do { \
     28 	unsigned int _var = 1; \
     29 	fprintf(stderr, "[xcb] Aborting, sorry about that.\n"); \
     30 	assert(!_var); \
     31 } while (0)
     32 
     33 #ifdef XTHREADS
     34 #define throw_thread_fail_assert(_message, _var) do { \
     35 	fprintf(stderr, "[xcb] " _message "\n"); \
     36         if (_Xglobal_lock) { \
     37             fprintf(stderr, "[xcb] You called XInitThreads, this is not your fault\n"); \
     38         } else { \
     39             fprintf(stderr, "[xcb] Most likely this is a multi-threaded client " \
     40                             "and XInitThreads has not been called\n"); \
     41         } \
     42 	xcb_fail_assert(_message, _var); \
     43 } while (0)
     44 #else
     45 #define throw_thread_fail_assert(_message, _var) do { \
     46         fprintf(stderr, "[xcb] " _message "\n"); \
     47         fprintf(stderr, "[xcb] The libX11 library was built without " \
     48                         "multi-threading support\n"); \
     49         xcb_fail_assert(_message, _var); \
     50 } while (0)
     51 #endif
     52 
     53 /* XXX: It would probably be most useful if we stored the last-processed
     54  *      request, so we could find the offender from the message. */
     55 #define throw_extlib_fail_assert(_message, _var) do { \
     56 	fprintf(stderr, "[xcb] " _message "\n"); \
     57 	fprintf(stderr, "[xcb] This is most likely caused by a broken X " \
     58 	                "extension library\n"); \
     59 	xcb_fail_assert(_message, _var); \
     60 } while (0)
     61 
     62 static void return_socket(void *closure)
     63 {
     64 	Display *dpy = closure;
     65 	InternalLockDisplay(dpy, /* don't skip user locks */ 0);
     66 	_XSend(dpy, NULL, 0);
     67 	dpy->bufmax = dpy->buffer;
     68 	UnlockDisplay(dpy);
     69 }
     70 
     71 static Bool require_socket(Display *dpy)
     72 {
     73 	if(dpy->bufmax == dpy->buffer)
     74 	{
     75 		uint64_t sent;
     76 		int flags = 0;
     77 		/* if we don't own the event queue, we have to ask XCB
     78 		 * to set our errors aside for us. */
     79 		if(dpy->xcb->event_owner != XlibOwnsEventQueue)
     80 			flags = XCB_REQUEST_CHECKED;
     81 		if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy,
     82 		                    flags, &sent)) {
     83 			_XIOError(dpy);
     84 			return False;
     85 		}
     86 		dpy->xcb->last_flushed = sent;
     87 		X_DPY_SET_REQUEST(dpy, sent);
     88 		dpy->bufmax = dpy->xcb->real_bufmax;
     89 	}
     90 	return True;
     91 }
     92 
     93 /* Call internal connection callbacks for any fds that are currently
     94  * ready to read. This function will not block unless one of the
     95  * callbacks blocks.
     96  *
     97  * This code borrowed from _XWaitForReadable. Inverse call tree:
     98  * _XRead
     99  *  _XWaitForWritable
    100  *   _XFlush
    101  *   _XSend
    102  *  _XEventsQueued
    103  *  _XReadEvents
    104  *  _XRead[0-9]+
    105  *   _XAllocIDs
    106  *  _XReply
    107  *  _XEatData
    108  * _XReadPad
    109  */
    110 static Bool check_internal_connections(Display *dpy)
    111 {
    112 	struct _XConnectionInfo *ilist;
    113 	fd_set r_mask;
    114 	struct timeval tv;
    115 	int result;
    116 	int highest_fd = -1;
    117 
    118 	if(dpy->flags & XlibDisplayProcConni || !dpy->im_fd_info)
    119 		return True;
    120 
    121 	FD_ZERO(&r_mask);
    122 	for(ilist = dpy->im_fd_info; ilist; ilist = ilist->next)
    123 	{
    124 		assert(ilist->fd >= 0);
    125 		FD_SET(ilist->fd, &r_mask);
    126 		if(ilist->fd > highest_fd)
    127 			highest_fd = ilist->fd;
    128 	}
    129 	assert(highest_fd >= 0);
    130 
    131 	tv.tv_sec = 0;
    132 	tv.tv_usec = 0;
    133 	result = select(highest_fd + 1, &r_mask, NULL, NULL, &tv);
    134 
    135 	if(result == -1)
    136 	{
    137 		if(errno != EINTR) {
    138 			_XIOError(dpy);
    139 			return False;
    140 		}
    141 
    142 		return True;
    143 	}
    144 
    145 	for(ilist = dpy->im_fd_info; result && ilist; ilist = ilist->next)
    146 		if(FD_ISSET(ilist->fd, &r_mask))
    147 		{
    148 			_XProcessInternalConnection(dpy, ilist);
    149 			--result;
    150 		}
    151 
    152 	return True;
    153 }
    154 
    155 static PendingRequest *append_pending_request(Display *dpy, uint64_t sequence)
    156 {
    157 	PendingRequest *node = malloc(sizeof(PendingRequest));
    158 	assert(node);
    159 	node->next = NULL;
    160 	node->sequence = sequence;
    161 	node->reply_waiter = 0;
    162 	if(dpy->xcb->pending_requests_tail)
    163 	{
    164 		if (XLIB_SEQUENCE_COMPARE(dpy->xcb->pending_requests_tail->sequence,
    165 		                          >=, node->sequence))
    166 			throw_thread_fail_assert("Unknown sequence number "
    167 			                         "while appending request",
    168 			                         xcb_xlib_unknown_seq_number);
    169 		if (dpy->xcb->pending_requests_tail->next != NULL)
    170 			throw_thread_fail_assert("Unknown request in queue "
    171 			                         "while appending request",
    172 			                         xcb_xlib_unknown_req_pending);
    173 		dpy->xcb->pending_requests_tail->next = node;
    174 	}
    175 	else
    176 		dpy->xcb->pending_requests = node;
    177 	dpy->xcb->pending_requests_tail = node;
    178 	return node;
    179 }
    180 
    181 static void dequeue_pending_request(Display *dpy, PendingRequest *req)
    182 {
    183 	if (req != dpy->xcb->pending_requests)
    184 		throw_thread_fail_assert("Unknown request in queue while "
    185 		                         "dequeuing",
    186 		                         xcb_xlib_unknown_req_in_deq);
    187 
    188 	dpy->xcb->pending_requests = req->next;
    189 	if(!dpy->xcb->pending_requests)
    190 	{
    191 		if (req != dpy->xcb->pending_requests_tail)
    192 			throw_thread_fail_assert("Unknown request in queue "
    193 			                         "while dequeuing",
    194 			                         xcb_xlib_unknown_req_in_deq);
    195 		dpy->xcb->pending_requests_tail = NULL;
    196 	}
    197 	else if (XLIB_SEQUENCE_COMPARE(req->sequence, >=,
    198 	                               dpy->xcb->pending_requests->sequence))
    199 		throw_thread_fail_assert("Unknown sequence number while "
    200 		                         "dequeuing request",
    201 		                         xcb_xlib_threads_sequence_lost);
    202 
    203 	free(req);
    204 }
    205 
    206 static int handle_error(Display *dpy, xError *err, Bool in_XReply)
    207 {
    208 	_XExtension *ext;
    209 	int ret_code;
    210 	/* Oddly, Xlib only allows extensions to suppress errors when
    211 	 * those errors were seen by _XReply. */
    212 	if(in_XReply)
    213 		/*
    214 		 * we better see if there is an extension who may
    215 		 * want to suppress the error.
    216 		 */
    217 		for(ext = dpy->ext_procs; ext; ext = ext->next)
    218 			if(ext->error && (*ext->error)(dpy, err, &ext->codes, &ret_code))
    219 				return ret_code;
    220 	_XError(dpy, err);
    221 	return 0;
    222 }
    223 
    224 /* Widen a 32-bit sequence number into a 64bit (uint64_t) sequence number.
    225  * Treating the comparison as a 1 and shifting it avoids a conditional branch.
    226  */
    227 static void widen(uint64_t *wide, unsigned int narrow)
    228 {
    229 	uint64_t new = (*wide & ~((uint64_t)0xFFFFFFFFUL)) | narrow;
    230 	/* If just copying the upper dword of *wide makes the number
    231 	 * go down by more than 2^31, then it means that the lower
    232 	 * dword has wrapped (or we have skipped 2^31 requests, which
    233 	 * is hopefully improbable), so we add a carry. */
    234 	uint64_t wraps = new + (1UL << 31) < *wide;
    235 	*wide = new + (wraps << 32);
    236 }
    237 
    238 /* Thread-safety rules:
    239  *
    240  * At most one thread can be reading from XCB's event queue at a time.
    241  * If you are not the current event-reading thread and you need to find
    242  * out if an event is available, you must wait.
    243  *
    244  * The same rule applies for reading replies.
    245  *
    246  * A single thread cannot be both the the event-reading and the
    247  * reply-reading thread at the same time.
    248  *
    249  * We always look at both the current event and the first pending reply
    250  * to decide which to process next.
    251  *
    252  * We always process all responses in sequence-number order, which may
    253  * mean waiting for another thread (either the event_waiter or the
    254  * reply_waiter) to handle an earlier response before we can process or
    255  * return a later one. If so, we wait on the corresponding condition
    256  * variable for that thread to process the response and wake us up.
    257  */
    258 
    259 static xcb_generic_reply_t *poll_for_event(Display *dpy, Bool queued_only)
    260 {
    261 	/* Make sure the Display's sequence numbers are valid */
    262 	if (!require_socket(dpy))
    263 		return NULL;
    264 
    265 	/* Precondition: This thread can safely get events from XCB. */
    266 	assert(dpy->xcb->event_owner == XlibOwnsEventQueue && !dpy->xcb->event_waiter);
    267 
    268 	if(!dpy->xcb->next_event) {
    269 		if(queued_only)
    270 			dpy->xcb->next_event = xcb_poll_for_queued_event(dpy->xcb->connection);
    271 		else
    272 			dpy->xcb->next_event = xcb_poll_for_event(dpy->xcb->connection);
    273 	}
    274 
    275 	if(dpy->xcb->next_event)
    276 	{
    277 		PendingRequest *req = dpy->xcb->pending_requests;
    278 		xcb_generic_event_t *event = dpy->xcb->next_event;
    279 		uint64_t event_sequence = X_DPY_GET_LAST_REQUEST_READ(dpy);
    280 		widen(&event_sequence, event->full_sequence);
    281 		if(!req || XLIB_SEQUENCE_COMPARE(event_sequence, <, req->sequence)
    282 		        || (event->response_type != X_Error && event_sequence == req->sequence))
    283 		{
    284 			uint64_t request = X_DPY_GET_REQUEST(dpy);
    285 			if (XLIB_SEQUENCE_COMPARE(event_sequence, >, request))
    286 			{
    287 				throw_thread_fail_assert("Unknown sequence "
    288 				                         "number while "
    289 							 "processing queue",
    290 				                xcb_xlib_threads_sequence_lost);
    291 			}
    292 			X_DPY_SET_LAST_REQUEST_READ(dpy, event_sequence);
    293 			dpy->xcb->next_event = NULL;
    294 			return (xcb_generic_reply_t *) event;
    295 		}
    296 	}
    297 	return NULL;
    298 }
    299 
    300 static xcb_generic_reply_t *poll_for_response(Display *dpy)
    301 {
    302 	void *response;
    303 	xcb_generic_reply_t *event;
    304 	PendingRequest *req;
    305 
    306 	while(1)
    307 	{
    308 		xcb_generic_error_t *error = NULL;
    309 		uint64_t request;
    310 		Bool poll_queued_only = dpy->xcb->next_response != NULL;
    311 
    312 		/* Step 1: is there an event in our queue before the next
    313 		 * reply/error? Return that first.
    314 		 *
    315 		 * If we don't have a reply/error saved from an earlier
    316 		 * invocation we check incoming events too, otherwise only
    317 		 * the ones already queued.
    318 		 */
    319 		response = poll_for_event(dpy, poll_queued_only);
    320 		if(response)
    321 			break;
    322 
    323 		/* Step 2:
    324 		 * Response is NULL, i.e. we have no events.
    325 		 * If we are not waiting for a reply or some other thread
    326 		 * had dibs on the next reply, exit.
    327 		 */
    328 		req = dpy->xcb->pending_requests;
    329 		if(!req || req->reply_waiter)
    330 			break;
    331 
    332 		/* Step 3:
    333 		 * We have some response (error or reply) related to req
    334 		 * saved from an earlier invocation of this function. Let's
    335 		 * use that one.
    336 		 */
    337 		if(dpy->xcb->next_response)
    338 		{
    339 			if (((xcb_generic_reply_t*)dpy->xcb->next_response)->response_type == X_Error)
    340 			{
    341 				error = dpy->xcb->next_response;
    342 				response = NULL;
    343 			}
    344 			else
    345 			{
    346 				response = dpy->xcb->next_response;
    347 				error = NULL;
    348 			}
    349 			dpy->xcb->next_response = NULL;
    350 		}
    351 		else
    352 		{
    353 			/* Step 4: pull down the next response from the wire. This
    354 			 * should be the 99% case.
    355 			 * xcb_poll_for_reply64() may also pull down events that
    356 			 * happened before the reply.
    357 			 */
    358 			if(!xcb_poll_for_reply64(dpy->xcb->connection, req->sequence,
    359 						 &response, &error)) {
    360 				/* if there is no reply/error, xcb_poll_for_reply64
    361 				 * may have read events. Return that. */
    362 				response = poll_for_event(dpy, True);
    363 				break;
    364 			}
    365 
    366 			/* Step 5: we have a new response, but we may also have some
    367 			 * events that happened before that response. Return those
    368 			 * first and save our reply/error for the next invocation.
    369 			 */
    370 			event = poll_for_event(dpy, True);
    371 			if(event)
    372 			{
    373 				dpy->xcb->next_response = error ? error : response;
    374 				response = event;
    375 				break;
    376 			}
    377 		}
    378 
    379 		/* Step 6: actually handle the reply/error now... */
    380 		request = X_DPY_GET_REQUEST(dpy);
    381 		if(XLIB_SEQUENCE_COMPARE(req->sequence, >, request))
    382 		{
    383 			throw_thread_fail_assert("Unknown sequence number "
    384 			                         "while awaiting reply",
    385 			                        xcb_xlib_threads_sequence_lost);
    386 		}
    387 		X_DPY_SET_LAST_REQUEST_READ(dpy, req->sequence);
    388 		if(response)
    389 			break;
    390 		dequeue_pending_request(dpy, req);
    391 		if(error)
    392 			return (xcb_generic_reply_t *) error;
    393 	}
    394 	return response;
    395 }
    396 
    397 static void handle_response(Display *dpy, xcb_generic_reply_t *response, Bool in_XReply)
    398 {
    399 	_XAsyncHandler *async, *next;
    400 	switch(response->response_type)
    401 	{
    402 	case X_Reply:
    403 		for(async = dpy->async_handlers; async; async = next)
    404 		{
    405 			next = async->next;
    406 			if(async->handler(dpy, (xReply *) response, (char *) response, sizeof(xReply) + (response->length << 2), async->data))
    407 				break;
    408 		}
    409 		break;
    410 
    411 	case X_Error:
    412 		handle_error(dpy, (xError *) response, in_XReply);
    413 		break;
    414 
    415 	default: /* event */
    416 		/* GenericEvents may be > 32 bytes. In this case, the
    417 		 * event struct is trailed by the additional bytes. the
    418 		 * xcb_generic_event_t struct uses 4 bytes for internal
    419 		 * numbering, so we need to shift the trailing data to
    420 		 * be after the first 32 bytes. */
    421 		if(response->response_type == GenericEvent && ((xcb_ge_event_t *) response)->length)
    422 		{
    423 			xcb_ge_event_t *event = (xcb_ge_event_t *) response;
    424 			memmove(&event->full_sequence, &event[1], event->length * 4);
    425 		}
    426 		_XEnq(dpy, (xEvent *) response);
    427 		break;
    428 	}
    429 	free(response);
    430 }
    431 
    432 int _XEventsQueued(Display *dpy, int mode)
    433 {
    434 	xcb_generic_reply_t *response;
    435 	if(dpy->flags & XlibDisplayIOError)
    436 		return 0;
    437 	if(dpy->xcb->event_owner != XlibOwnsEventQueue)
    438 		return 0;
    439 
    440 	if(mode == QueuedAfterFlush)
    441 		_XSend(dpy, NULL, 0);
    442 	else if (!check_internal_connections(dpy))
    443 		return 0;
    444 
    445 	/* If another thread is blocked waiting for events, then we must
    446 	 * let that thread pick up the next event. Since it blocked, we
    447 	 * can reasonably claim there are no new events right now. */
    448 	if(!dpy->xcb->event_waiter)
    449 	{
    450 		while((response = poll_for_response(dpy)))
    451 			handle_response(dpy, response, False);
    452 		if(xcb_connection_has_error(dpy->xcb->connection)) {
    453 			_XIOError(dpy);
    454 			return 0;
    455 		}
    456 	}
    457 	return dpy->qlen;
    458 }
    459 
    460 /* _XReadEvents - Flush the output queue,
    461  * then read as many events as possible (but at least 1) and enqueue them
    462  */
    463 void _XReadEvents(Display *dpy)
    464 {
    465 	xcb_generic_reply_t *response;
    466 	unsigned long serial;
    467 
    468 	if(dpy->flags & XlibDisplayIOError)
    469 		return;
    470 	_XSend(dpy, NULL, 0);
    471 	if(dpy->xcb->event_owner != XlibOwnsEventQueue)
    472 		return;
    473 	if (!check_internal_connections(dpy))
    474 		return;
    475 
    476 	serial = dpy->next_event_serial_num;
    477 	while(serial == dpy->next_event_serial_num || dpy->qlen == 0)
    478 	{
    479 		if(dpy->xcb->event_waiter)
    480 		{
    481 			ConditionWait(dpy, dpy->xcb->event_notify);
    482 			/* Maybe the other thread got us an event. */
    483 			continue;
    484 		}
    485 
    486 		if(!dpy->xcb->next_event)
    487 		{
    488 			xcb_generic_event_t *event;
    489 			dpy->xcb->event_waiter = 1;
    490 			UnlockDisplay(dpy);
    491 			event = xcb_wait_for_event(dpy->xcb->connection);
    492 			/* It appears that classic Xlib respected user
    493 			 * locks when waking up after waiting for
    494 			 * events. However, if this thread did not have
    495 			 * any user locks, and another thread takes a
    496 			 * user lock and tries to read events, then we'd
    497 			 * deadlock. So we'll choose to let the thread
    498 			 * that got in first consume events, despite the
    499 			 * later thread's user locks. */
    500 			InternalLockDisplay(dpy, /* ignore user locks */ 1);
    501 			dpy->xcb->event_waiter = 0;
    502 			ConditionBroadcast(dpy, dpy->xcb->event_notify);
    503 			if(!event)
    504 			{
    505 				_XIOError(dpy);
    506 				return;
    507 			}
    508 			dpy->xcb->next_event = event;
    509 		}
    510 
    511 		/* We've established most of the conditions for
    512 		 * poll_for_response to return non-NULL. The exceptions
    513 		 * are connection shutdown, and finding that another
    514 		 * thread is waiting for the next reply we'd like to
    515 		 * process. */
    516 
    517 		response = poll_for_response(dpy);
    518 		if(response)
    519 			handle_response(dpy, response, False);
    520 		else if(dpy->xcb->pending_requests->reply_waiter)
    521 		{ /* need braces around ConditionWait */
    522 			ConditionWait(dpy, dpy->xcb->reply_notify);
    523 		}
    524 		else
    525 		{
    526 		        _XIOError(dpy);
    527 		        return;
    528 		}
    529 	}
    530 
    531 	/* The preceding loop established that there is no
    532 	 * event_waiter--unless we just called ConditionWait because of
    533 	 * a reply_waiter, in which case another thread may have become
    534 	 * the event_waiter while we slept unlocked. */
    535 	if(!dpy->xcb->event_waiter)
    536 		while((response = poll_for_response(dpy)))
    537 			handle_response(dpy, response, False);
    538 	if(xcb_connection_has_error(dpy->xcb->connection))
    539 		_XIOError(dpy);
    540 }
    541 
    542 /*
    543  * _XSend - Flush the buffer and send the client data. 32 bit word aligned
    544  * transmission is used, if size is not 0 mod 4, extra bytes are transmitted.
    545  *
    546  * Note that the connection must not be read from once the data currently
    547  * in the buffer has been written.
    548  */
    549 void _XSend(Display *dpy, const char *data, long size)
    550 {
    551 	static const xReq dummy_request;
    552 	static char const pad[3];
    553 	struct iovec vec[3];
    554 	uint64_t requests;
    555 	uint64_t dpy_request;
    556 	_XExtension *ext;
    557 	xcb_connection_t *c = dpy->xcb->connection;
    558 	if(dpy->flags & XlibDisplayIOError)
    559 		return;
    560 
    561 	if(dpy->bufptr == dpy->buffer && !size)
    562 		return;
    563 
    564 	/* append_pending_request does not alter the dpy request number
    565 	 * therefore we can get it outside of the loop and the if
    566 	 */
    567 	dpy_request = X_DPY_GET_REQUEST(dpy);
    568 	/* iff we asked XCB to set aside errors, we must pick those up
    569 	 * eventually. iff there are async handlers, we may have just
    570 	 * issued requests that will generate replies. in either case,
    571 	 * we need to remember to check later. */
    572 	if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers)
    573 	{
    574 		uint64_t sequence;
    575 		for(sequence = dpy->xcb->last_flushed + 1; sequence <= dpy_request; ++sequence)
    576 			append_pending_request(dpy, sequence);
    577 	}
    578 	requests = dpy_request - dpy->xcb->last_flushed;
    579 	dpy->xcb->last_flushed = dpy_request;
    580 
    581 	vec[0].iov_base = dpy->buffer;
    582 	vec[0].iov_len = dpy->bufptr - dpy->buffer;
    583 	vec[1].iov_base = (char *)data;
    584 	vec[1].iov_len = size;
    585 	vec[2].iov_base = (char *)pad;
    586 	vec[2].iov_len = -size & 3;
    587 
    588 	for(ext = dpy->flushes; ext; ext = ext->next_flush)
    589 	{
    590 		int i;
    591 		for(i = 0; i < 3; ++i)
    592 			if(vec[i].iov_len)
    593 				ext->before_flush(dpy, &ext->codes, vec[i].iov_base, vec[i].iov_len);
    594 	}
    595 
    596 	if(xcb_writev(c, vec, 3, requests) < 0) {
    597 		_XIOError(dpy);
    598 		return;
    599 	}
    600 	dpy->bufptr = dpy->buffer;
    601 	dpy->last_req = (char *) &dummy_request;
    602 
    603 	if (!check_internal_connections(dpy))
    604 		return;
    605 
    606 	_XSetSeqSyncFunction(dpy);
    607 }
    608 
    609 /*
    610  * _XFlush - Flush the X request buffer.  If the buffer is empty, no
    611  * action is taken.
    612  */
    613 void _XFlush(Display *dpy)
    614 {
    615 	if (!require_socket(dpy))
    616 		return;
    617 
    618 	_XSend(dpy, NULL, 0);
    619 
    620 	_XEventsQueued(dpy, QueuedAfterReading);
    621 }
    622 
    623 static const XID inval_id = ~0UL;
    624 
    625 void _XIDHandler(Display *dpy)
    626 {
    627 	if (dpy->xcb->next_xid == inval_id)
    628 		_XAllocIDs(dpy, &dpy->xcb->next_xid, 1);
    629 }
    630 
    631 /* _XAllocID - resource ID allocation routine. */
    632 XID _XAllocID(Display *dpy)
    633 {
    634 	XID ret = dpy->xcb->next_xid;
    635 	assert (ret != inval_id);
    636 	dpy->xcb->next_xid = inval_id;
    637 	_XSetPrivSyncFunction(dpy);
    638 	return ret;
    639 }
    640 
    641 /* _XAllocIDs - multiple resource ID allocation routine. */
    642 void _XAllocIDs(Display *dpy, XID *ids, int count)
    643 {
    644 	int i;
    645 #ifdef XTHREADS
    646 	if (dpy->lock)
    647 		(*dpy->lock->user_lock_display)(dpy);
    648 	UnlockDisplay(dpy);
    649 #endif
    650 	for (i = 0; i < count; i++)
    651 		ids[i] = xcb_generate_id(dpy->xcb->connection);
    652 #ifdef XTHREADS
    653 	InternalLockDisplay(dpy, /* don't skip user locks */ 0);
    654 	if (dpy->lock)
    655 		(*dpy->lock->user_unlock_display)(dpy);
    656 #endif
    657 }
    658 
    659 static void _XFreeReplyData(Display *dpy, Bool force)
    660 {
    661 	if(!force && dpy->xcb->reply_consumed < dpy->xcb->reply_length)
    662 		return;
    663 	free(dpy->xcb->reply_data);
    664 	dpy->xcb->reply_data = NULL;
    665 }
    666 
    667 /*
    668  * _XReply - Wait for a reply packet and copy its contents into the
    669  * specified rep.
    670  * extra: number of 32-bit words expected after the reply
    671  * discard: should I discard data following "extra" words?
    672  */
    673 Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard)
    674 {
    675 	xcb_generic_error_t *error;
    676 	xcb_connection_t *c = dpy->xcb->connection;
    677 	char *reply;
    678 	PendingRequest *current;
    679 	uint64_t dpy_request;
    680 
    681 	if (dpy->xcb->reply_data)
    682 		throw_extlib_fail_assert("Extra reply data still left in queue",
    683 		                         xcb_xlib_extra_reply_data_left);
    684 
    685 	if(dpy->flags & XlibDisplayIOError)
    686 		return 0;
    687 
    688 	_XSend(dpy, NULL, 0);
    689 	dpy_request = X_DPY_GET_REQUEST(dpy);
    690 	if(dpy->xcb->pending_requests_tail
    691 	   && dpy->xcb->pending_requests_tail->sequence == dpy_request)
    692 		current = dpy->xcb->pending_requests_tail;
    693 	else
    694 		current = append_pending_request(dpy, dpy_request);
    695 	/* Don't let any other thread get this reply. */
    696 	current->reply_waiter = 1;
    697 
    698 	while(1)
    699 	{
    700 		PendingRequest *req = dpy->xcb->pending_requests;
    701 		xcb_generic_reply_t *response;
    702 
    703 		if(req != current && req->reply_waiter)
    704 		{
    705 			ConditionWait(dpy, dpy->xcb->reply_notify);
    706 			/* Another thread got this reply. */
    707 			continue;
    708 		}
    709 		req->reply_waiter = 1;
    710 		UnlockDisplay(dpy);
    711 		response = xcb_wait_for_reply64(c, req->sequence, &error);
    712 		/* Any user locks on another thread must have been taken
    713 		 * while we slept in xcb_wait_for_reply64. Classic Xlib
    714 		 * ignored those user locks in this case, so we do too. */
    715 		InternalLockDisplay(dpy, /* ignore user locks */ 1);
    716 
    717 		/* We have the response we're looking for. Now, before
    718 		 * letting anyone else process this sequence number, we
    719 		 * need to process any events that should have come
    720 		 * earlier. */
    721 
    722 		if(dpy->xcb->event_owner == XlibOwnsEventQueue)
    723 		{
    724 			xcb_generic_reply_t *event;
    725 
    726 			/* Assume event queue is empty if another thread is blocking
    727 			 * waiting for event. */
    728 			if(!dpy->xcb->event_waiter)
    729 			{
    730 				while((event = poll_for_response(dpy)))
    731 					handle_response(dpy, event, True);
    732                         }
    733 		}
    734 
    735 		req->reply_waiter = 0;
    736 		ConditionBroadcast(dpy, dpy->xcb->reply_notify);
    737 		dpy_request = X_DPY_GET_REQUEST(dpy);
    738 		if(XLIB_SEQUENCE_COMPARE(req->sequence, >, dpy_request)) {
    739 			throw_thread_fail_assert("Unknown sequence number "
    740 			                         "while processing reply",
    741 			                        xcb_xlib_threads_sequence_lost);
    742 		}
    743 		X_DPY_SET_LAST_REQUEST_READ(dpy, req->sequence);
    744 		if(!response)
    745 			dequeue_pending_request(dpy, req);
    746 
    747 		if(req == current)
    748 		{
    749 			reply = (char *) response;
    750 			break;
    751 		}
    752 
    753 		if(error)
    754 			handle_response(dpy, (xcb_generic_reply_t *) error, True);
    755 		else if(response)
    756 			handle_response(dpy, response, True);
    757 	}
    758 	if (!check_internal_connections(dpy))
    759 		return 0;
    760 
    761 	if(dpy->xcb->next_event && dpy->xcb->next_event->response_type == X_Error)
    762 	{
    763 		xcb_generic_event_t *event = dpy->xcb->next_event;
    764 		uint64_t last_request_read = X_DPY_GET_LAST_REQUEST_READ(dpy);
    765 		uint64_t event_sequence = last_request_read;
    766 		widen(&event_sequence, event->full_sequence);
    767 		if(event_sequence == last_request_read)
    768 		{
    769 			error = (xcb_generic_error_t *) event;
    770 			dpy->xcb->next_event = NULL;
    771 		}
    772 	}
    773 
    774 	if(error)
    775 	{
    776 		int ret_code;
    777 
    778 		/* Xlib is evil and assumes that even errors will be
    779 		 * copied into rep. */
    780 		memcpy(rep, error, 32);
    781 
    782 		/* do not die on "no such font", "can't allocate",
    783 		   "can't grab" failures */
    784 		switch(error->error_code)
    785 		{
    786 			case BadName:
    787 				switch(error->major_code)
    788 				{
    789 					case X_LookupColor:
    790 					case X_AllocNamedColor:
    791 						free(error);
    792 						return 0;
    793 				}
    794 				break;
    795 			case BadFont:
    796 				if(error->major_code == X_QueryFont) {
    797 					free(error);
    798 					return 0;
    799 				}
    800 				break;
    801 			case BadAlloc:
    802 			case BadAccess:
    803 				free(error);
    804 				return 0;
    805 		}
    806 
    807 		ret_code = handle_error(dpy, (xError *) error, True);
    808 		free(error);
    809 		return ret_code;
    810 	}
    811 
    812 	/* it's not an error, but we don't have a reply, so it's an I/O
    813 	 * error. */
    814 	if(!reply) {
    815 		_XIOError(dpy);
    816 		return 0;
    817 	}
    818 
    819 	/* there's no error and we have a reply. */
    820 	dpy->xcb->reply_data = reply;
    821 	dpy->xcb->reply_consumed = sizeof(xReply) + (extra * 4);
    822 	dpy->xcb->reply_length = sizeof(xReply);
    823 	if(dpy->xcb->reply_data[0] == 1)
    824 		dpy->xcb->reply_length += (((xcb_generic_reply_t *) dpy->xcb->reply_data)->length * 4);
    825 
    826 	/* error: Xlib asks too much. give them what we can anyway. */
    827 	if(dpy->xcb->reply_length < dpy->xcb->reply_consumed)
    828 		dpy->xcb->reply_consumed = dpy->xcb->reply_length;
    829 
    830 	memcpy(rep, dpy->xcb->reply_data, dpy->xcb->reply_consumed);
    831 	_XFreeReplyData(dpy, discard);
    832 	return 1;
    833 }
    834 
    835 int _XRead(Display *dpy, char *data, long size)
    836 {
    837 	assert(size >= 0);
    838 	if(size == 0)
    839 		return 0;
    840 	if(dpy->xcb->reply_data == NULL ||
    841 	   dpy->xcb->reply_consumed + size > dpy->xcb->reply_length)
    842 		throw_extlib_fail_assert("Too much data requested from _XRead",
    843 		                         xcb_xlib_too_much_data_requested);
    844 	memcpy(data, dpy->xcb->reply_data + dpy->xcb->reply_consumed, size);
    845 	dpy->xcb->reply_consumed += size;
    846 	_XFreeReplyData(dpy, False);
    847 	return 0;
    848 }
    849 
    850 /*
    851  * _XReadPad - Read bytes from the socket taking into account incomplete
    852  * reads.  If the number of bytes is not 0 mod 4, read additional pad
    853  * bytes.
    854  */
    855 void _XReadPad(Display *dpy, char *data, long size)
    856 {
    857 	_XRead(dpy, data, size);
    858 	dpy->xcb->reply_consumed += -size & 3;
    859 	_XFreeReplyData(dpy, False);
    860 }
    861 
    862 /* Read and discard "n" 8-bit bytes of data */
    863 void _XEatData(Display *dpy, unsigned long n)
    864 {
    865 	dpy->xcb->reply_consumed += n;
    866 	_XFreeReplyData(dpy, False);
    867 }
    868 
    869 /*
    870  * Read and discard "n" 32-bit words of data
    871  * Matches the units of the length field in X protocol replies, and provides
    872  * a single implementation of overflow checking to avoid having to replicate
    873  * those checks in every caller.
    874  */
    875 void _XEatDataWords(Display *dpy, unsigned long n)
    876 {
    877 	if (n < ((INT_MAX - dpy->xcb->reply_consumed) >> 2))
    878 		dpy->xcb->reply_consumed += (n << 2);
    879 	else
    880 		/* Overflow would happen, so just eat the rest of the reply */
    881 		dpy->xcb->reply_consumed = dpy->xcb->reply_length;
    882 	_XFreeReplyData(dpy, False);
    883 }
    884 
    885 unsigned long
    886 _XNextRequest(Display *dpy)
    887 {
    888     /* This will update dpy->request. The assumption is that the next thing
    889      * that the application will do is make a request so there's little
    890      * overhead.
    891      */
    892     require_socket(dpy);
    893     return NextRequest(dpy);
    894 }
    895