Skip to content

Commit

Permalink
Merge pull request #1391 from MoarVM/thread_local-nativecall
Browse files Browse the repository at this point in the history
Implement MVM_nativecall_find_thread_context using MVM_get_running_threads_context
  • Loading branch information
jnthn committed Nov 24, 2020
2 parents ec50786 + 34e0686 commit bc21907
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 76 deletions.
37 changes: 0 additions & 37 deletions src/core/nativecall.c
Expand Up @@ -2,7 +2,6 @@
#ifndef _WIN32
#include <dlfcn.h>
#endif
#include <platform/threads.h>
#include <platform/time.h>

/* Grabs a NativeCall body. */
Expand Down Expand Up @@ -1149,42 +1148,6 @@ void MVM_nativecall_refresh(MVMThreadContext *tc, MVMObject *cthingy) {
}
}

/* Locate the thread that a callback should be run on. */
MVMThreadContext * MVM_nativecall_find_thread_context(MVMInstance *instance) {
MVMint64 wanted_thread_id = MVM_platform_thread_id();
MVMThreadContext *tc = NULL;
while (1) {
uv_mutex_lock(&(instance->mutex_threads));
if (instance->in_gc) {
/* VM is in GC; free lock since the GC will acquire it again to
* clear the in_gc flag, and sleep a bit until it's safe to read
* the threads list. */
uv_mutex_unlock(&(instance->mutex_threads));
MVM_platform_sleep(0.0001);
}
else {
/* Not in GC. If a GC starts while we are reading this, then we
* are holding mutex_threads, and the GC will block on it before
* it gets to a stage where it can move things. */
MVMThread *thread = instance->threads;
while (thread) {
if (thread->body.native_thread_id == wanted_thread_id) {
tc = thread->body.tc;
if (tc)
break;
}
thread = thread->body.next;
}
if (!tc)
MVM_panic(1, "native callback ran on thread (%"PRId64") unknown to MoarVM",
wanted_thread_id);
uv_mutex_unlock(&(instance->mutex_threads));
break;
}
}
return tc;
}

