Hello,

While I tried to use the xcb-sync (1.12) I found I issue while getting
the list of system counter. It seems to be an error due to incorrect
parsing of the content of the reply message of
xcb_sync_list_system_counters request.

The cause is that the padding does not apply between items headers and
the following name, but after the item header and the following name.
libxcb do the former.

If I am correct, libxcb expect something like:

counter : 4 bytes
resolution: 8 bytes
name_len : 2 bytes
[padding]: 2 bytes
name: *name_len* bytes
[padding] : N bytes to pad to 4 bytes bound.

while the correct layout is:

counter : 4 bytes
resolution: 8 bytes
name_len : 2 bytes
name: *name_len* bytes
[padding] : N bytes to pad to 4 bytes bound.

I attached a dirty but correct way to parse the list of system counter.
I do not known how to fix sync.xml and c_client.py to get the proper
behavior.

best regards.
/*
 ============================================================================
 Name        : test_xsync.c
 Author      : 
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/sync.h>

int query_extension(xcb_connection_t * dpy, char const * name, int * opcode,
		int * event, int * error) {
	xcb_generic_error_t * err;
	xcb_query_extension_cookie_t ck = xcb_query_extension(dpy, strlen(name),
			name);
	xcb_query_extension_reply_t * r = xcb_query_extension_reply(dpy, ck, &err);
	if (err != 0 || r == 0) {
		return 0;
	} else {
		*opcode = r->major_opcode;
		*event = r->first_event;
		*error = r->first_error;
		free(r);
		return 1;
	}
}

int check_sync_extension(xcb_connection_t * dpy) {
	int sync_opcode;
	int sync_event;
	int sync_error;
	if (!query_extension(dpy, "SYNC", &sync_opcode, &sync_event, &sync_error)) {
		return 0;
	} else {
		xcb_generic_error_t * err;
		xcb_sync_initialize_cookie_t ck = xcb_sync_initialize(dpy,
				XCB_SYNC_MAJOR_VERSION, XCB_SYNC_MINOR_VERSION);
		xcb_sync_initialize_reply_t * r = xcb_sync_initialize_reply(dpy, ck,
				&err);

		if (r == 0 || err != 0)
			return 0;

		printf("SYNC Extension version %d.%d found\n", r->major_version,
				r->minor_version);
		free(r);
		return 1;
	}
}

uint64_t toint(xcb_sync_int64_t * v) {
	return ((uint64_t) v->hi << 32) + (uint64_t) v->lo;
}

struct fixed_xcb_sync_systemcounter_t {
	xcb_sync_counter_t counter;
	xcb_sync_int64_t resolution;
	uint16_t name_len;
}__attribute__((packed));
// the name just follow the _packed_ header.

int sizeof_entry(struct fixed_xcb_sync_systemcounter_t * xdata) {
	unsigned length = xdata->name_len;
	/* padding apply to packed struct fixed_xcb_sync_systemcounter_t + length */
	return (((sizeof(struct fixed_xcb_sync_systemcounter_t) + length) >> 2)
			<< 2) + 4;
}

char * extract_name(struct fixed_xcb_sync_systemcounter_t * entry) {
	char * name = (char*) (entry + 1);
	int length = entry->name_len;
	char * ret = (char*) malloc(sizeof(char) * (length + 1));
	memcpy(ret, name, length);
	ret[length] = 0;
	return ret;
}

int main(void) {
	int screen;
	xcb_connection_t * dpy = xcb_connect(0, &screen);
	check_sync_extension(dpy);

	xcb_generic_error_t * e;
	xcb_sync_list_system_counters_cookie_t ck = xcb_sync_list_system_counters(
			dpy);
	xcb_sync_list_system_counters_reply_t * r =
			xcb_sync_list_system_counters_reply(dpy, ck, &e);
	printf("counter length %u\n", r->counters_len);
	if (r != 0) {
		// the first item is correctly computed by libxcb but I can extract it
		// without xcb_sync_list_system_counters_counters_iterator, thus
		// extract it manually.
		struct fixed_xcb_sync_systemcounter_t * item =
				(struct fixed_xcb_sync_systemcounter_t*) (r + 1);
		for (int i = 0; i < r->counters_len; ++i) {
			char * name = extract_name(item);
			printf("COUNTER_NAME %d = %s, id = %u, resolution = %lu\n", i, name,
					item->counter, toint(&item->resolution));
			free(name);
			/* next item */
			item = (struct fixed_xcb_sync_systemcounter_t*) (((char*) item)
					+ sizeof_entry(item));
		}
		free(r);
	}

	return EXIT_SUCCESS;
}
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to