Skip to content

Commit f499495

Browse files
Merge pull request #249 from insertinterestingnamehere/tsan_interop
Thread Sanitizer Interop
2 parents 6495403 + 58be42b commit f499495

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

include/qt_qthread_struct.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
#include <stdatomic.h>
55

6+
#if defined(__has_feature)
7+
#if __has_feature(thread_sanitizer)
8+
#include <sanitizer/tsan_interface.h>
9+
#endif
10+
#endif
11+
612
#ifdef HAVE_CONFIG_H
713
#include "config.h"
814
#endif
@@ -67,6 +73,11 @@ struct qthread_runtime_data_s {
6773
/* affinity for children created by this task */
6874
qthread_shepherd_id_t child_affinity;
6975
#endif
76+
#if defined(__has_feature)
77+
#if __has_feature(thread_sanitizer)
78+
void *_Atomic tsan_fiber;
79+
#endif
80+
#endif
7081
};
7182

7283
/* Try very VERY hard to keep this under 1 cacheline (64 bytes) */

include/qthread_innards.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ typedef struct qlib_s {
4747
qt_context_t master_context;
4848
#ifdef QTHREAD_USE_VALGRIND
4949
unsigned int valgrind_masterstack_id;
50+
#endif
51+
#if defined(__has_feature)
52+
#if __has_feature(thread_sanitizer)
53+
void *tsan_main_fiber;
54+
#endif
5055
#endif
5156

5257
/* assigns a unique thread_id mostly for debugging! */

src/qthread.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
#include <sys/mman.h>
3737
#include <sys/types.h>
3838

39+
#if defined(__has_feature)
40+
#if __has_feature(thread_sanitizer)
41+
#include <sanitizer/tsan_interface.h>
42+
#endif
43+
#endif
44+
3945
/******************************************************/
4046
/* Public Headers */
4147
/******************************************************/
@@ -225,8 +231,80 @@ static inline void alloc_rdata(qthread_shepherd_t *me, qthread_t *t) { /*{{{*/
225231
VALGRIND_STACK_REGISTER(stack, qlib->qthread_stack_size);
226232
}
227233
#endif
234+
#if defined(__has_feature)
235+
#if __has_feature(thread_sanitizer)
236+
atomic_store_explicit(
237+
&rdata->tsan_fiber, __tsan_create_fiber(0u), memory_order_relaxed);
238+
assert(atomic_load_explicit(&rdata->tsan_fiber, memory_order_relaxed));
239+
#endif
240+
#endif
228241
} /*}}}*/
229242

