@@ -55,15 +55,29 @@ static inline void sanitizer_finish_switch_fiber(void) {}
55
55
#endif
56
56
57
57
#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 );
61
61
}
62
- ctx -> state = NULL ;
62
+ ctx -> tsan_state = NULL ;
63
63
}
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 );
66
75
}
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 ) {}
67
81
#endif
68
82
69
83
// 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)
180
194
#error COPY_STACKS is incompatible with this platform
181
195
#endif
182
196
sanitizer_start_switch_fiber (t -> stkbuf , t -> bufsz );
197
+ tsan_switch_to_copyctx (& t -> copy_stack_ctx );
183
198
#if defined(_OS_WINDOWS_ )
184
199
jl_setcontext (& t -> ctx );
185
200
#else
@@ -357,9 +372,9 @@ static void ctx_switch(jl_task_t *lastt)
357
372
t -> sticky = 1 ;
358
373
t -> bufsz = 0 ;
359
374
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 ) );
361
376
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 ) );
363
378
#else
364
379
jl_throw (jl_memory_exception );
365
380
#endif
@@ -401,35 +416,39 @@ static void ctx_switch(jl_task_t *lastt)
401
416
#endif
402
417
jl_set_pgcstack (& t -> gcstack );
403
418
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
409
419
if (t -> started ) {
410
420
#ifdef COPY_STACKS
411
421
if (t -> copy_stack ) {
412
422
if (!killed && !lastt -> copy_stack )
413
423
restore_stack2 (t , ptls , lastt );
414
- else if (lastt -> copy_stack ) {
415
- restore_stack (t , ptls , NULL ); // (doesn't return)
416
- }
417
424
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
+ }
419
435
}
420
436
}
421
437
else
422
438
#endif
423
439
{
424
440
sanitizer_start_switch_fiber (t -> stkbuf , t -> bufsz );
425
441
if (killed ) {
442
+ tsan_switch_to_ctx (& t -> ctx );
443
+ tsan_destroy_ctx (ptls , & lastt -> ctx );
426
444
jl_set_fiber (& t -> ctx ); // (doesn't return)
427
445
abort (); // unreachable
428
446
}
429
447
else {
430
448
if (lastt -> copy_stack ) {
431
449
// Resume at the jl_setjmp earlier in this function,
432
450
// don't do a full task swap
451
+ tsan_switch_to_ctx (& t -> ctx );
433
452
jl_set_fiber (& t -> ctx ); // (doesn't return)
434
453
}
435
454
else {
@@ -441,6 +460,10 @@ static void ctx_switch(jl_task_t *lastt)
441
460
else {
442
461
sanitizer_start_switch_fiber (t -> stkbuf , t -> bufsz );
443
462
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
+ }
444
467
#ifdef COPY_STACKS
445
468
#if defined(_OS_WINDOWS_ )
446
469
jl_setcontext (& t -> ctx );
@@ -452,11 +475,14 @@ static void ctx_switch(jl_task_t *lastt)
452
475
}
453
476
else {
454
477
if (killed ) {
478
+ tsan_switch_to_ctx (& t -> ctx );
479
+ tsan_destroy_ctx (ptls , & lastt -> ctx );
455
480
jl_start_fiber_set (& t -> ctx ); // (doesn't return)
456
481
abort ();
457
482
}
458
483
else if (lastt -> copy_stack ) {
459
484
// Resume at the jl_setjmp earlier in this function
485
+ tsan_switch_to_ctx (& t -> ctx );
460
486
jl_start_fiber_set (& t -> ctx ); // (doesn't return)
461
487
abort ();
462
488
}
@@ -764,7 +790,10 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, jl_value_t *completion
764
790
}
765
791
#endif
766
792
#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 );
768
797
#endif
769
798
return t ;
770
799
}
@@ -924,10 +953,12 @@ static void jl_start_fiber_set(jl_ucontext_t *t)
924
953
static void jl_start_fiber_swap (jl_ucontext_t * lastt , jl_ucontext_t * t )
925
954
{
926
955
assert (lastt );
956
+ tsan_switch_to_ctx (t );
927
957
swapcontext (lastt , t );
928
958
}
929
959
static void jl_swap_fiber (jl_ucontext_t * lastt , jl_ucontext_t * t )
930
960
{
961
+ tsan_switch_to_ctx (t );
931
962
swapcontext (lastt , t );
932
963
}
933
964
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)
982
1013
{
983
1014
if (jl_setjmp (lastt -> uc_mcontext , 0 ))
984
1015
return ;
1016
+ tsan_switch_to_ctx (t );
985
1017
jl_set_fiber (t ); // doesn't return
986
1018
}
987
1019
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)
1069
1101
if (jl_setjmp (lastt -> uc_mcontext , 0 ))
1070
1102
return ;
1071
1103
#endif
1104
+ tsan_switch_to_ctx (t );
1072
1105
jl_start_fiber_set (t ); // doesn't return
1073
1106
}
1074
1107
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)
1219
1252
assert (lastt );
1220
1253
if (lastt && jl_setjmp (lastt -> uc_mcontext , 0 ))
1221
1254
return ;
1255
+ tsan_switch_to_ctx (t );
1222
1256
jl_start_fiber_set (t );
1223
1257
}
1224
1258
static void jl_swap_fiber (jl_ucontext_t * lastt , jl_ucontext_t * t )
1225
1259
{
1226
1260
if (jl_setjmp (lastt -> uc_mcontext , 0 ))
1227
1261
return ;
1262
+ tsan_switch_to_ctx (t );
1228
1263
jl_start_fiber_set (t ); // doesn't return
1229
1264
}
1230
1265
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)
1311
1346
assert (jl_current_task == ct );
1312
1347
1313
1348
#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 ();
1315
1353
#endif
1316
1354
1317
1355
#ifdef COPY_STACKS
0 commit comments