typedef struct ResolverData {
MVMObject *site;
MVMRegister args[1];
Expand Down
14 changes: 13 additions & 1 deletion src/core/nativecall.h
Expand Up @@ -135,7 +135,19 @@ void * MVM_nativecall_unmarshal_cpointer(MVMThreadContext *tc, MVMObject *value,
void * MVM_nativecall_unmarshal_carray(MVMThreadContext *tc, MVMObject *value, MVMint16 unmarshal_kind);
void * MVM_nativecall_unmarshal_vmarray(MVMThreadContext *tc, MVMObject *value, MVMint16 unmarshal_kind);
void * MVM_nativecall_unmarshal_cunion(MVMThreadContext *tc, MVMObject *value, MVMint16 unmarshal_kind);
MVMThreadContext * MVM_nativecall_find_thread_context(MVMInstance *instance);

/* Locate the thread that a callback should be run on. */
MVM_STATIC_INLINE MVMThreadContext * MVM_nativecall_find_thread_context(MVMInstance *instance) {
MVMThreadContext *tc = MVM_get_running_threads_context();

if (!tc)
MVM_panic(1, "native callback ran on thread (%"PRId64") unknown to MoarVM",
MVM_platform_thread_id());

return tc;
}


MVMJitGraph *MVM_nativecall_jit_graph_for_caller_code(
MVMThreadContext *tc,
MVMSpeshGraph *sg,
Expand Down
1 change: 0 additions & 1 deletion src/core/nativecall_libffi.c
@@ -1,5 +1,4 @@
#include "moar.h"
#include <platform/threads.h>

//~ ffi_type * MVM_nativecall_get_ffi_type(MVMThreadContext *tc, MVMuint64 type_id, void **values, MVMuint64 offset) {
ffi_type * MVM_nativecall_get_ffi_type(MVMThreadContext *tc, MVMuint64 type_id) {
Expand Down
33 changes: 33 additions & 0 deletions src/core/threadcontext.h
Expand Up @@ -340,3 +340,36 @@ void MVM_tc_set_ex_release_mutex(MVMThreadContext *tc, uv_mutex_t *mutex);
void MVM_tc_set_ex_release_atomic(MVMThreadContext *tc, AO_t *flag);
void MVM_tc_release_ex_release_mutex(MVMThreadContext *tc);
void MVM_tc_clear_ex_release_mutex(MVMThreadContext *tc);

/* UV always defines this for Win32 but not Unix. Which is fine, as we can probe
* for it on Unix more easily than on Win32. */
#if !defined(MVM_THREAD_LOCAL) && defined(UV_THREAD_LOCAL)
#define MVM_THREAD_LOCAL UV_THREAD_LOCAL
#endif

#ifdef MVM_THREAD_LOCAL

extern MVM_THREAD_LOCAL MVMThreadContext *MVM_running_threads_context;

MVM_STATIC_INLINE MVMThreadContext *MVM_get_running_threads_context(void) {
return MVM_running_threads_context;
}

MVM_STATIC_INLINE void MVM_set_running_threads_context(MVMThreadContext *tc) {
MVM_running_threads_context = tc;
}

#else

/* 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);
}

MVM_STATIC_INLINE void MVM_set_running_threads_context(MVMThreadContext *tc) {
return uv_key_set(&MVM_running_threads_context_key, tc);
}

#endif
1 change: 0 additions & 1 deletion src/core/threads.c
@@ -1,5 +1,4 @@
#include "moar.h"
#include <platform/threads.h>

/* Temporary structure for passing data to thread start. */
typedef struct {
Expand Down
1 change: 0 additions & 1 deletion src/debug/debugserver.c
@@ -1,5 +1,4 @@
#include "moar.h"
#include "platform/threads.h"

#define DEBUGSERVER_MAJOR_PROTOCOL_VERSION 1
#define DEBUGSERVER_MINOR_PROTOCOL_VERSION 2
Expand Down
1 change: 0 additions & 1 deletion src/gc/orchestrate.c
@@ -1,5 +1,4 @@
#include "moar.h"
#include <platform/threads.h>
#include "platform/malloc_trim.h"

/* If we have the job of doing GC for a thread, we add it to our work
Expand Down
1 change: 0 additions & 1 deletion src/moar.c
@@ -1,7 +1,6 @@
#include "platform/memmem.h"
#include "moar.h"
#include "platform/io.h"
#include <platform/threads.h>
#include "platform/random.h"
#include "platform/time.h"
#include "platform/mmap.h"
Expand Down
36 changes: 3 additions & 33 deletions src/moar.h
Expand Up @@ -39,6 +39,9 @@
#include <dyncall_callback.h>
#endif

/* needed in threadcontext.h */
#include <platform/threads.h>

/* forward declarations */
#include "types.h"

Expand Down Expand Up @@ -292,36 +295,3 @@ 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))

/* UV always defines this for Win32 but not Unix. Which is fine, as we can probe
* for it on Unix more easily than on Win32. */
#if !defined(MVM_THREAD_LOCAL) && defined(UV_THREAD_LOCAL)
#define MVM_THREAD_LOCAL UV_THREAD_LOCAL
#endif

#ifdef MVM_THREAD_LOCAL

extern MVM_THREAD_LOCAL MVMThreadContext *MVM_running_threads_context;

MVM_STATIC_INLINE MVMThreadContext *MVM_get_running_threads_context(void) {
return MVM_running_threads_context;
}

MVM_STATIC_INLINE void MVM_set_running_threads_context(MVMThreadContext *tc) {
MVM_running_threads_context = tc;
}

#else

/* 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);
}

MVM_STATIC_INLINE void MVM_set_running_threads_context(MVMThreadContext *tc) {
return uv_key_set(&MVM_running_threads_context_key, tc);
}

#endif

0 comments on commit bc21907

Please sign in to comment.