return NULL;
}
+ /* TSan reports data races between the suspension flag setter */
+ /* (called from GC_suspend_thread) and GC_suspend_handler_inner, */
+ /* suspend_self_inner. The first one seems to be a false positive */
+ /* as the handler is invoked after RAISE_SIGNAL, and the 2nd one is */
+ /* safe to be ignored as the flag is checked in a loop. */
+ static void set_suspended_ext_flag(GC_thread t) GC_ATTR_NO_SANITIZE_THREAD
+ {
+ t -> flags |= SUSPENDED_EXT;
+ }
+
GC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID thread) {
GC_thread t;
IF_CANCEL(int cancel_state;)
return;
}
- t -> flags |= SUSPENDED_EXT;
+ set_suspended_ext_flag(t);
if ((pthread_t)thread == pthread_self()) {
UNLOCK();
/* It is safe as "t" cannot become invalid here (no race with */
UNLOCK();
}
- GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID thread) {
+ /* Same as for GC_suspend_thread(), TSan reports data races between */
+ /* this function and GC_suspend_handler_inner, suspend_self_inner; */
+ /* it is safe to ignore them both. */
+ GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID thread)
+ GC_ATTR_NO_SANITIZE_THREAD
+ {
GC_thread t;
DCL_LOCK_STATE;