aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2020-05-11 19:41:16 +0200
committerMattias Andrée <maandree@kth.se>2020-05-11 19:41:16 +0200
commit80bcfd86b16b990cac7c172d4f55740b27a1510b (patch)
treefbad87ac55543fc5f5563983b516325a1f9e07c6
parentm (diff)
downloadlibaxl-80bcfd86b16b990cac7c172d4f55740b27a1510b.tar.gz
libaxl-80bcfd86b16b990cac7c172d4f55740b27a1510b.tar.bz2
libaxl-80bcfd86b16b990cac7c172d4f55740b27a1510b.tar.xz
Documentation, use of liberror, and implement libaxl_deallocate_id
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--LIBAXL_REQUEST_CLEAR_AREA.386
-rw-r--r--Makefile1
-rw-r--r--common.h38
-rw-r--r--libaxl.h2
-rw-r--r--libaxl/display-info.h2
-rw-r--r--libaxl_close.c2
-rw-r--r--libaxl_create.c2
-rw-r--r--libaxl_deallocate_id.c52
-rw-r--r--libaxl_detach.c5
-rw-r--r--libaxl_generate_id.c26
-rw-r--r--libaxl_get_decnet_object.c2
11 files changed, 201 insertions, 17 deletions
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 <libaxl.h>
+
+#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 <liberror-libc.h>
#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);
}