243+
#if defined(__has_feature)
244+
#if __has_feature(thread_sanitizer)
245+
#define qthread_before_swap_to_qthread(t) \
246+
do { \
247+
void *tsan_local_fiber = \
248+
atomic_load_explicit(&t->rdata->tsan_fiber, memory_order_relaxed); \
249+
atomic_store_explicit(&t->rdata->tsan_fiber, \
250+
__tsan_get_current_fiber(), \
251+
memory_order_relaxed); \
252+
__tsan_switch_to_fiber(tsan_local_fiber, 0u); \
253+
} while (0)
254+
255+
#define qthread_after_swap_to_qthread(t)
256+
257+
#define qthread_before_swap_from_qthread(t) \
258+
do { \
259+
void *tsan_local_fiber = \
260+
atomic_load_explicit(&t->rdata->tsan_fiber, memory_order_relaxed); \
261+
atomic_store_explicit(&t->rdata->tsan_fiber, \
262+
__tsan_get_current_fiber(), \
263+
memory_order_relaxed); \
264+
__tsan_switch_to_fiber(tsan_local_fiber, 0u); \
265+
} while (0)
266+
267+
#define qthread_after_swap_from_qthread(t)
268+
269+
#define qthread_before_swap_to_main() \
270+
do { \
271+
void *tsan_local_fiber_main = qlib->tsan_main_fiber; \
272+
qlib->tsan_main_fiber = __tsan_get_current_fiber(); \
273+
__tsan_switch_to_fiber(tsan_local_fiber_main, 0u); \
274+
} while (0)
275+
276+
#define qthread_after_swap_to_main()
277+
278+
#define qthread_before_swap_from_main() \
279+
do { \
280+
void *tsan_local_fiber_main = qlib->tsan_main_fiber; \
281+
qlib->tsan_main_fiber = __tsan_get_current_fiber(); \
282+
__tsan_switch_to_fiber(tsan_local_fiber_main, 0u); \
283+
} while (0)
284+
285+
#define qthread_after_swap_from_main()
286+
287+
#else
288+
#define qthread_before_swap_to_qthread(t)
289+
#define qthread_after_swap_to_qthread(t)
290+
#define qthread_before_swap_from_qthread(t)
291+
#define qthread_after_swap_from_qthread(t)
292+
#define qthread_before_swap_to_main()
293+
#define qthread_after_swap_to_main()
294+
#define qthread_before_swap_from_main()
295+
#define qthread_after_swap_from_main()
296+
#endif
297+
#else
298+
#define qthread_before_swap_to_qthread(t)
299+
#define qthread_after_swap_to_qthread(t)
300+
#define qthread_before_swap_from_qthread(t)
301+
#define qthread_after_swap_from_qthread(t)
302+
#define qthread_before_swap_to_main()
303+
#define qthread_after_swap_to_main()
304+
#define qthread_before_swap_from_main()
305+
#define qthread_after_swap_from_main()
306+
#endif
307+
230308
/* the qthread_master() function is the loop responsible for actually
231309
* executing the work units
232310
*
@@ -251,6 +329,7 @@ static void *qthread_master(void *arg) {
251329
qthread_worker_t *me_worker = (qthread_worker_t *)arg;
252330
qthread_shepherd_t *me = (qthread_shepherd_t *)me_worker->shepherd;
253331
qthread_shepherd_id_t my_id = me->shepherd_id;
332+
if (my_id == 0 && me_worker->worker_id == 0) { qthread_after_swap_to_main(); }
254333
qt_context_t my_context;
255334
qt_threadqueue_t *threadqueue;
256335
qt_threadqueue_private_t *localqueue = NULL;
@@ -441,6 +520,10 @@ static void *qthread_master(void *arg) {
441520
}
442521
}
443522

523+
if (my_id == 0 && me_worker->worker_id == 0) {
524+
qthread_before_swap_from_main();
525+
}
526+
444527
pthread_exit(NULL);
445528
return NULL;
446529
} /*}}} */
@@ -714,6 +797,17 @@ int API_FUNC qthread_initialize(void) { /*{{{ */
714797
qlib->mccoy_thread->rdata->stack = NULL;
715798
qlib->mccoy_thread->rdata->tasklocal_size = 0;
716799

800+
#if defined(__has_feature)
801+
#if __has_feature(thread_sanitizer)
802+
atomic_store_explicit(&qlib->mccoy_thread->rdata->tsan_fiber,
803+
__tsan_get_current_fiber(),
804+
memory_order_relaxed);
805+
qlib->tsan_main_fiber = __tsan_create_fiber(0u);
806+
assert(atomic_load_explicit(&qlib->mccoy_thread->rdata->tsan_fiber,
807+
memory_order_relaxed) &&
808+
qlib->tsan_main_fiber);
809+
#endif
810+
#endif
717811
TLS_SET(shepherd_structs,
718812
(qthread_shepherd_t *)&(qlib->shepherds[0].workers[0]));
719813
qt_threadqueue_enqueue(qlib->shepherds[0].ready, qlib->mccoy_thread);
@@ -749,6 +843,9 @@ int API_FUNC qthread_initialize(void) { /*{{{ */
749843
sizeof(qt_context_t));
750844
VALGRIND_MAKE_MEM_DEFINED(&(qlib->master_context), sizeof(qt_context_t));
751845
#endif
846+
847+
qthread_before_swap_to_main();
848+
752849
#ifdef HAVE_NATIVE_MAKECONTEXT
753850
qassert(
754851
swapcontext(&qlib->mccoy_thread->rdata->context, &(qlib->master_context)),
@@ -758,6 +855,9 @@ int API_FUNC qthread_initialize(void) { /*{{{ */
758855
qt_swapctxt(&qlib->mccoy_thread->rdata->context, &(qlib->master_context)),
759856
0);
760857
#endif
858+
859+
qthread_after_swap_from_main();
860+
761861
assert(hw_par > 0);
762862
qlib->nworkers_active = hw_par;
763863

@@ -1053,6 +1153,14 @@ void API_FUNC qthread_finalize(void) { /*{{{ */
10531153
#ifdef QTHREAD_USE_VALGRIND
10541154
VALGRIND_STACK_DEREGISTER(qlib->mccoy_thread->rdata->valgrind_stack_id);
10551155
VALGRIND_STACK_DEREGISTER(qlib->valgrind_masterstack_id);
1156+
#endif
1157+
#if defined(__has_feature)
1158+
#if __has_feature(thread_sanitizer)
1159+
assert(atomic_load_explicit(&qlib->mccoy_thread->rdata->tsan_fiber,
1160+
memory_order_relaxed) &&
1161+
qlib->tsan_main_fiber);
1162+
//__tsan_destroy_fiber(qlib->tsan_main_fiber);
1163+
#endif
10561164
#endif
10571165
assert(qlib->mccoy_thread->rdata->stack == NULL);
10581166
if (qlib->mccoy_thread->rdata->tasklocal_size > 0) {
@@ -1381,6 +1489,12 @@ void qthread_thread_free(qthread_t *t) { /*{{{ */
13811489
}
13821490
#ifdef QTHREAD_USE_VALGRIND
13831491
VALGRIND_STACK_DEREGISTER(t->rdata->valgrind_stack_id);
1492+
#endif
1493+
#if defined(__has_feature)
1494+
#if __has_feature(thread_sanitizer)
1495+
assert(atomic_load_explicit(&t->rdata->tsan_fiber, memory_order_relaxed));
1496+
//__tsan_destroy_fiber(t->rdata->tsan_fiber);
1497+
#endif
13841498
#endif
13851499
if (atomic_load_explicit(&t->flags, memory_order_relaxed) &
13861500
QTHREAD_SIMPLE) {
@@ -1452,6 +1566,7 @@ static void qthread_wrapper(unsigned int high, unsigned int low) { /*{{{ */
14521566
static void qthread_wrapper(void *ptr) {
14531567
qthread_t *t = (qthread_t *)ptr;
14541568
#endif
1569+
if ((t->flags & QTHREAD_SIMPLE) == 0) { qthread_after_swap_to_qthread(t); }
14551570
#ifdef QTHREAD_ALLOW_HPCTOOLKIT_STACK_UNWINDING
14561571
MONITOR_ASM_LABEL(qthread_fence1); // add label for HPCToolkit stack unwind
14571572
#endif
@@ -1594,7 +1709,10 @@ static void qthread_wrapper(void *ptr) {
15941709
#endif
15951710
if ((atomic_load_explicit(&t->flags, memory_order_relaxed) &
15961711
QTHREAD_SIMPLE) == 0) {
1712+
qthread_before_swap_from_qthread(t);
15971713
qthread_back_to_master2(t);
1714+
qthread_after_swap_to_qthread(t);
1715+
qthread_before_swap_from_qthread(t);
15981716
}
15991717
} /*}}} */
16001718

@@ -1643,6 +1761,9 @@ void INTERNAL qthread_exec(qthread_t *t, qt_context_t *c) { /*{{{ */
16431761
atomic_load_explicit(&t->rdata->return_context, memory_order_relaxed),
16441762
sizeof(qt_context_t));
16451763
#endif
1764+
1765+
qthread_before_swap_to_qthread(t);
1766+
16461767
#ifdef HAVE_NATIVE_MAKECONTEXT
16471768
qassert(swapcontext(atomic_load_explicit(&t->rdata->return_context,
16481769
memory_order_relaxed),
@@ -1654,6 +1775,9 @@ void INTERNAL qthread_exec(qthread_t *t, qt_context_t *c) { /*{{{ */
16541775
&t->rdata->context),
16551776
0);
16561777
#endif
1778+
1779+
qthread_after_swap_from_qthread(t);
1780+
16571781
} else {
16581782
assert(t->thread_state == QTHREAD_STATE_NEW);
16591783
atomic_store_explicit(
@@ -2109,6 +2233,7 @@ void INTERNAL qthread_back_to_master(qthread_t *t) { /*{{{ */
21092233
atomic_load_explicit(&t->rdata->return_context, memory_order_relaxed),
21102234
sizeof(qt_context_t));
21112235
#endif
2236+
qthread_before_swap_from_qthread(t);
21122237
#ifdef HAVE_NATIVE_MAKECONTEXT
21132238
qassert(swapcontext(&t->rdata->context,
21142239
atomic_load_explicit(&t->rdata->return_context,
@@ -2120,6 +2245,9 @@ void INTERNAL qthread_back_to_master(qthread_t *t) { /*{{{ */
21202245
memory_order_relaxed)),
21212246
0);
21222247
#endif
2248+
2249+
qthread_after_swap_to_qthread(t);
2250+
21232251
} /*}}} */
21242252

21252253
void INTERNAL qthread_back_to_master2(qthread_t *t) { /*{{{ */

0 commit comments

Comments
 (0)