summaryrefslogtreecommitdiffhomepage
path: root/vm.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2024-10-19 16:06:09 +0200
committerJo-Philipp Wich <jo@mein.io>2024-12-02 15:25:39 +0100
commitefeb578065523b2882d71d91f38cd63115928b7a (patch)
tree43017d5d8683168f4a9ca2453fcf3d5f1975d34f /vm.c
parent47b54cf5a4b6166944efa4ee4cd023d73ebe6c3e (diff)
types, vm: refactor usage of global variables
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 <idewolff@vincitech.nl> [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 <jo@mein.io>
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/vm.c b/vm.c
index 9488288..ce9c217 100644
--- a/vm.c
+++ b/vm.c
@@ -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)
@@ -778,11 +785,10 @@ 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) {
@@ -790,6 +796,8 @@ uc_vm_exception_new(uc_vm_t *vm, uc_exception_type_t type, const char *message,
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);
@@ -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) {