From 9e46b02ff9c5dca4b2724f27583bb513c6e5a1fd Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 29 Aug 2010 00:13:52 -0400 Subject: [PATCH 1/2] add "dynamic request marshaler" suitable for some basic benchmarking and not much else Only CreateWindow is supported, for example. This is not "introspection"; it is just a byte description of the marshaling steps. Presumably, introspection-based marshaling using some more versatile description of the request would be a little slower than this. (The ideal versatile introspection would map 1-1 to the XML files in most ways, probably.) The idea of this is just to be able to see how much size win or speed lose dynamic marshaling would impose. --- src/Makefile.am | 4 +- src/xcb_dyn.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/xcbdyn.h | 71 ++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 src/xcb_dyn.c create mode 100644 src/xcbdyn.h diff --git a/src/Makefile.am b/src/Makefile.am index f0bdeaa..2606e0e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(NEEDED_CFLAGS) $(XDMCP_CFLAGS) libxcb_la_LIBADD = $(NEEDED_LIBS) $(XDMCP_LIBS) libxcb_la_SOURCES = \ xcb_conn.c xcb_out.c xcb_in.c xcb_ext.c xcb_xid.c \ - xcb_list.c xcb_util.c xcb_auth.c c_client.py + xcb_list.c xcb_util.c xcb_auth.c xcb_dyn.c c_client.py nodist_libxcb_la_SOURCES = xproto.c bigreq.c xc_misc.c # Explanation for -version-info: @@ -210,7 +210,7 @@ endif EXTHEADERS=$(EXTSOURCES:.c=.h) -xcbinclude_HEADERS = xcb.h xcbext.h +xcbinclude_HEADERS = xcb.h xcbext.h xcbdyn.h nodist_xcbinclude_HEADERS = $(EXTHEADERS) noinst_HEADERS = xcbint.h diff --git a/src/xcb_dyn.c b/src/xcb_dyn.c new file mode 100644 index 0000000..8090e95 --- /dev/null +++ b/src/xcb_dyn.c @@ -0,0 +1,129 @@ +/* -*- mode: C; c-file-style: "k&r"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + * Copyright (C) 2010 Havoc Pennington + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors or their + * institutions shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the authors. + */ +#include +#include +#include +#include + +#include "xcbdyn.h" +#include "xcbext.h" +#include "xcbint.h" + +xcb_void_cookie_t +xcb_send_request_dynamic(xcb_connection_t *c, int flags, + xcb_extension_t *ext, + const xcb_request_op_t *ops, + ...) +{ + va_list args; + char *buf; + struct iovec *parts_base; + struct iovec *parts; + xcb_void_cookie_t cookie; + xcb_protocol_request_t xcb_req; + + xcb_req.ext = ext; + xcb_req.opcode = ops[0]; + xcb_req.isvoid = ops[1]; + ops += 2; + + va_start(args, ops); + + while (1) + { + + switch (*ops) + { + case XCB_REQUEST_OP_NULL: + parts->iov_base = NULL; + parts->iov_len = 0; + goto done; + + case XCB_REQUEST_OP_BUFS_COUNT: + ++ops; + xcb_req.count = *ops; + parts_base = alloca(sizeof(struct iovec) * (xcb_req.count + 2)); + parts = parts_base + 2; + break; + + case XCB_REQUEST_OP_START_BUF: + ++ops; + parts->iov_len = *ops; + buf = alloca(parts->iov_len); + parts->iov_base = buf; + break; + + case XCB_REQUEST_OP_END_BUF: + parts++; + break; + + case XCB_REQUEST_OP_HEADER: + buf += 4; + break; + + case XCB_REQUEST_OP_HEADER_WITH_PAD_FIELD: + buf[1] = (uint8_t) va_arg(args, uint32_t); /* varargs get bumped up to 32 */ + buf += 4; + break; + + case XCB_REQUEST_OP_FIELD_8: + *buf++ = (uint8_t) va_arg(args, uint32_t); /* varargs get bumped up to 32 */ + break; + + case XCB_REQUEST_OP_FIELD_16: + *((uint16_t*)buf) = (uint16_t) va_arg(args, uint32_t); /* varargs get bumped up to 32 */ + buf += 2; + break; + + case XCB_REQUEST_OP_FIELD_32: + *((uint32_t*)buf) = va_arg(args, uint32_t); + buf += 4; + break; + + case XCB_REQUEST_OP_FIELD_32_END_BUF_POPCOUNTED_ARRAY_32: { + uint32_t mask = va_arg(args, uint32_t); + *((uint32_t*)buf) = mask; + buf += 4; + parts++; + parts->iov_base = va_arg(args, uint32_t*); + parts->iov_len = xcb_popcount(mask) * sizeof(uint32_t); + parts++; + /* no padding possible since we're 32 */ + } + break; + } + + ++ops; + } + +done: + va_end(args); + + cookie.sequence = xcb_send_request(c, flags, &parts_base[2], &xcb_req); + return cookie; +} diff --git a/src/xcbdyn.h b/src/xcbdyn.h new file mode 100644 index 0000000..21f7d93 --- /dev/null +++ b/src/xcbdyn.h @@ -0,0 +1,71 @@ +/* -*- mode: C; c-file-style: "k&r"; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ +/* + * Copyright (C) 2010 Havoc Pennington + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors or their + * institutions shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization from the authors. + */ + +#ifndef __XCBDYN_H +#define __XCBDYN_H + +#include "xcbext.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* xcb_dyn.c */ + +#define XCB_PADDING(length) (-(length) & 3) + +/* A "request op" tells us a step to take to marshal a request from C + * function parameters to wire format. To marshal a request we + * execute all its request ops. Ops can have arguments which appear + * after them in the ops array. + */ +typedef uint8_t xcb_request_op_t; + +typedef enum { + XCB_REQUEST_OP_NULL, + XCB_REQUEST_OP_BUFS_COUNT, + XCB_REQUEST_OP_START_BUF, + XCB_REQUEST_OP_END_BUF, + XCB_REQUEST_OP_HEADER, + XCB_REQUEST_OP_HEADER_WITH_PAD_FIELD, + XCB_REQUEST_OP_FIELD_8, + XCB_REQUEST_OP_FIELD_16, + XCB_REQUEST_OP_FIELD_32, + XCB_REQUEST_OP_FIELD_32_END_BUF_POPCOUNTED_ARRAY_32 +} xcb_request_op_tag_t; + +xcb_void_cookie_t xcb_send_request_dynamic(xcb_connection_t *c, int flags, + xcb_extension_t *ext, + const xcb_request_op_t *ops, + ...); + +#ifdef __cplusplus +} +#endif + +#endif -- 1.7.0.4