Skip to content

Commit 3ac1e62

Browse files
authored
Merge pull request #17120 from JuliaLang/yyc/threads/mac
Optimize TLS access on mac and windows
2 parents abbd32c + 09a0be0 commit 3ac1e62

File tree

3 files changed

+77
-10
lines changed

3 files changed

+77
-10
lines changed

src/julia_threads.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,9 @@ STATIC_INLINE int8_t jl_gc_state_set(jl_tls_states_t *ptls,
366366
}
367367
#else // ifndef JULIA_ENABLE_THREADING
368368
typedef jl_tls_states_t *(*jl_get_ptls_states_func)(void);
369+
#if !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_)
369370
JL_DLLEXPORT void jl_set_ptls_states_getter(jl_get_ptls_states_func f);
371+
#endif
370372
// Make sure jl_gc_state() is always a rvalue
371373
#define jl_gc_state(ptls) ((int8_t)ptls->gc_state)
372374
STATIC_INLINE int8_t jl_gc_state_set(jl_tls_states_t *ptls,

src/threading.c

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,82 @@ extern "C" {
3030
#include "threading.h"
3131

3232
#ifdef JULIA_ENABLE_THREADING
33+
# if defined(_OS_DARWIN_)
34+
// Mac doesn't seem to have static TLS model so the runtime TLS getter
35+
// registration will only add overhead to TLS access. The `__thread` variables
36+
// are emulated with `pthread_key_t` so it is actually faster to use it directly.
37+
static pthread_key_t jl_tls_key;
38+
39+
__attribute__((constructor)) void jl_mac_init_tls(void)
40+
{
41+
pthread_key_create(&jl_tls_key, NULL);
42+
}
43+
44+
JL_DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void)
45+
{
46+
void *ptls = pthread_getspecific(jl_tls_key);
47+
if (__unlikely(!ptls)) {
48+
ptls = calloc(1, sizeof(jl_tls_states_t));
49+
pthread_setspecific(jl_tls_key, ptls);
50+
}
51+
return (jl_tls_states_t*)ptls;
52+
}
53+
54+
// This is only used after the tls is already initialized on the thread
55+
static JL_CONST_FUNC jl_tls_states_t *jl_get_ptls_states_fast(void)
56+
{
57+
return (jl_tls_states_t*)pthread_getspecific(jl_tls_key);
58+
}
59+
60+
jl_get_ptls_states_func jl_get_ptls_states_getter(void)
61+
{
62+
// for codegen
63+
return &jl_get_ptls_states_fast;
64+
}
65+
# elif defined(_OS_WINDOWS_)
66+
// Apparently windows doesn't have a static TLS model (or one that can be
67+
// reliably used from a shared library) either..... Use `TLSAlloc` instead.
68+
69+
static DWORD jl_tls_key;
70+
71+
// Put this here for now. We can move this out later if we find more use for it.
72+
BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle, IN DWORD nReason,
73+
IN LPVOID Reserved)
74+
{
75+
switch (nReason) {
76+
case DLL_PROCESS_ATTACH:
77+
jl_tls_key = TlsAlloc();
78+
assert(jl_tls_key != TLS_OUT_OF_INDEXES);
79+
// Fall through
80+
case DLL_THREAD_ATTACH:
81+
TlsSetValue(jl_tls_key, calloc(1, sizeof(jl_tls_states_t)));
82+
break;
83+
case DLL_THREAD_DETACH:
84+
free(TlsGetValue(jl_tls_key));
85+
TlsSetValue(jl_tls_key, NULL);
86+
break;
87+
case DLL_PROCESS_DETACH:
88+
free(TlsGetValue(jl_tls_key));
89+
TlsFree(jl_tls_key);
90+
break;
91+
}
92+
}
93+
94+
JL_DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void)
95+
{
96+
return TlsGetValue(jl_tls_key);
97+
}
98+
99+
jl_get_ptls_states_func jl_get_ptls_states_getter(void)
100+
{
101+
// for codegen
102+
return &jl_get_ptls_states;
103+
}
104+
# else
33105
// fallback provided for embedding
34106
static JL_CONST_FUNC jl_tls_states_t *jl_get_ptls_states_fallback(void)
35107
{
36-
# if !defined(_COMPILER_MICROSOFT_)
37108
static __thread jl_tls_states_t tls_states;
38-
# else
39-
static __declspec(thread) jl_tls_states_t tls_states;
40-
# endif
41109
return &tls_states;
42110
}
43111
static jl_tls_states_t *jl_get_ptls_states_init(void);
@@ -78,6 +146,7 @@ jl_get_ptls_states_func jl_get_ptls_states_getter(void)
78146
// for codegen
79147
return jl_tls_states_cb;
80148
}
149+
# endif
81150
#else
82151
JL_DLLEXPORT jl_tls_states_t jl_tls_states;
83152
JL_DLLEXPORT JL_CONST_FUNC jl_tls_states_t *(jl_get_ptls_states)(void)

ui/repl.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,10 @@
3434
extern "C" {
3535
#endif
3636

37-
#ifdef JULIA_ENABLE_THREADING
37+
#if defined(JULIA_ENABLE_THREADING) && !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_)
3838
static JL_CONST_FUNC jl_tls_states_t *jl_get_ptls_states_static(void)
3939
{
40-
# if !defined(_COMPILER_MICROSOFT_)
4140
static __attribute__((tls_model("local-exec"))) __thread jl_tls_states_t tls_states;
42-
# else
43-
static __declspec(thread) jl_tls_states_t tls_states;
44-
# endif
4541
return &tls_states;
4642
}
4743
#endif
@@ -660,7 +656,7 @@ int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
660656
argv[i] = (wchar_t*)arg;
661657
}
662658
#endif
663-
#ifdef JULIA_ENABLE_THREADING
659+
#if defined(JULIA_ENABLE_THREADING) && !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_)
664660
// We need to make sure this function is called before any reference to
665661
// TLS variables. Since the compiler is free to move calls to
666662
// `jl_get_ptls_states()` around, we should avoid referencing TLS

0 commit comments

Comments
 (0)