Skip to content

Commit 47c20ec

Browse files
Kenovtjnash
authored andcommitted
Re-correct TSAN integration
Looks like #36929 got reverted without comment. Not sure what happened there. Re-apply it to fix TSAN.
1 parent 5b42a34 commit 47c20ec

File tree

3 files changed

+68
-23
lines changed

3 files changed

+68
-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: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,29 @@ 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_destroy_copyctx(jl_ptls_t ptls, struct jl_stack_context_t *ctx) {}
79+
static inline void tsan_switch_to_ctx(jl_ucontext_t *ctx) {}
80+
static inline void tsan_switch_to_copyctx(struct jl_stack_context_t *ctx) {}
6781
#endif
6882

6983
// empirically, jl_finish_task needs about 64k stack space to infer/run
@@ -180,6 +194,7 @@ static void restore_stack2(jl_task_t *t, jl_ptls_t ptls, jl_task_t *lastt)
180194
#error COPY_STACKS is incompatible with this platform
181195
#endif
182196
sanitizer_start_switch_fiber(t->stkbuf, t->bufsz);
197+
tsan_switch_to_copyctx(&t->copy_stack_ctx);
183198
#if defined(_OS_WINDOWS_)
184199
jl_setcontext(&t->ctx);
185200
#else
@@ -357,9 +372,9 @@ static void ctx_switch(jl_task_t *lastt)
357372
t->sticky = 1;
358373
t->bufsz = 0;
359374
if (always_copy_stacks)
360-
memcpy(&t->copy_stack_ctx, &ptls->copy_stack_ctx, sizeof(t->copy_stack_ctx));
375+
memcpy(&t->copy_stack_ctx, &ptls->copy_stack_ctx, sizeof(t->copy_stack_ctx) - sizeof(t->copy_stack_ctx.tsan_state));
361376
else
362-
memcpy(&t->ctx, &ptls->base_ctx, sizeof(t->ctx));
377+
memcpy(&t->ctx, &ptls->base_ctx, sizeof(t->ctx) - sizeof(t->ctx.tsan_state));
363378
#else
364379
jl_throw(jl_memory_exception);
365380
#endif
@@ -401,35 +416,39 @@ static void ctx_switch(jl_task_t *lastt)
401416
#endif
402417
jl_set_pgcstack(&t->gcstack);
403418

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
409419
if (t->started) {
410420
#ifdef COPY_STACKS
411421
if (t->copy_stack) {
412422
if (!killed && !lastt->copy_stack)
413423
restore_stack2(t, ptls, lastt);
414-
else if (lastt->copy_stack) {
415-
restore_stack(t, ptls, NULL); // (doesn't return)
416-
}
417424
else {
418-
restore_stack(t, ptls, (char*)1); // (doesn't return)
425+
tsan_switch_to_copyctx(&t->copy_stack_ctx);
426+
if (killed)
427+
tsan_destroy_copyctx(ptls, &lastt->copy_stack_ctx);
428+
429+
if (lastt->copy_stack) {
430+
restore_stack(t, ptls, NULL); // (doesn't return)
431+
}
432+
else {
433+
restore_stack(t, ptls, (char*)1); // (doesn't return)
434+
}
419435
}
420436
}
421437
else
422438
#endif
423439
{
424440
sanitizer_start_switch_fiber(t->stkbuf, t->bufsz);
425441
if (killed) {
442+
tsan_switch_to_ctx(&t->ctx);
443+
tsan_destroy_ctx(ptls, &lastt->ctx);
426444
jl_set_fiber(&t->ctx); // (doesn't return)
427445
abort(); // unreachable
428446
}
429447
else {
430448
if (lastt->copy_stack) {
431449
// Resume at the jl_setjmp earlier in this function,
432450
// don't do a full task swap
451+
tsan_switch_to_ctx(&t->ctx);
433452
jl_set_fiber(&t->ctx); // (doesn't return)
434453
}
435454
else {
@@ -441,6 +460,10 @@ static void ctx_switch(jl_task_t *lastt)
441460
else {
442461
sanitizer_start_switch_fiber(t->stkbuf, t->bufsz);
443462
if (t->copy_stack && always_copy_stacks) {
463+
tsan_switch_to_ctx(&t->ctx);
464+
if (killed) {
465+
tsan_destroy_ctx(ptls, &lastt->ctx);
466+
}
444467
#ifdef COPY_STACKS
445468
#if defined(_OS_WINDOWS_)
446469
jl_setcontext(&t->ctx);
@@ -452,11 +475,14 @@ static void ctx_switch(jl_task_t *lastt)
452475
}
453476
else {
454477
if (killed) {
478+
tsan_switch_to_ctx(&t->ctx);
479+
tsan_destroy_ctx(ptls, &lastt->ctx);
455480
jl_start_fiber_set(&t->ctx); // (doesn't return)
456481
abort();
457482
}
458483
else if (lastt->copy_stack) {
459484
// Resume at the jl_setjmp earlier in this function
485+
tsan_switch_to_ctx(&t->ctx);
460486
jl_start_fiber_set(&t->ctx); // (doesn't return)
461487
abort();
462488
}
@@ -764,7 +790,10 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, jl_value_t *completion
764790
}
765791
#endif
766792
#ifdef _COMPILER_TSAN_ENABLED_
767-
t->tsan_state = __tsan_create_fiber(0);
793+
if (always_copy_stacks)
794+
t->copy_stack_ctx.tsan_state = __tsan_create_fiber(0);
795+
else
796+
t->ctx.tsan_state = __tsan_create_fiber(0);
768797
#endif
769798
return t;
770799
}
@@ -924,10 +953,12 @@ static void jl_start_fiber_set(jl_ucontext_t *t)
924953
static void jl_start_fiber_swap(jl_ucontext_t *lastt, jl_ucontext_t *t)
925954
{
926955
assert(lastt);
956+
tsan_switch_to_ctx(t);
927957
swapcontext(lastt, t);
928958
}
929959
static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t)
930960
{
961+
tsan_switch_to_ctx(t);
931962
swapcontext(lastt, t);
932963
}
933964
static void jl_set_fiber(jl_ucontext_t *t)
@@ -982,6 +1013,7 @@ static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t)
9821013
{
9831014
if (jl_setjmp(lastt->uc_mcontext, 0))
9841015
return;
1016+
tsan_switch_to_ctx(t);
9851017
jl_set_fiber(t); // doesn't return
9861018
}
9871019
static void jl_set_fiber(jl_ucontext_t *t)
@@ -1069,6 +1101,7 @@ static void jl_start_fiber_swap(jl_ucontext_t *lastt, jl_ucontext_t *t)
10691101
if (jl_setjmp(lastt->uc_mcontext, 0))
10701102
return;
10711103
#endif
1104+
tsan_switch_to_ctx(t);
10721105
jl_start_fiber_set(t); // doesn't return
10731106
}
10741107
static void jl_start_fiber_set(jl_ucontext_t *t)
@@ -1219,12 +1252,14 @@ static void jl_start_fiber_swap(jl_ucontext_t *lastt, jl_ucontext_t *t)
12191252
assert(lastt);
12201253
if (lastt && jl_setjmp(lastt->uc_mcontext, 0))
12211254
return;
1255+
tsan_switch_to_ctx(t);
12221256
jl_start_fiber_set(t);
12231257
}
12241258
static void jl_swap_fiber(jl_ucontext_t *lastt, jl_ucontext_t *t)
12251259
{
12261260
if (jl_setjmp(lastt->uc_mcontext, 0))
12271261
return;
1262+
tsan_switch_to_ctx(t);
12281263
jl_start_fiber_set(t); // doesn't return
12291264
}
12301265
static void jl_set_fiber(jl_ucontext_t *t)
@@ -1311,7 +1346,10 @@ jl_task_t *jl_init_root_task(jl_ptls_t ptls, void *stack_lo, void *stack_hi)
13111346
assert(jl_current_task == ct);
13121347

13131348
#ifdef _COMPILER_TSAN_ENABLED_
1314-
ct->tsan_state = __tsan_get_current_fiber();
1349+
if (always_copy_stacks)
1350+
ct->copy_stack_ctx.tsan_state = __tsan_get_current_fiber();
1351+
else
1352+
ct->ctx.tsan_state = __tsan_get_current_fiber();
13151353
#endif
13161354

13171355
#ifdef COPY_STACKS

0 commit comments

Comments
 (0)