Skip to content

Commit b249b33

Browse files
committed
Re-correct TSAN integration
Looks like #36929 got reverted without comment. Not sure what happened there. Re-apply it to fix TSAN.
1 parent 22d25b1 commit b249b33

File tree

3 files changed

+67
-23
lines changed

3 files changed

+67
-23
lines changed

src/julia.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,9 +1851,6 @@ typedef struct _jl_task_t {
18511851
struct jl_stack_context_t copy_stack_ctx;
18521852
#endif
18531853
};
1854-
#if defined(_COMPILER_TSAN_ENABLED_)
1855-
void *tsan_state;
1856-
#endif
18571854
void *stkbuf; // malloc'd memory (either copybuf or stack)
18581855
size_t bufsz; // actual sizeof stkbuf
18591856
unsigned int copy_stack:31; // sizeof stack for copybuf

src/julia_threads.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ typedef win32_ucontext_t jl_ucontext_t;
5959

6060
struct jl_stack_context_t {
6161
jl_jmp_buf uc_mcontext;
62+
#if defined(_COMPILER_TSAN_ENABLED_)
63+
void *tsan_state;
64+
#endif
6265
};
6366

6467
#if (!defined(JL_HAVE_UNW_CONTEXT) && defined(JL_HAVE_ASM)) || defined(JL_HAVE_SIGALTSTACK)
@@ -84,7 +87,14 @@ typedef unw_context_t jl_ucontext_t;
8487
#endif
8588
#if defined(JL_HAVE_UCONTEXT)
8689
#include <ucontext.h>
87-
typedef ucontext_t jl_ucontext_t;
90+
typedef struct {
91+
ucontext_t ctx;
92+
#if defined(_COMPILER_TSAN_ENABLED_)
93+
void *tsan_state;
94+
#else
95+
uint8_t tsan_state[0]
96+
#endif
97+
} jl_ucontext_t;
8898
#endif
8999
#endif
90100

src/task.c

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,28 @@ static inline void sanitizer_finish_switch_fiber(void) {}
5555
#endif
5656

