Skip to content

Commit

Permalink
Re-correct TSAN integration with task switching
Browse files Browse the repository at this point in the history
This reverts commit 15772ba
"Update references to tsan state (#42440)", and fixes integration.

Looks like #36929 got reverted
when trying to simplify the code, but it now isn't legal. Since these
must be inlined in the right point in the runtime call/return context,
use a macro to ensure that.
  • Loading branch information
Keno authored and vtjnash committed Oct 14, 2021
1 parent 5909efa commit 578392a
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 115 deletions.
6 changes: 3 additions & 3 deletions src/gc-stacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ void sweep_stack_pools(void)
_jl_free_stack(ptls2, stkbuf, bufsz);
}
#ifdef _COMPILER_TSAN_ENABLED_
if (t->tsan_state) {
__tsan_destroy_fiber(t->tsan_state);
t->tsan_state = NULL;
if (t->ctx.tsan_state) {
__tsan_destroy_fiber(t->ctx.tsan_state);
t->ctx.tsan_state = NULL;
}
#endif
}
Expand Down
14 changes: 2 additions & 12 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1846,18 +1846,8 @@ typedef struct _jl_task_t {
jl_excstack_t *excstack;
// current exception handler
jl_handler_t *eh;

union {
jl_ucontext_t ctx; // saved thread state
#ifdef _OS_WINDOWS_
jl_ucontext_t copy_stack_ctx;
#else
struct jl_stack_context_t copy_stack_ctx;
#endif
};
#if defined(_COMPILER_TSAN_ENABLED_)
void *tsan_state;
#endif
// saved thread state
jl_ucontext_t ctx;
void *stkbuf; // malloc'd memory (either copybuf or stack)
size_t bufsz; // actual sizeof stkbuf
unsigned int copy_stack:31; // sizeof stack for copybuf
Expand Down
38 changes: 22 additions & 16 deletions src/julia_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ JL_DLLEXPORT void jl_threading_profile(void);

#ifdef _OS_WINDOWS_
#define JL_HAVE_UCONTEXT
typedef win32_ucontext_t jl_ucontext_t;
typedef win32_ucontext_t jl_stack_context_t;
typedef jl_stack_context_t _jl_ucontext_t;
#else
typedef struct {
jl_jmp_buf uc_mcontext;
} jl_stack_context_t;
#if !defined(JL_HAVE_UCONTEXT) && \
!defined(JL_HAVE_ASM) && \
!defined(JL_HAVE_UNW_CONTEXT) && \
Expand All @@ -56,13 +60,8 @@ typedef win32_ucontext_t jl_ucontext_t;
#endif
#endif


struct jl_stack_context_t {
jl_jmp_buf uc_mcontext;
};

#if (!defined(JL_HAVE_UNW_CONTEXT) && defined(JL_HAVE_ASM)) || defined(JL_HAVE_SIGALTSTACK)
typedef struct jl_stack_context_t jl_ucontext_t;
typedef jl_stack_context_t _jl_ucontext_t;
#endif
#if defined(JL_HAVE_ASYNCIFY)
#if defined(_COMPILER_TSAN_ENABLED_)
Expand All @@ -75,19 +74,30 @@ typedef struct {
// __asyncify_data struct.
void *stackbottom;
void *stacktop;
} jl_ucontext_t;
} _jl_ucontext_t;
#endif
#if defined(JL_HAVE_UNW_CONTEXT)
#define UNW_LOCAL_ONLY
#include <libunwind.h>
typedef unw_context_t jl_ucontext_t;
typedef unw_context_t _jl_ucontext_t;
#endif
#if defined(JL_HAVE_UCONTEXT)
#include <ucontext.h>
typedef ucontext_t jl_ucontext_t;
typedef ucontext_t _jl_ucontext_t;
#endif
#endif

typedef struct {
union {
_jl_ucontext_t ctx;
jl_stack_context_t copy_ctx;
};
#if defined(_COMPILER_TSAN_ENABLED_)
void *tsan_state;
#endif
} jl_ucontext_t;


// handle to reference an OS thread
#ifdef _OS_WINDOWS_
typedef DWORD jl_thread_t;
Expand Down Expand Up @@ -225,13 +235,9 @@ typedef struct _jl_tls_states_t {
void *stackbase;
size_t stacksize;
union {
jl_ucontext_t base_ctx; // base context of stack
_jl_ucontext_t base_ctx; // base context of stack
// This hack is needed to support always_copy_stacks:
#ifdef _OS_WINDOWS_
jl_ucontext_t copy_stack_ctx;
#else
struct jl_stack_context_t copy_stack_ctx;
#endif
jl_stack_context_t copy_stack_ctx;
};
// Temp storage for exception thrown in signal handler. Not rooted.
struct _jl_value_t *sig_exception;
Expand Down
3 changes: 2 additions & 1 deletion src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
#include "julia_assert.h"

// helper function for returning the unw_context_t inside a ucontext_t
static bt_context_t *jl_to_bt_context(void *sigctx)
// (also used by stackwalk.c)
bt_context_t *jl_to_bt_context(void *sigctx)
{
#ifdef __APPLE__
return (bt_context_t*)&((ucontext64_t*)sigctx)->uc_mcontext64->__ss;
Expand Down
5 changes: 2 additions & 3 deletions src/signals-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ static void jl_try_throw_sigint(void)

void __cdecl crt_sig_handler(int sig, int num)
{
jl_task_t *ct = jl_current_task;
CONTEXT Context;
switch (sig) {
case SIGFPE:
Expand Down Expand Up @@ -100,8 +99,8 @@ void __cdecl crt_sig_handler(int sig, int num)
// StackOverflowException needs extra stack space to record the backtrace
// so we keep one around, shared by all threads
static jl_mutex_t backtrace_lock;
static jl_ucontext_t collect_backtrace_fiber;
static jl_ucontext_t error_return_fiber;
static win32_ucontext_t collect_backtrace_fiber;
static win32_ucontext_t error_return_fiber;
static PCONTEXT stkerror_ctx;
static jl_ptls_t stkerror_ptls;
static int have_backtrace_fiber;
Expand Down
6 changes: 3 additions & 3 deletions src/stackwalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ void jl_rec_backtrace(jl_task_t *t)
#if defined(_OS_WINDOWS_)
bt_context_t c;
memset(&c, 0, sizeof(c));
_JUMP_BUFFER *mctx = (_JUMP_BUFFER*)&t->ctx.uc_mcontext;
_JUMP_BUFFER *mctx = (_JUMP_BUFFER*)&t->ctx.ctx.uc_mcontext;
#if defined(_CPU_X86_64_)
c.Rbx = mctx->Rbx;
c.Rsp = mctx->Rsp;
Expand All @@ -737,9 +737,9 @@ void jl_rec_backtrace(jl_task_t *t)
#endif
context = &c;
#elif defined(JL_HAVE_UNW_CONTEXT)
context = &t->ctx;
context = &t->ctx.ctx;
#elif defined(JL_HAVE_UCONTEXT)
context = jl_to_bt_context(&t->ctx);
context = jl_to_bt_context(&t->ctx.ctx);
#else
#endif
if (context)
Expand Down
Loading

0 comments on commit 578392a

Please sign in to comment.