Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keymap compiler server #536

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -512,6 +512,19 @@ if build_tools
c_args: ['-DENABLE_PRIVATE_APIS'],
include_directories: [include_directories('src', 'include')],
install: false)
thread_dep = dependency('threads', required: false)
if thread_dep.found() and cc.has_header('sys/un.h')
# The same tool again, but for batch processing.
executable('compile-keymap-server',
'tools/compile-keymap-server.c',
'src/xkbcomp/cache.c',
'src/xkbcomp/cache.h',
libxkbcommon_sources,
dependencies: [tools_dep, thread_dep],
c_args: ['-DENABLE_KEYMAP_SOCKET', '-DENABLE_KEYMAP_CACHE'],
include_directories: [include_directories('src', 'include')],
install: false)
endif

# Tool: compose
executable('xkbcli-compile-compose',
109 changes: 109 additions & 0 deletions src/atom.c
Original file line number Diff line number Diff line change
@@ -80,6 +80,9 @@
#include "atom.h"
#include "darray.h"
#include "utils.h"
#ifdef ENABLE_KEYMAP_CACHE
#include <stdatomic.h>
#endif

/* FNV-1a (http://www.isthe.com/chongo/tech/comp/fnv/). */
static inline uint32_t
@@ -95,6 +98,7 @@ hash_buf(const char *string, size_t len)
return hash;
}

#ifndef ENABLE_KEYMAP_CACHE
/*
* The atom table is an insert-only linear probing hash table
* mapping strings to atoms. Another array maps the atoms to
@@ -191,3 +195,108 @@ atom_intern(struct atom_table *table, const char *string, size_t len, bool add)

assert(!"couldn't find an empty slot during probing");
}

#else

struct atom_table {
size_t size;
_Atomic(char *) *strings;
};

struct atom_table *
atom_table_new(size_t size_log2)
{
struct atom_table *table = calloc(1, sizeof(*table));
if (!table)
return NULL;
size_t size = 1u << size_log2;
table->size = size;
table->strings = calloc(size, sizeof(char*));
return table;
}

void
atom_table_free(struct atom_table *table)
{
if (!table)
return;

size_t count = 0;
for (size_t k = 0 ; k < table->size; k++) {
if (table->strings[k]) {
free(table->strings[k]);
count++;
}
}
free(table->strings);
free(table);
}


xkb_atom_t
atom_intern(struct atom_table *table, const char *string, size_t len, bool add)
{

uint32_t hash = hash_buf(string, len);
char *new_value = NULL;
for (size_t i = 0; i < table->size; i++) {
xkb_atom_t index_pos = (hash + i) & (table->size - 1);
if (index_pos == XKB_ATOM_NONE)
continue;

char *existing_value = atomic_load_explicit(&table->strings[index_pos],
memory_order_acquire);

/* Check if there is a value at the current index */
if (!existing_value) {
/* No value defined. Check if we are allowed to add one */
if (!add)
return XKB_ATOM_NONE;

/*
* Prepare addition: duplicate string.
* Warning: This may not be our first attempt!
*/
if (!new_value)
new_value = strndup(string, len);
if (!new_value) {
/* Failed memory allocation */
// FIXME: error handling?
return XKB_ATOM_NONE;
}
/* Try to register a new entry */
if (atomic_compare_exchange_strong_explicit(
&table->strings[index_pos], &existing_value, new_value,
memory_order_release, memory_order_acquire)) {
return index_pos;
}
/*
* We were not fast enough to take the spot.
* But maybe the newly added value is our value, so read it again.
*/
existing_value = atomic_load_explicit(&table->strings[index_pos],
memory_order_acquire);
}

/* Check the value are equal */
if (strncmp(existing_value, string, len) == 0 &&
existing_value[len] == '\0') {
/* We may have tried unsuccessfully to add the string */
free(new_value);
return index_pos;
}
/* Hash collision: try next atom */
}

free(new_value);
assert(!"couldn't find an empty slot during probing");
}

const char *
atom_text(struct atom_table *table, xkb_atom_t atom)
{
assert(atom < table->size);
return table->strings[atom];
}

#endif
5 changes: 5 additions & 0 deletions src/atom.h
Original file line number Diff line number Diff line change
@@ -30,8 +30,13 @@ typedef uint32_t xkb_atom_t;

struct atom_table;

#ifdef ENABLE_KEYMAP_CACHE
struct atom_table *
atom_table_new(size_t size);
#else
struct atom_table *
atom_table_new(void);
#endif

void
atom_table_free(struct atom_table *table);
10 changes: 8 additions & 2 deletions src/context.c
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdatomic.h>

#include "xkbcommon/xkbcommon.h"
#include "utils.h"
@@ -189,7 +190,7 @@ xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx)
XKB_EXPORT struct xkb_context *
xkb_context_ref(struct xkb_context *ctx)
{
ctx->refcnt++;
atomic_fetch_add(&ctx->refcnt, 1);
return ctx;
}

@@ -200,7 +201,7 @@ xkb_context_ref(struct xkb_context *ctx)
XKB_EXPORT void
xkb_context_unref(struct xkb_context *ctx)
{
if (!ctx || --ctx->refcnt > 0)
if (!ctx || atomic_fetch_sub(&ctx->refcnt, 1) > 1)
return;

free(ctx->x11_atom_cache);
@@ -312,7 +313,12 @@ xkb_context_new(enum xkb_context_flags flags)
return NULL;
}

#ifdef ENABLE_KEYMAP_CACHE
/* NOTE: Size should be adusted to deal with xkeyboard-config database */
ctx->atom_table = atom_table_new(14);
#else
ctx->atom_table = atom_table_new();
#endif
if (!ctx->atom_table) {
xkb_context_unref(ctx);
return NULL;
13 changes: 12 additions & 1 deletion src/context.h
Original file line number Diff line number Diff line change
@@ -26,11 +26,18 @@
#ifndef CONTEXT_H
#define CONTEXT_H

#include <stdatomic.h>

#include "xkbcommon/xkbcommon.h"
#include "atom.h"
#include "messages-codes.h"
#include "src/utils.h"
#ifdef ENABLE_KEYMAP_CACHE
#include "xkbcomp/cache.h"
#endif

struct xkb_context {
int refcnt;
atomic_int refcnt;

ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx,
enum xkb_log_level level,
@@ -55,6 +62,10 @@ struct xkb_context {

unsigned int use_environment_names : 1;
unsigned int use_secure_getenv : 1;

#ifdef ENABLE_KEYMAP_CACHE
struct xkb_keymap_cache *keymap_cache;
#endif
};

char *
Loading