2 changes: 2 additions & 0 deletions openmp/runtime/src/kmp_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <process.h>
#endif

#include "tsan_annotations.h"

#if defined(KMP_GOMP_COMPAT)
char const __kmp_version_alt_comp[] = KMP_VERSION_PREFIX "alternative compiler support: yes";
Expand Down Expand Up @@ -5669,6 +5670,7 @@ __kmp_reap_thread(
/* Assume the threads are at the fork barrier here */
KA_TRACE( 20, ("__kmp_reap_thread: releasing T#%d from fork barrier for reap\n", gtid ) );
/* Need release fence here to prevent seg faults for tree forkjoin barrier (GEH) */
ANNOTATE_HAPPENS_BEFORE(thread);
kmp_flag_64 flag(&thread->th.th_bar[ bs_forkjoin_barrier ].bb.b_go, thread);
__kmp_release_64(&flag);
}; // if
Expand Down
27 changes: 23 additions & 4 deletions openmp/runtime/src/kmp_tasking.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "ompt-specific.h"
#endif

#include "tsan_annotations.h"

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

Expand Down Expand Up @@ -555,6 +557,7 @@ __kmp_free_task( kmp_int32 gtid, kmp_taskdata_t * taskdata, kmp_info_t * thread
KMP_DEBUG_ASSERT( TCR_4(taskdata->td_incomplete_child_tasks) == 0 );

taskdata->td_flags.freed = 1;
ANNOTATE_HAPPENS_BEFORE(taskdata);
// deallocate the taskdata and shared variable blocks associated with this task
#if USE_FAST_MEMORY
__kmp_fast_free( thread, taskdata );
Expand Down Expand Up @@ -1022,6 +1025,7 @@ __kmp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_tasking_flags_t *flags,
#else /* ! USE_FAST_MEMORY */
taskdata = (kmp_taskdata_t *) __kmp_thread_malloc( thread, shareds_offset + sizeof_shareds );
#endif /* USE_FAST_MEMORY */
ANNOTATE_HAPPENS_AFTER(taskdata);

task = KMP_TASKDATA_TO_TASK(taskdata);

Expand Down Expand Up @@ -1121,6 +1125,7 @@ __kmp_task_alloc( ident_t *loc_ref, kmp_int32 gtid, kmp_tasking_flags_t *flags,

KA_TRACE(20, ("__kmp_task_alloc(exit): T#%d created task %p parent=%p\n",
gtid, taskdata, taskdata->td_parent) );
ANNOTATE_HAPPENS_BEFORE(task);

#if OMPT_SUPPORT
__kmp_task_init_ompt(taskdata, gtid, (void*) task_entry);
Expand Down Expand Up @@ -1206,9 +1211,13 @@ __kmp_invoke_task( kmp_int32 gtid, kmp_task_t *task, kmp_taskdata_t * current_ta

#if OMP_45_ENABLED
// Proxy tasks are not handled by the runtime
if ( taskdata->td_flags.proxy != TASK_PROXY )
if ( taskdata->td_flags.proxy != TASK_PROXY ) {
#endif
ANNOTATE_HAPPENS_AFTER(task);
__kmp_task_start( gtid, task, current_task );
#if OMP_45_ENABLED
}
#endif
__kmp_task_start( gtid, task, current_task );

#if OMPT_SUPPORT
ompt_thread_info_t oldInfo;
Expand Down Expand Up @@ -1303,9 +1312,13 @@ __kmp_invoke_task( kmp_int32 gtid, kmp_task_t *task, kmp_taskdata_t * current_ta

#if OMP_45_ENABLED
// Proxy tasks are not handled by the runtime
if ( taskdata->td_flags.proxy != TASK_PROXY )
if ( taskdata->td_flags.proxy != TASK_PROXY ) {
#endif
ANNOTATE_HAPPENS_BEFORE(taskdata->td_parent);
__kmp_task_finish( gtid, task, current_task );
#if OMP_45_ENABLED
}
#endif
__kmp_task_finish( gtid, task, current_task );

#if USE_ITT_BUILD && USE_ITT_NOTIFY
// Barrier imbalance - correct arrive time after the task finished
Expand Down Expand Up @@ -1353,6 +1366,7 @@ __kmpc_omp_task_parts( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task)
"loc=%p task=%p, return: TASK_CURRENT_NOT_QUEUED\n", gtid, loc_ref,
new_taskdata ) );

ANNOTATE_HAPPENS_BEFORE(new_task);
return TASK_CURRENT_NOT_QUEUED;
}

Expand Down Expand Up @@ -1397,6 +1411,7 @@ __kmp_omp_task( kmp_int32 gtid, kmp_task_t * new_task, bool serialize_immediate
}
#endif

ANNOTATE_HAPPENS_BEFORE(new_task);
return TASK_CURRENT_NOT_QUEUED;
}