5757
#if defined(_COMPILER_TSAN_ENABLED_)
58-
static inline void tsan_destroy_ctx(jl_ptls_t ptls, void *state) {
59-
if (state != &ptls->root_task->state) {
60-
__tsan_destroy_fiber(ctx->state);
58+
static inline void tsan_destroy_ctx(jl_ptls_t ptls, jl_ucontext_t *ctx) {
59+
if (ctx != &ptls->root_task->ctx) {
60+
__tsan_destroy_fiber(ctx->tsan_state);
6161
}
62-
ctx->state = NULL;
62+
ctx->tsan_state = NULL;
6363
}
64-
static inline void tsan_switch_to_ctx(void *state) {
65-
__tsan_switch_to_fiber(state, 0);
64+
static inline void tsan_destroy_copyctx(jl_ptls_t ptls, struct jl_stack_context_t *ctx) {
65+
if (ctx != &ptls->root_task->copy_stack_ctx) {
66+
__tsan_destroy_fiber(ctx->tsan_state);
67+
}
68+
ctx->tsan_state = NULL;
69+
}
70+
static inline void tsan_switch_to_ctx(jl_ucontext_t *ctx) {
71+
__tsan_switch_to_fiber(ctx->tsan_state, 0);
72+
}
73+
static inline void tsan_switch_to_copyctx(struct jl_stack_context_t *ctx) {
74+
__tsan_switch_to_fiber(ctx->tsan_state, 0);
6675
}
76+
#else
77+
static inline void tsan_destroy_ctx(jl_ptls_t ptls, jl_ucontext_t *ctx) {}
78+
static inline void tsan_switch_to_ctx(jl_ucontext_t *ctx) {}
79+
static inline void tsan_switch_to_copyctx(struct jl_stack_context_t *ctx) {}
6780
#endif
6881

6982
// empirically, jl_finish_task needs about 64k stack space to infer/run
@@ -180,6 +193,7 @@ static void restore_stack2(jl_task_t *t, jl_ptls_t ptls, jl_task_t *lastt)
180193
#error COPY_STACKS is incompatible with this platform
181194
#endif
182195
sanitizer_start_switch_fiber(t->stkbuf, t->bufsz);
196+
tsan_switch_to_copyctx(&t->copy_stack_ctx);
183197
#if defined(_OS_WINDOWS_)
184198
jl_setcontext(&t->ctx);
185199
#else
@@ -357,9 +371,9 @@ static void ctx_switch(jl_task_t *lastt)
357371
t->sticky = 1;
358372
t->bufsz = 0;
359373
if (always_copy_stacks)
360-
memcpy(&t->copy_stack_ctx, &ptls->copy_stack_ctx, sizeof(t->copy_stack_ctx));
374+
memcpy(&t->copy_stack_ctx, &ptls->copy_stack_ctx, sizeof(t->copy_stack_ctx) - sizeof(t->copy_stack_ctx.tsan_state));
361375
else
362-
memcpy(&t->ctx, &ptls->base_ctx, sizeof(t->ctx));
376+
memcpy(&t->ctx, &ptls->base_ctx, sizeof(t->ctx) - sizeof(t->ctx.tsan_state));
363377
#else
364378
jl_throw(jl_memory_exception);
365379
#endif
@@ -401,35 +415,39 @@ static void ctx_switch(jl_task_t *lastt)
401415
#endif
402416
jl_set_pgcstack(&t->gcstack);
403417

404-
#if defined(_COMPILER_TSAN_ENABLED_)
405-
tsan_switch_to_ctx(&t->tsan_state);
406-
if (killed)
407-
tsan_destroy_ctx(ptls, &lastt->tsan_state);
408-
#endif
409418
if (t->started) {
410419
#ifdef COPY_STACKS
411420
if (t->copy_stack) {
412421
if (!killed && !lastt->copy_stack)
413422
restore_stack2(t, ptls, lastt);
414-
else if (lastt->copy_stack) {
415-
restore_stack(t, ptls, NULL); // (doesn't return)
416-
}
417423
else {
418-
restore_stack(t, ptls, (char*)1); // (doesn't return)
424+
tsan_switch_to_copyctx(&t->copy_stack_ctx);
425+
if (killed)
426+
tsan_destroy_copyctx(ptls, &lastt->copy_stack_ctx);
427+
428+
if (lastt->copy_stack) {
429+
restore_stack(t, ptls, NULL); // (doesn't return)
430+
}
431+
else {
432+
restore_stack(t, ptls, (char*)1); // (doesn't return)
433+
}
419434
}
420435
}
421436
else
422437
#endif
423438
{
424439
sanitizer_start_switch_fiber(t->stkbuf, t->bufsz);
425440
if (killed) {
441+
tsan_switch_to_ctx(&t->ctx);
442+
tsan_destroy_ctx(ptls, &lastt->ctx);
426443
jl_set_fiber(&t->ctx); // (doesn't return)
427444
abort(); // unreachable
428445
}
429446
else {
430447
if (lastt->copy_stack) {
431448
// Resume at the jl_setjmp earlier in this function,
432449
// don't do a full task swap
450+
tsan_switch_to_ctx(&t->ctx);
433451
jl_set_fiber(&t->ctx); // (doesn't return)
434452
}
435453
else {
@@ -441,6 +459,10 @@ static void ctx_switch(jl_task_t *lastt)
441459
else {
442460
sanitizer_start_switch_fiber(t->stkbuf, t->bufsz);
443461
if (t->copy_stack && always_copy_stacks) {
462+
tsan_switch_to_ctx(&t->ctx);
463+
if (killed) {
464+
tsan_destroy_ctx(ptls, &lastt->ctx);
465+
}
444466
#ifdef COPY_STACKS
445467
#if defined(_OS_WINDOWS_)
446468
jl_setcontext(&t->ctx);
@@ -452,11 +474,14 @@ static void ctx_switch(jl_task_t *lastt)
452474
}
453475
else {
454476
if (killed) {
477+
tsan_switch_to_ctx(&t->ctx);
478+
tsan_destroy_ctx(ptls, &lastt->ctx);
455479
jl_start_fiber_set(&t->ctx); // (doesn't return)
456480
abort();
457481
}
458482
else if (lastt->copy_stack) {
459483
// Resume at the jl_setjmp earlier in this function
484+
tsan_switch_to_ctx(&t->ctx);
460485
jl_start_fiber_set(&t->ctx); // (doesn't return)
461486
abort();
462487
}
@@ -764,7 +789,10 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, jl_value_t *completion
764789
}
765790
#endif
766791
#ifdef _COMPILER_TSAN_ENABLED_
767-
t->tsan_state = __tsan_create_fiber(0);
792+
if (always_copy_stacks)
793+
t->copy_stack_ctx.tsan_state = __tsan_create_fiber(0);
794+
else
795+
t->ctx.tsan_state = __tsan_create_fiber(0);
768796
#endif
769797
return t;
770798
}
@@ -924,10 +952,12 @@ static void jl_start_fiber_set(jl_ucontext_t *t)
924952
static void jl_start_fiber_swap(jl_ucontext_t *lastt, jl_ucontext_t *t)
925953
{
926954
assert(lastt);
955+
tsan_switch_to_ctx(t);
927956
swapcontext(lastt, t);
928957
}
929958
static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t)
930959
{
960+
tsan_switch_to_ctx(t);
931961
swapcontext(lastt, t);
932962
}
933963
static void jl_set_fiber(jl_ucontext_t *t)
@@ -982,6 +1012,7 @@ static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t)
9821012
{
9831013
if (jl_setjmp(lastt->uc_mcontext, 0))
9841014
return;
1015+
tsan_switch_to_ctx(t);
9851016
jl_set_fiber(t); // doesn't return
9861017
}
9871018
static void jl_set_fiber(jl_ucontext_t *t)
@@ -1069,6 +1100,7 @@ static void jl_start_fiber_swap(jl_ucontext_t *lastt, jl_ucontext_t *t)
10691100
if (jl_setjmp(lastt->uc_mcontext, 0))
10701101
return;
10711102
#endif
1103+
tsan_switch_to_ctx(t);
10721104
jl_start_fiber_set(t); // doesn't return
10731105
}
10741106
static void jl_start_fiber_set(jl_ucontext_t *t)
@@ -1219,12 +1251,14 @@ static void jl_start_fiber_swap(jl_ucontext_t *lastt, jl_ucontext_t *t)
12191251
assert(lastt);
12201252
if (lastt && jl_setjmp(lastt->uc_mcontext, 0))
12211253
return;
1254+
tsan_switch_to_ctx(t);
12221255
jl_start_fiber_set(t);
12231256
}
12241257
static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t)
12251258
{
12261259
if (jl_setjmp(lastt->uc_mcontext, 0))
12271260
return;
1261+
tsan_switch_to_ctx(t);
12281262
jl_start_fiber_set(t); // doesn't return
12291263
}
12301264
static void jl_set_fiber(jl_ucontext_t *t)
@@ -1311,7 +1345,10 @@ jl_task_t *jl_init_root_task(jl_ptls_t ptls, void *stack_lo, void *stack_hi)
13111345
assert(jl_current_task == ct);
13121346

13131347
#ifdef _COMPILER_TSAN_ENABLED_
1314-
ct->tsan_state = __tsan_get_current_fiber();
1348+
if (always_copy_stacks)
1349+
ct->copy_stack_ctx.tsan_state = __tsan_get_current_fiber();
1350+
else
1351+
ct->ctx.tsan_state = __tsan_get_current_fiber();
13151352
#endif
13161353

13171354
#ifdef COPY_STACKS

0 commit comments

Comments
 (0)