summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/ucode/types.h18
-rw-r--r--tests/custom/03_stdlib/60_gc50
-rw-r--r--types.c26
-rw-r--r--vm.c28
4 files changed, 74 insertions, 48 deletions
diff --git a/include/ucode/types.h b/include/ucode/types.h
index 9cd7cfc..85c3eb8 100644
--- a/include/ucode/types.h
+++ b/include/ucode/types.h
@@ -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;
@@ -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 {
diff --git a/tests/custom/03_stdlib/60_gc b/tests/custom/03_stdlib/60_gc
index 28c0d00..44e5d9e 100644
--- a/tests/custom/03_stdlib/60_gc
+++ b/tests/custom/03_stdlib/60_gc
@@ -45,11 +45,11 @@ Returns an object count if the given operation is `count`.
-- End --
-- Expect stdout --
-Count #1: 6
-Count #2: 7
-Count #3: 6
-Count #4: 7
-Count #5: 6
+Count #1: 5
+Count #2: 6
+Count #3: 5
+Count #4: 6
+Count #5: 5
-- End --
@@ -84,24 +84,24 @@ Testing enabling the automatic collector.
-- End --
-- Expect stdout --
-Count #1: 7
-Count #2: 14
-Count #3: 14
-Count #4: 14
-Count #5: 14
-Count #6: 14
-Count #7: 14
-Count #8: 14
-Count #9: 14
-Count #10: 14
-Count #11: 14
-Count #12: 24
-Count #13: 34
-Count #14: 44
-Count #15: 54
-Count #16: 64
-Count #17: 74
-Count #18: 84
-Count #19: 94
-Count #20: 104
+Count #1: 6
+Count #2: 12
+Count #3: 12
+Count #4: 12
+Count #5: 12
+Count #6: 12
+Count #7: 12
+Count #8: 12
+Count #9: 12
+Count #10: 12
+Count #11: 12
+Count #12: 22
+Count #13: 32
+Count #14: 42
+Count #15: 52
+Count #16: 62
+Count #17: 72
+Count #18: 82
+Count #19: 92
+Count #20: 102
-- End --
diff --git a/types.c b/types.c
index 8c30614..5dbf6a8 100644
--- a/types.c
+++ b/types.c
@@ -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 = {
@@ -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)
@@ -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)
@@ -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)
@@ -2481,3 +2476,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;
+}
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) {