diff --git a/src/6model/serialization.c b/src/6model/serialization.c index 6fe74f1159..e1062d016f 100644 --- a/src/6model/serialization.c +++ b/src/6model/serialization.c @@ -508,9 +508,9 @@ static void write_array_str(MVMThreadContext *tc, MVMSerializationWriter *writer } /* Writes a hash where each key is a MVMString and each value a variant reference. */ -static MVMThreadContext *cmp_tc; static int cmp_strings(const void *s1, const void *s2) { - return MVM_string_compare(cmp_tc, *(MVMString **)s1, *(MVMString **)s2); + MVMThreadContext *tc = MVM_get_running_threads_context(); + return MVM_string_compare(tc, *(MVMString **)s1, *(MVMString **)s2); } static void write_hash_str_var(MVMThreadContext *tc, MVMSerializationWriter *writer, MVMObject *hash) { MVMuint32 elems = (MVMuint32)MVM_repr_elems(tc, hash); @@ -526,7 +526,6 @@ static void write_hash_str_var(MVMThreadContext *tc, MVMSerializationWriter *wri MVM_repr_shift_o(tc, iter); keys[i++] = MVM_iterkey_s(tc, (MVMIter *)iter); } - cmp_tc = tc; qsort(keys, elems, sizeof(MVMString*), cmp_strings); for (i = 0; i < elems; i++) { MVM_serialization_write_str(tc, writer, keys[i]); diff --git a/src/core/threads.c b/src/core/threads.c index 9079df8341..6f5ab13309 100644 --- a/src/core/threads.c +++ b/src/core/threads.c @@ -76,6 +76,13 @@ static void start_thread(void *data) { /* Stash thread ID. */ tc->thread_obj->body.native_thread_id = MVM_platform_thread_id(); +#ifndef MVM_THREAD_LOCAL + /* Store this thread's thread context pointer, so that we can retrieve it + * in places where we can't pass it in to, such as the callback function + * used by qsort. */ + uv_key_set(&MVM_running_threads_context_key, tc); +#endif + /* Create a spesh log for this thread, unless it's just going to run C * code (and thus it's a VM internal worker). */ if (REPR(tc->thread_obj->body.invokee)->ID != MVM_REPR_ID_MVMCFunction) diff --git a/src/moar.c b/src/moar.c index 4c13851118..97cda277f3 100644 --- a/src/moar.c +++ b/src/moar.c @@ -87,6 +87,17 @@ MVM_STATIC_INLINE MVMuint64 ptr_hash_64_to_64(MVMuint64 u) { return (MVMuint64)u; } +#ifndef MVM_THREAD_LOCAL +uv_key_t MVM_running_threads_context_key; + +static void +make_uv_key() { + int result = uv_key_create(&MVM_running_threads_context_key); + if (result) + MVM_panic(1, "uv_key_create failed with code %u", result); +} +#endif + /* Create a new instance of the VM. */ MVMInstance * MVM_vm_create_instance(void) { MVMInstance *instance; @@ -98,6 +109,11 @@ MVMInstance * MVM_vm_create_instance(void) { char *dynvar_log; int init_stat; +#ifndef MVM_THREAD_LOCAL + static uv_once_t key_once = UV_ONCE_INIT; + uv_once(&key_once, make_uv_key); +#endif + /* Set up instance data structure. */ instance = MVM_calloc(1, sizeof(MVMInstance)); diff --git a/src/moar.h b/src/moar.h index 73d045dbe9..8b41f9278f 100644 --- a/src/moar.h +++ b/src/moar.h @@ -292,3 +292,14 @@ AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr, AO_t old_val, AO_t * which the other atomic operation macros are used... */ #define MVM_store(addr, new) AO_store_full((volatile AO_t *)(addr), (AO_t)(new)) #define MVM_load(addr) AO_load_full((volatile AO_t *)(addr)) + +#ifndef MVM_THREAD_LOCAL + +/* Fallback to an implememtation using UV's APIs (pretty much pthreads) */ +extern uv_key_t MVM_running_threads_context_key; + +MVM_STATIC_INLINE MVMThreadContext *MVM_get_running_threads_context(void) { + return uv_key_get(&MVM_running_threads_context_key); +} + +#endif