Skip to content

Commit

Permalink
types, vm: refactor usage of global variables
Browse files Browse the repository at this point in the history
Introduce an extensible private TLS context structure and use it within
libucode to store global state such as active object iterators.

This allows using libucode concurrently in multiple threads without
unintentionally sharing global state among them.

Also adjust the signal dispatching setup logic in `uc_vm_init()` to only
enable signal handling if no other VM in the same thread already handles
signals.

Suggested-by: Isaac de Wolff <[email protected]>
[squash commits, move signal handler vm pointer and object iterator list
 into common extensible TLS context, whitespace and naming adjustments,
 extended signal setup logic]
Signed-off-by: Jo-Philipp Wich <[email protected]>
  • Loading branch information
jow- committed Dec 2, 2024
1 parent 590c846 commit 0e09c26
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
18 changes: 13 additions & 5 deletions include/ucode/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ typedef struct {

uc_declare_vector(uc_resource_types_t, uc_resource_type_t *);


/* Object iteration */

extern uc_list_t uc_object_iterators;

typedef struct {
uc_list_t list;
struct lh_table *table;
Expand Down Expand Up @@ -270,6 +265,19 @@ uc_search_path_free(uc_search_path_t *search_path) {
}


/* TLS data */

typedef struct {
/* VM owning installed signal handlers */
uc_vm_t *signal_handler_vm;

/* Object iteration */
uc_list_t object_iterators;
} uc_thread_context_t;

__hidden uc_thread_context_t *uc_thread_context_get(void);


/* VM definitions */

typedef enum {
Expand Down
26 changes: 18 additions & 8 deletions types.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@
#include "ucode/vm.h"
#include "ucode/program.h"

uc_list_t uc_object_iterators = {
.prev = &uc_object_iterators,
.next = &uc_object_iterators
};

static char *uc_default_search_path[] = { LIB_SEARCH_PATH };

uc_parse_config_t uc_default_parse_config = {
Expand Down Expand Up @@ -898,7 +893,7 @@ ucv_array_length(uc_value_t *uv)
static void
ucv_free_object_entry(struct lh_entry *entry)
{
uc_list_foreach(item, &uc_object_iterators) {
uc_list_foreach(item, &uc_thread_context_get()->object_iterators) {
uc_object_iterator_t *iter = (uc_object_iterator_t *)item;

if (iter->u.pos == entry)
Expand Down Expand Up @@ -955,7 +950,7 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)

/* insert will rehash table, backup affected iterator states */
if (rehash) {
uc_list_foreach(item, &uc_object_iterators) {
uc_list_foreach(item, &uc_thread_context_get()->object_iterators) {
uc_object_iterator_t *iter = (uc_object_iterator_t *)item;

if (iter->table != object->table)
Expand All @@ -979,7 +974,7 @@ ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val)

/* restore affected iterator state pointer after rehash */
if (rehash) {
uc_list_foreach(item, &uc_object_iterators) {
uc_list_foreach(item, &uc_thread_context_get()->object_iterators) {
uc_object_iterator_t *iter = (uc_object_iterator_t *)item;

if (iter->table != object->table)
Expand Down Expand Up @@ -2478,3 +2473,18 @@ uc_search_path_init(uc_search_path_t *search_path)
for (i = 0; i < ARRAY_SIZE(uc_default_search_path); i++)
uc_vector_push(search_path, xstrdup(uc_default_search_path[i]));
}


static __thread uc_thread_context_t *tls_ctx;

uc_thread_context_t *
uc_thread_context_get(void)
{
if (tls_ctx == NULL) {
tls_ctx = xalloc(sizeof(*tls_ctx));
tls_ctx->object_iterators.prev = &tls_ctx->object_iterators;
tls_ctx->object_iterators.next = &tls_ctx->object_iterators;
}

return tls_ctx;
}
28 changes: 18 additions & 10 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,37 +145,44 @@ uc_vm_alloc_global_scope(uc_vm_t *vm)
static void
uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex);

static uc_vm_t *signal_handler_vm;

static void
uc_vm_signal_handler(int sig)
{
assert(signal_handler_vm);
uc_vm_t *vm = uc_thread_context_get()->signal_handler_vm;

assert(vm);

uc_vm_signal_raise(signal_handler_vm, sig);
uc_vm_signal_raise(vm, sig);
}

static void
uc_vm_signal_handlers_setup(uc_vm_t *vm)
{
uc_thread_context_t *tctx;

memset(&vm->signal, 0, sizeof(vm->signal));

vm->signal.sigpipe[0] = -1;
vm->signal.sigpipe[1] = -1;

if (!vm->config->setup_signal_handlers)
if (vm->config->setup_signal_handlers)
return;

if (pipe2(vm->signal.sigpipe, O_CLOEXEC | O_NONBLOCK) != 0)
tctx = uc_thread_context_get();

if (tctx->signal_handler_vm)
return;

signal_handler_vm = vm;
if (pipe2(vm->signal.sigpipe, O_CLOEXEC | O_NONBLOCK) != 0)
return;

vm->signal.handler = ucv_array_new_length(vm, UC_SYSTEM_SIGNAL_COUNT);

vm->signal.sa.sa_handler = uc_vm_signal_handler;
vm->signal.sa.sa_flags = SA_RESTART | SA_ONSTACK;
sigemptyset(&vm->signal.sa.sa_mask);

tctx->signal_handler_vm = vm;
}

void uc_vm_init(uc_vm_t *vm, uc_parse_config_t *config)
Expand Down Expand Up @@ -778,18 +785,19 @@ uc_vm_exception_tostring(uc_vm_t *vm, size_t nargs)
return message ? ucv_get(message) : ucv_string_new("Exception");
}

static uc_value_t *exception_prototype = NULL;

static uc_value_t *
uc_vm_exception_new(uc_vm_t *vm, uc_exception_type_t type, const char *message, uc_value_t *stacktrace)
{
uc_value_t *exception_prototype = uc_vm_registry_get(vm, "vm.exception.proto");
uc_value_t *exo;

if (exception_prototype == NULL) {
exception_prototype = ucv_object_new(vm);

ucv_object_add(exception_prototype, "tostring",
ucv_cfunction_new("tostring", uc_vm_exception_tostring));

uc_vm_registry_set(vm, "vm.exception.proto", exception_prototype);
}

exo = ucv_object_new(vm);
Expand Down Expand Up @@ -2222,7 +2230,7 @@ uc_vm_object_iterator_next(uc_vm_t *vm, uc_vm_insn_t insn,
iter->table = obj->table;
iter->u.pos = obj->table->head;

uc_list_insert(&uc_object_iterators, &iter->list);
uc_list_insert(&uc_thread_context_get()->object_iterators, &iter->list);
}
else if (ucv_type(k) == UC_RESOURCE &&
res->type == &uc_vm_object_iterator_type && res->data != NULL) {
Expand Down

0 comments on commit 0e09c26

Please sign in to comment.