From 80bcfd86b16b990cac7c172d4f55740b27a1510b Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Mon, 11 May 2020 19:41:16 +0200 Subject: Documentation, use of liberror, and implement libaxl_deallocate_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- LIBAXL_REQUEST_CLEAR_AREA.3 | 86 +++++++++++++++++++++++++++++++++++++++++++++ Makefile | 1 + common.h | 38 +++++++++++++------- libaxl.h | 2 +- libaxl/display-info.h | 2 ++ libaxl_close.c | 2 +- libaxl_create.c | 2 +- libaxl_deallocate_id.c | 52 +++++++++++++++++++++++++++ libaxl_detach.c | 5 +++ libaxl_generate_id.c | 26 ++++++++++++++ libaxl_get_decnet_object.c | 2 +- 11 files changed, 201 insertions(+), 17 deletions(-) create mode 100644 LIBAXL_REQUEST_CLEAR_AREA.3 create mode 100644 libaxl_deallocate_id.c diff --git a/LIBAXL_REQUEST_CLEAR_AREA.3 b/LIBAXL_REQUEST_CLEAR_AREA.3 new file mode 100644 index 0000000..1957ce7 --- /dev/null +++ b/LIBAXL_REQUEST_CLEAR_AREA.3 @@ -0,0 +1,86 @@ +.TH LIBAXL_REQUEST_CLEAR_AREA 3 libaxl +.SH NAME +LIBAXL_REQUEST_CLEAR_AREA - Restore background +.SH SYNOPSIS +.nf +#include + +#define LIBAXL_REQUEST_CLEAR_AREA 61 +struct libaxl_request_clear_area { + uint8_t \fIopcode\fP; + libaxl_bool_t \fIexposures\fP; + uint16_t \fI_request_length\fP; + libaxl_window_t \fIwindow\fP; + int16_t \fIx\fP; + int16_t \fIy\fP; + uint16_t \fIwidth\fP; + uint16_t \fIheight\fP; +}; +.fi +.SH DESCRIPTION +The display server shall redraw the window's, +whose ID is specified in the +.I window +field, background in the rectangle specified +by the +.IR x , +.IR y , +.IR width , +and +.IR height . +.PP +The +.I x +and +.I y +fields specify the rectangles top left corner +as pixels offset right of and down from the +window's top left corner. The +.I width +and +.I height +fields specify the width and height, in +pixels, of the rectangle, however the +specified +.I width +is 0, than the rectangle stretches to the +right edge of the window, and if the specified +.I height +is 0, than the rectangle stretches to the +bottom edge of the window. +.PP +If the +.I exposures +field is set to +.IR LIBAXL_TRUE , +one or more +.I LIBAXL_EVENT_EXPOSE +events are generated for regions of the rectangle +that are either visible or are being retained in +a backing store. +.PP +The value of the +.I opcode +field shall be +.I LIBAXL_REQUEST_CLEAR_AREA +to signify that the request is of the +request described in this document. +.PP +Other fields are filled in automatically by the +.BR libaxl_send_request (3) +function. +.SH ERRORS +.TP +.BR LIBAXL_ERROR_MATCH (3) +The window with the specified window ID +is an input-only window. +.TP +.BR LIBAXL_ERROR_VALUE (3) +TODO \" LIBAXL_ERROR_VALUE +.TP +.BR LIBAXL_ERROR_WINDOW (3) +The specified window ID does not exist. +.SH REPLIES +None +.SH SEE ALSO +.BR libaxl_send_request (3) diff --git a/Makefile b/Makefile index 4f1114e..720bf58 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ OBJ =\ libaxl_context_create.o\ libaxl_context_free.o\ libaxl_create.o\ + libaxl_deallocate_id.o\ libaxl_detach.o\ libaxl_fileno.o\ libaxl_flush.o\ diff --git a/common.h b/common.h index e57fd78..3d76d23 100644 --- a/common.h +++ b/common.h @@ -31,6 +31,7 @@ # include #else # if defined(NO_LIBERROR) +# define __checked_int(X, _FUN) X # define __checked_ptr(X, _FUN) X # define __checked_ssize_t(X, _FUN) X # else @@ -42,10 +43,14 @@ liberror_set_error_errno(strerror(errno), func, errno);\ return ret;\ } +DEFINE_CHECKED(int, __checked_int) DEFINE_CHECKED(void *, __checked_ptr) DEFINE_CHECKED(ssize_t, __checked_ssize_t) # endif +# define liberror_snprintf(...) __checked_int(snprintf(__VA_ARGS__), "snprintf") +# define liberror_close(FD) __checked_int(close(FD), "close") # define liberror_malloc(N) __checked_ptr(malloc(N), "malloc") +# define liberror_calloc(N, M) __checked_ptr(calloc(N, M), "calloc") # define liberror_realloc(P, N) __checked_ptr(realloc(P, N), "realloc") # define liberror_send(FD, B, N, F, _NAM) __checked_ssize_t(send(FD, B, N, F), "send") # define liberror_recv(FD, B, N, F, _NAM) __checked_ssize_t(recv(FD, B, N, F), "recv") @@ -55,21 +60,28 @@ DEFINE_CHECKED(ssize_t, __checked_ssize_t) #define X_TCP_PORT 6000 +struct id_pool { + uint32_t first; + uint32_t last; + struct id_pool *next; +}; + struct libaxl_connection { - int fd; - uint16_t last_seqnum; + int fd; + uint16_t last_seqnum; LIBAXL_CONNECTION_RWLOCK; - LIBAXL_CONTEXT *pending_out; - size_t in_progress; - size_t in_buf_size; - char *in_buf; - uint32_t xid_base; - uint32_t xid_max; - uint32_t xid_shift; - volatile _Atomic uint32_t xid_last; - uint8_t request_map[1UL << 16]; - struct libaxl_display_info info; - char *info_buf; + LIBAXL_CONTEXT *pending_out; + size_t in_progress; + size_t in_buf_size; + char *in_buf; + uint32_t xid_base; + uint32_t xid_max; + uint32_t xid_shift; + volatile _Atomic uint32_t xid_last; + struct id_pool *_Atomic volatile xid_pool; + uint8_t request_map[1UL << 16]; + struct libaxl_display_info info; + char *info_buf; }; struct libaxl_context { diff --git a/libaxl.h b/libaxl.h index d9b3d26..fd0c9c1 100644 --- a/libaxl.h +++ b/libaxl.h @@ -194,7 +194,7 @@ libaxl_id_t libaxl_generate_id(LIBAXL_CONTEXT *); * @return 0 on success, a negative libaxl error code on failure */ _LIBAXL_GCC_ONLY(__attribute__((__nonnull__))) -int libaxl_deallocate_id(LIBAXL_CONTEXT *, libaxl_id_t); /* TODO implement */ +int libaxl_deallocate_id(LIBAXL_CONTEXT *, libaxl_id_t); /** * Send a request to the display server diff --git a/libaxl/display-info.h b/libaxl/display-info.h index 66a39d5..91ceac2 100644 --- a/libaxl/display-info.h +++ b/libaxl/display-info.h @@ -305,6 +305,8 @@ struct libaxl_display_info { /** * The default screen + * + * `NULL` if the specified default screen does not exist */ const struct libaxl_screen *default_screen; }; diff --git a/libaxl_close.c b/libaxl_close.c index 4d9c488..8964f95 100644 --- a/libaxl_close.c +++ b/libaxl_close.c @@ -4,5 +4,5 @@ int libaxl_close(LIBAXL_CONNECTION *conn) { - return close(libaxl_detach(conn)); + return liberror_close(libaxl_detach(conn)); } diff --git a/libaxl_create.c b/libaxl_create.c index 5c78c27..3d6d7b6 100644 --- a/libaxl_create.c +++ b/libaxl_create.c @@ -5,7 +5,7 @@ LIBAXL_CONNECTION * libaxl_create(int fd) { LIBAXL_CONNECTION *conn; - conn = calloc(1, sizeof(*conn)); + conn = liberror_calloc(1, sizeof(*conn)); if (conn) { conn->fd = fd; atomic_init(&conn->xid_last, 0); diff --git a/libaxl_deallocate_id.c b/libaxl_deallocate_id.c new file mode 100644 index 0000000..0a27de0 --- /dev/null +++ b/libaxl_deallocate_id.c @@ -0,0 +1,52 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +int +libaxl_deallocate_id(LIBAXL_CONTEXT *ctx, libaxl_id_t id) +{ + LIBAXL_CONNECTION *conn = ctx->conn; + struct id_pool *pool = NULL, *node; + uint32_t inc = (uint32_t)1 << conn->xid_shift; + int ret = 0; + + pool = atomic_exchange(&conn->xid_pool, pool); + if (pool) { + for (node = pool;; node = node->next) { + if (id + inc == node->first) { + node->first = id; + goto out; + } else if (node->last + inc == id) { + node->last = id; + goto out; + } + if (!node->next) + break; + } + node->next = liberror_malloc(sizeof(*node->next)); + if (node->next) { + node->next->first = id; + node->next->last = id; + atomic_init(&node->next->next, NULL); + } else { + ret = -1; + } + } else { + pool = liberror_malloc(sizeof(*pool)); + if (pool) { + pool->first = id; + pool->last = id; + atomic_init(&pool->next, NULL); + } else { + ret = -1; + } + } + +out: + while ((pool = atomic_exchange(&conn->xid_pool, pool))) { + for (node = pool; node->next; node = node->next); + node->next = atomic_exchange(&conn->xid_pool, NULL); + } + + return ret; +} + diff --git a/libaxl_detach.c b/libaxl_detach.c index c4a0a21..72343a9 100644 --- a/libaxl_detach.c +++ b/libaxl_detach.c @@ -6,11 +6,16 @@ libaxl_detach(LIBAXL_CONNECTION *conn) { int fd = conn->fd; LIBAXL_CONTEXT *ctx; + struct id_pool *pool, *next_pool; while (conn->pending_out) { ctx = conn->pending_out; conn->pending_out = ctx->next_pending_out; libaxl_context_free(ctx); } + for (pool = atomic_load(&conn->xid_pool); pool; pool = next_pool) { + next_pool = pool->next; + free(pool); + } free(conn->in_buf); free(conn->info_buf); free(conn); diff --git a/libaxl_generate_id.c b/libaxl_generate_id.c index 232ef4d..91b5aa6 100644 --- a/libaxl_generate_id.c +++ b/libaxl_generate_id.c @@ -5,8 +5,34 @@ libaxl_id_t libaxl_generate_id(LIBAXL_CONTEXT *ctx) { LIBAXL_CONNECTION *conn = ctx->conn; + struct id_pool *pool = NULL, *next, *last; uint32_t id; + pool = atomic_exchange(&conn->xid_pool, pool); + if (pool) { + id = pool->first; + pool->first += (uint32_t)1 << conn->xid_shift; + if (id == pool->last) { + next = pool->next; + if (next) { + free(pool); + pool = next; + } + next = NULL; + if (atomic_compare_exchange_strong(&conn->xid_pool, &next, pool)) + return id; + if (!pool->next) { + free(pool); + return id; + } + } + while ((pool = atomic_exchange(&conn->xid_pool, pool))) { + for (last = pool; last->next; last = last->next); + last->next = atomic_exchange(&conn->xid_pool, NULL); + } + return id; + } + id = atomic_fetch_add(&conn->xid_last, 1); if (id <= conn->xid_max) return (id << conn->xid_shift) | conn->xid_base; diff --git a/libaxl_get_decnet_object.c b/libaxl_get_decnet_object.c index a744fd2..a29d140 100644 --- a/libaxl_get_decnet_object.c +++ b/libaxl_get_decnet_object.c @@ -4,5 +4,5 @@ int libaxl_get_decnet_object(char *buf, size_t size, int display) { - return snprintf(buf, size, "X$X%i", display); + return liberror_snprintf(buf, size, "X$X%i", display); } -- cgit v1.2.3-70-g09d2