Expand Down Expand Up @@ -1511,6 +1526,7 @@ __kmpc_omp_taskwait( ident_t *loc_ref, kmp_int32 gtid )
taskdata->ompt_task_info.frame.reenter_runtime_frame = NULL;
}
#endif
ANNOTATE_HAPPENS_AFTER(taskdata);
}

KA_TRACE(10, ("__kmpc_omp_taskwait(exit): T#%d task %p finished waiting, "
Expand Down Expand Up @@ -1649,6 +1665,7 @@ __kmpc_end_taskgroup( ident_t* loc, int gtid )
__kmp_thread_free( thread, taskgroup );

KA_TRACE(10, ("__kmpc_end_taskgroup(exit): T#%d task %p finished waiting\n", gtid, taskdata) );
ANNOTATE_HAPPENS_AFTER(taskdata);
}
#endif

Expand Down Expand Up @@ -2328,8 +2345,10 @@ __kmp_realloc_task_threads_data( kmp_info_t *thread, kmp_task_team_t *task_team
// Make the initial allocate for threads_data array, and zero entries
// Cannot use __kmp_thread_calloc() because threads not around for
// kmp_reap_task_team( ).
ANNOTATE_IGNORE_WRITES_BEGIN();
*threads_data_p = (kmp_thread_data_t *)
__kmp_allocate( nthreads * sizeof(kmp_thread_data_t) );
ANNOTATE_IGNORE_WRITES_END();
#ifdef BUILD_TIED_TASK_STACK
// GEH: Figure out if this is the right thing to do
for (i = 0; i < nthreads; i++) {
Expand Down
63 changes: 63 additions & 0 deletions openmp/runtime/src/tsan_annotations.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* tsan_annotations.c -- ThreadSanitizer annotations to support data
* race detection in OpenMP programs.
*/


//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//

#include "tsan_annotations.h"

#include <stdio.h>

typedef unsigned long uptr;
typedef signed long sptr;

extern "C" __attribute__((weak)) void AnnotateHappensBefore(const char *f, int l, uptr addr) {}
extern "C" __attribute__((weak)) void AnnotateHappensAfter(const char *f, int l, uptr addr) {}
extern "C" __attribute__((weak)) void AnnotateCondVarSignal(const char *f, int l, uptr cv) {}
extern "C" __attribute__((weak)) void AnnotateCondVarSignalAll(const char *f, int l, uptr cv) {}
extern "C" __attribute__((weak)) void AnnotateMutexIsNotPHB(const char *f, int l, uptr mu) {}
extern "C" __attribute__((weak)) void AnnotateCondVarWait(const char *f, int l, uptr cv, uptr lock) {}
extern "C" __attribute__((weak)) void AnnotateRWLockCreate(const char *f, int l, uptr m) {}
extern "C" __attribute__((weak)) void AnnotateRWLockCreateStatic(const char *f, int l, uptr m) {}
extern "C" __attribute__((weak)) void AnnotateRWLockDestroy(const char *f, int l, uptr m) {}
extern "C" __attribute__((weak)) void AnnotateRWLockAcquired(const char *f, int l, uptr m, uptr is_w) {}
extern "C" __attribute__((weak)) void AnnotateRWLockReleased(const char *f, int l, uptr m, uptr is_w) {}
extern "C" __attribute__((weak)) void AnnotateTraceMemory(const char *f, int l, uptr mem) {}
extern "C" __attribute__((weak)) void AnnotateFlushState(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateNewMemory(const char *f, int l, uptr mem, uptr size) {}
extern "C" __attribute__((weak)) void AnnotateNoOp(const char *f, int l, uptr mem) {}
extern "C" __attribute__((weak)) void AnnotateFlushExpectedRaces(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateEnableRaceDetection( const char *f, int l, int enable) {}
extern "C" __attribute__((weak)) void AnnotateMutexIsUsedAsCondVar( const char *f, int l, uptr mu) {}
extern "C" __attribute__((weak)) void AnnotatePCQGet( const char *f, int l, uptr pcq) {}
extern "C" __attribute__((weak)) void AnnotatePCQPut( const char *f, int l, uptr pcq) {}
extern "C" __attribute__((weak)) void AnnotatePCQDestroy( const char *f, int l, uptr pcq) {}
extern "C" __attribute__((weak)) void AnnotatePCQCreate( const char *f, int l, uptr pcq) {}
extern "C" __attribute__((weak)) void AnnotateExpectRace( const char *f, int l, uptr mem, char *desc) {}
extern "C" __attribute__((weak)) void AnnotateBenignRaceSized( const char *f, int l, uptr mem, uptr size, char *desc) {}
extern "C" __attribute__((weak)) void AnnotateBenignRace( const char *f, int l, uptr mem, char *desc) {}
extern "C" __attribute__((weak)) void AnnotateIgnoreReadsBegin(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateIgnoreReadsEnd(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateIgnoreWritesBegin(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateIgnoreWritesEnd(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateIgnoreSyncBegin(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotateIgnoreSyncEnd(const char *f, int l) {}
extern "C" __attribute__((weak)) void AnnotatePublishMemoryRange( const char *f, int l, uptr addr, uptr size) {}
extern "C" __attribute__((weak)) void AnnotateUnpublishMemoryRange( const char *f, int l, uptr addr, uptr size) {}
extern "C" __attribute__((weak)) void AnnotateThreadName( const char *f, int l, char *name) {}
extern "C" __attribute__((weak)) void WTFAnnotateHappensBefore(const char *f, int l, uptr addr) {}
extern "C" __attribute__((weak)) void WTFAnnotateHappensAfter(const char *f, int l, uptr addr) {}
extern "C" __attribute__((weak)) void WTFAnnotateBenignRaceSized( const char *f, int l, uptr mem, uptr sz, char *desc) {}
extern "C" __attribute__((weak)) int RunningOnValgrind() {return 0;}
extern "C" __attribute__((weak)) double ValgrindSlowdown(void) {return 0;}
extern "C" __attribute__((weak)) const char __attribute__((weak))* ThreadSanitizerQuery(const char *query) {return 0;}
extern "C" __attribute__((weak)) void AnnotateMemoryIsInitialized(const char *f, int l, uptr mem, uptr sz) {}
168 changes: 168 additions & 0 deletions openmp/runtime/src/tsan_annotations.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*! \file */
/*
* tsan_annotations.h -- ThreadSanitizer annotations to support data
* race detection in OpenMP programs.
*/


//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.txt for details.
//
//===----------------------------------------------------------------------===//

#ifndef TSAN_ANNOTATIONS_H
#define TSAN_ANNOTATIONS_H

#include "kmp_config.h"

/* types as used in tsan/rtl/tsan_interface_ann.cc */
typedef unsigned long uptr;
typedef signed long sptr;

#ifdef __cplusplus
extern "C" {
#endif

/* Declaration of all annotation functions in tsan/rtl/tsan_interface_ann.cc */
void AnnotateHappensBefore(const char *f, int l, uptr addr);
void AnnotateHappensAfter(const char *f, int l, uptr addr);
void AnnotateCondVarSignal(const char *f, int l, uptr cv);
void AnnotateCondVarSignalAll(const char *f, int l, uptr cv);
void AnnotateMutexIsNotPHB(const char *f, int l, uptr mu);
void AnnotateCondVarWait(const char *f, int l, uptr cv, uptr lock);
void AnnotateRWLockCreate(const char *f, int l, uptr m);
void AnnotateRWLockCreateStatic(const char *f, int l, uptr m);
void AnnotateRWLockDestroy(const char *f, int l, uptr m);
void AnnotateRWLockAcquired(const char *f, int l, uptr m, uptr is_w);
void AnnotateRWLockReleased(const char *f, int l, uptr m, uptr is_w);
void AnnotateTraceMemory(const char *f, int l, uptr mem);
void AnnotateFlushState(const char *f, int l);
void AnnotateNewMemory(const char *f, int l, uptr mem, uptr size);
void AnnotateNoOp(const char *f, int l, uptr mem);
void AnnotateFlushExpectedRaces(const char *f, int l);
void AnnotateEnableRaceDetection( const char *f, int l, int enable);
void AnnotateMutexIsUsedAsCondVar( const char *f, int l, uptr mu);
void AnnotatePCQGet( const char *f, int l, uptr pcq);
void AnnotatePCQPut( const char *f, int l, uptr pcq);
void AnnotatePCQDestroy( const char *f, int l, uptr pcq);
void AnnotatePCQCreate( const char *f, int l, uptr pcq);
void AnnotateExpectRace( const char *f, int l, uptr mem, char *desc);
void AnnotateBenignRaceSized( const char *f, int l, uptr mem, uptr size, char *desc);
void AnnotateBenignRace( const char *f, int l, uptr mem, char *desc);
void AnnotateIgnoreReadsBegin(const char *f, int l);
void AnnotateIgnoreReadsEnd(const char *f, int l);
void AnnotateIgnoreWritesBegin(const char *f, int l);
void AnnotateIgnoreWritesEnd(const char *f, int l);
void AnnotateIgnoreSyncBegin(const char *f, int l);
void AnnotateIgnoreSyncEnd(const char *f, int l);
void AnnotatePublishMemoryRange( const char *f, int l, uptr addr, uptr size);
void AnnotateUnpublishMemoryRange( const char *f, int l, uptr addr, uptr size);
void AnnotateThreadName( const char *f, int l, char *name);
void WTFAnnotateHappensBefore(const char *f, int l, uptr addr);
void WTFAnnotateHappensAfter(const char *f, int l, uptr addr);
void WTFAnnotateBenignRaceSized( const char *f, int l, uptr mem, uptr sz, char *desc);
int RunningOnValgrind();
double ValgrindSlowdown(void);
const char * ThreadSanitizerQuery(const char *query);
void AnnotateMemoryIsInitialized(const char *f, int l, uptr mem, uptr sz);

#ifdef __cplusplus
}
#endif

#ifdef TSAN_SUPPORT
#define ANNOTATE_HAPPENS_AFTER(addr) AnnotateHappensAfter(__FILE__, __LINE__, (uptr)addr)
#define ANNOTATE_HAPPENS_BEFORE(addr) AnnotateHappensBefore(__FILE__, __LINE__, (uptr)addr)
#define ANNOTATE_IGNORE_WRITES_BEGIN() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
#define ANNOTATE_IGNORE_WRITES_END() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
#define ANNOTATE_RWLOCK_CREATE(lck) AnnotateRWLockCreate(__FILE__, __LINE__, (uptr)lck)
#define ANNOTATE_RWLOCK_RELEASED(lck) AnnotateRWLockAcquired(__FILE__, __LINE__, (uptr)lck, 1)
#define ANNOTATE_RWLOCK_ACQUIRED(lck) AnnotateRWLockReleased(__FILE__, __LINE__, (uptr)lck, 1)

/* new higher level barrier annotations */
#define ANNOTATE_NEW_BARRIER_BEGIN(addr) AnnotateHappensBefore(__FILE__, __LINE__, (uptr)addr)
#define ANNOTATE_NEW_BARRIER_END(addr) AnnotateHappensAfter(__FILE__, __LINE__, (uptr)addr)
// #define ANNOTATE_NEW_BARRIER_BEGIN(addr)
// #define ANNOTATE_NEW_BARRIER_END(addr)


#define ANNOTATE_REDUCE_AFTER(addr) AnnotateHappensAfter(__FILE__, __LINE__, (uptr)addr)
#define ANNOTATE_REDUCE_BEFORE(addr) AnnotateHappensBefore(__FILE__, __LINE__, (uptr)addr)
// #define ANNOTATE_REDUCE_AFTER(addr)
// #define ANNOTATE_REDUCE_BEFORE(addr)

#else
#define ANNOTATE_HAPPENS_AFTER(addr)
#define ANNOTATE_HAPPENS_BEFORE(addr)
#define ANNOTATE_IGNORE_WRITES_BEGIN()
#define ANNOTATE_IGNORE_WRITES_END()
#define ANNOTATE_RWLOCK_CREATE(lck)
#define ANNOTATE_RWLOCK_RELEASED(lck)
#define ANNOTATE_RWLOCK_ACQUIRED(lck)
#define ANNOTATE_NEW_BARRIER_BEGIN(addr)
#define ANNOTATE_NEW_BARRIER_END(addr)
#define ANNOTATE_REDUCE_AFTER(addr)
#define ANNOTATE_REDUCE_BEFORE(addr)
#endif

#define ANNOTATE_QUEUING
#define ANNOTATE_TICKET
#define ANNOTATE_FUTEX
#define ANNOTATE_TAS
#define ANNOTATE_DRDPA

#ifdef ANNOTATE_QUEUING
#define ANNOTATE_QUEUING_CREATE(lck)
#define ANNOTATE_QUEUING_RELEASED(lck) ANNOTATE_HAPPENS_BEFORE(lck)
#define ANNOTATE_QUEUING_ACQUIRED(lck) ANNOTATE_HAPPENS_AFTER(lck)
#else
#define ANNOTATE_QUEUING_CREATE(lck)
#define ANNOTATE_QUEUING_RELEASED(lck)
#define ANNOTATE_QUEUING_ACQUIRED(lck)
#endif

#ifdef ANNOTATE_TICKET
#define ANNOTATE_TICKET_CREATE(lck)
#define ANNOTATE_TICKET_RELEASED(lck) ANNOTATE_HAPPENS_BEFORE(lck)
#define ANNOTATE_TICKET_ACQUIRED(lck) ANNOTATE_HAPPENS_AFTER(lck)
#else
#define ANNOTATE_TICKET_CREATE(lck)
#define ANNOTATE_TICKET_RELEASED(lck)
#define ANNOTATE_TICKET_ACQUIRED(lck)
#endif

#ifdef ANNOTATE_FUTEX
#define ANNOTATE_FUTEX_CREATE(lck)
#define ANNOTATE_FUTEX_RELEASED(lck) ANNOTATE_HAPPENS_BEFORE(lck)
#define ANNOTATE_FUTEX_ACQUIRED(lck) ANNOTATE_HAPPENS_AFTER(lck)
#else
#define ANNOTATE_FUTEX_CREATE(lck)
#define ANNOTATE_FUTEX_RELEASED(lck)
#define ANNOTATE_FUTEX_ACQUIRED(lck)
#endif

#ifdef ANNOTATE_TAS
#define ANNOTATE_TAS_CREATE(lck)
#define ANNOTATE_TAS_RELEASED(lck) ANNOTATE_HAPPENS_BEFORE(lck)
#define ANNOTATE_TAS_ACQUIRED(lck) ANNOTATE_HAPPENS_AFTER(lck)
#else
#define ANNOTATE_TAS_CREATE(lck)
#define ANNOTATE_TAS_RELEASED(lck)
#define ANNOTATE_TAS_ACQUIRED(lck)
#endif

#ifdef ANNOTATE_DRDPA
#define ANNOTATE_DRDPA_CREATE(lck)
#define ANNOTATE_DRDPA_RELEASED(lck) ANNOTATE_HAPPENS_BEFORE(lck)
#define ANNOTATE_DRDPA_ACQUIRED(lck) ANNOTATE_HAPPENS_AFTER(lck)
#else
#define ANNOTATE_DRDPA_CREATE(lck)
#define ANNOTATE_DRDPA_RELEASED(lck)
#define ANNOTATE_DRDPA_ACQUIRED(lck)
#endif

#endif
4 changes: 4 additions & 0 deletions openmp/runtime/src/z_Linux_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
#include <ctype.h>
#include <fcntl.h>

#include "tsan_annotations.h"

/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */

Expand Down Expand Up @@ -1609,6 +1611,7 @@ __kmp_suspend_initialize( void )
static void
__kmp_suspend_initialize_thread( kmp_info_t *th )
{
ANNOTATE_HAPPENS_AFTER(&th->th.th_suspend_init_count);
if ( th->th.th_suspend_init_count <= __kmp_fork_count ) {
/* this means we haven't initialized the suspension pthread objects for this thread
in this instance of the process */
Expand All @@ -1618,6 +1621,7 @@ __kmp_suspend_initialize_thread( kmp_info_t *th )
status = pthread_mutex_init( &th->th.th_suspend_mx.m_mutex, & __kmp_suspend_mutex_attr );
KMP_CHECK_SYSFAIL( "pthread_mutex_init", status );
*(volatile int*)&th->th.th_suspend_init_count = __kmp_fork_count + 1;
ANNOTATE_HAPPENS_BEFORE(&th->th.th_suspend_init_count);
};
}

Expand Down