diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp index 77488f8432854..c8fec4564205b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp @@ -339,12 +339,16 @@ void FiberSwitchImpl(ThreadState *from, ThreadState *to) { ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags) { void *mem = Alloc(sizeof(ThreadState)); + if ((flags & FiberSwitchFlagNoSync)) + thr->ignore_sync++; ThreadState *fiber = static_cast(mem); internal_memset(fiber, 0, sizeof(*fiber)); Tid tid = ThreadCreate(thr, pc, 0, true); FiberSwitchImpl(thr, fiber); ThreadStart(fiber, tid, 0, ThreadType::Fiber); FiberSwitchImpl(fiber, thr); + if ((flags & FiberSwitchFlagNoSync)) + thr->ignore_sync--; return fiber; } @@ -357,6 +361,8 @@ void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) { void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags) { + if (thr == fiber) + return; if (!(flags & FiberSwitchFlagNoSync)) Release(thr, pc, (uptr)fiber); FiberSwitchImpl(thr, fiber); diff --git a/openmp/runtime/src/ompt-specific.cpp b/openmp/runtime/src/ompt-specific.cpp index 9743f35d2c4ff..df4804c1c3a1e 100644 --- a/openmp/runtime/src/ompt-specific.cpp +++ b/openmp/runtime/src/ompt-specific.cpp @@ -476,6 +476,9 @@ int __ompt_get_task_memory_internal(void **addr, size_t *size, int blocknum) { if (taskdata->td_flags.tasktype != TASK_EXPLICIT) return 0; // support only explicit task + if (taskdata->td_size_alloc < 0) + return 0; + *addr = taskdata; *size = taskdata->td_size_alloc; return 0; diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp index 8b338f6b18b6e..870f01d148a67 100644 --- a/openmp/tools/archer/ompt-tsan.cpp +++ b/openmp/tools/archer/ompt-tsan.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include "omp-tools.h" @@ -52,7 +52,7 @@ static int hasReductionCallback; -namespace { +namespace __archer { class ArcherFlags { public: #if (LLVM_VERSION) >= 40 @@ -64,34 +64,50 @@ class ArcherFlags { int report_data_leak{0}; int ignore_serial{0}; std::atomic all_memory{0}; + int tasking{0}; + int stack_size{1024}; + std::atomic untieds{0}; ArcherFlags(const char *env) { if (env) { std::vector tokens; - std::string token; std::string str(env); - std::istringstream iss(str); - int tmp_int; - while (std::getline(iss, token, ' ')) - tokens.push_back(token); + auto end = str.end(); + auto it = str.begin(); + auto is_sep = [](char c) { + return c == ' ' || c == ',' || c == ':' || c == '\n' || c == '\t' || + c == '\r'; + }; + while (it != end) { + auto next_it = std::find_if(it, end, is_sep); + tokens.emplace_back(it, next_it); + it = next_it; + if (it != end) { + ++it; + } + } - for (std::vector::iterator it = tokens.begin(); - it != tokens.end(); ++it) { + int tmp_int = 0; + for (const auto &token : tokens) { #if (LLVM_VERSION) >= 40 - if (sscanf(it->c_str(), "flush_shadow=%d", &flush_shadow)) + if (sscanf(token.c_str(), "flush_shadow=%d", &flush_shadow)) continue; #endif - if (sscanf(it->c_str(), "print_max_rss=%d", &print_max_rss)) + if (sscanf(token.c_str(), "print_max_rss=%d", &print_max_rss)) + continue; + if (sscanf(token.c_str(), "verbose=%d", &verbose)) + continue; + if (sscanf(token.c_str(), "report_data_leak=%d", &report_data_leak)) continue; - if (sscanf(it->c_str(), "verbose=%d", &verbose)) + if (sscanf(token.c_str(), "enable=%d", &enabled)) continue; - if (sscanf(it->c_str(), "report_data_leak=%d", &report_data_leak)) + if (sscanf(token.c_str(), "tasking=%d", &tasking)) continue; - if (sscanf(it->c_str(), "enable=%d", &enabled)) + if (sscanf(token.c_str(), "stack_size=%d", &stack_size)) continue; - if (sscanf(it->c_str(), "ignore_serial=%d", &ignore_serial)) + if (sscanf(token.c_str(), "ignore_serial=%d", &ignore_serial)) continue; - if (sscanf(it->c_str(), "all_memory=%d", &tmp_int)) { + if (sscanf(token.c_str(), "all_memory=%d", &tmp_int)) { all_memory = tmp_int; continue; } @@ -135,7 +151,9 @@ class TsanFlags { } } }; -} // namespace + +static ArcherFlags *archer_flags; +} // namespace __archer #if (LLVM_VERSION) >= 40 extern "C" { @@ -143,7 +161,6 @@ int __attribute__((weak)) __archer_get_omp_status(); void __attribute__((weak)) __tsan_flush_memory() {} } #endif -static ArcherFlags *archer_flags; #ifndef TsanHappensBefore // Thread Sanitizer is a tool that finds races in code. @@ -159,6 +176,10 @@ static void (*AnnotateNewMemory)(const char *, int, const volatile void *, static void (*__tsan_func_entry)(const void *); static void (*__tsan_func_exit)(void); static int (*RunningOnValgrind)(void); +static void *(*__tsan_get_current_fiber)(); +static void *(*__tsan_create_fiber)(unsigned flags); +static void (*__tsan_destroy_fiber)(void *fiber); +static void (*__tsan_switch_to_fiber)(void *fiber, unsigned flags); } // This marker is used to define a happens-before arc. The race detector will @@ -189,9 +210,16 @@ static int (*RunningOnValgrind)(void); #define TsanFuncEntry(pc) __tsan_func_entry(pc) #define TsanFuncExit() __tsan_func_exit() +// Fibers +#define TsanGetCurrentFiber() __tsan_get_current_fiber() +#define TsanCreateFiber(flags) __tsan_create_fiber(flags) +#define TsanSwitchToFiber(fiber, flags) __tsan_switch_to_fiber(fiber, flags) +#define TsanDestroyFiber(fiber) __tsan_destroy_fiber(fiber) + /// Required OMPT inquiry functions. static ompt_get_parallel_info_t ompt_get_parallel_info; -static ompt_get_thread_data_t ompt_get_thread_data; +typedef int (*ompt_get_task_memory_t)(void **addr, size_t *size, int blocknum); +static ompt_get_task_memory_t ompt_get_task_memory; typedef char ompt_tsan_clockid; @@ -201,11 +229,11 @@ static uint64_t my_next_id() { return ret; } -static int pagesize{0}; - // Data structure to provide a threadsafe pool of reusable objects. // DataPool -namespace { +namespace __archer { +static int pagesize{0}; + template struct DataPool final { static __thread DataPool *ThreadDataPool; std::mutex DPMutex{}; @@ -399,7 +427,7 @@ struct ParallelData final : DataPoolEntry { void *GetBarrierPtr(unsigned Index) { return &(Barrier[Index]); } ParallelData *Init(const void *codeptr) { - codePtr = codeptr; + this->codePtr = codeptr; return this; } @@ -474,6 +502,10 @@ struct TaskData final : DataPoolEntry { /// count execution phase int execution{0}; + size_t PrivateDataSize{0}; + void *PrivateDataAddr{nullptr}; + + const void *CodePtr{nullptr}; /// Count how often this structure has been put into child tasks + 1. std::atomic_int RefCount{1}; @@ -503,6 +535,13 @@ struct TaskData final : DataPoolEntry { int freed{0}; #endif + void *Fiber{nullptr}; + + void activate() { + if (Fiber) + TsanSwitchToFiber(Fiber, 1); + } + void deactivate() { assert(!Fiber || Fiber == TsanGetCurrentFiber()); } bool isIncluded() { return TaskType & ompt_task_undeferred; } bool isUntied() { return TaskType & ompt_task_untied; } bool isFinal() { return TaskType & ompt_task_final; } @@ -527,7 +566,8 @@ struct TaskData final : DataPoolEntry { void *GetLastAllMemoryPtr() { return AllMemory; } void *GetNextAllMemoryPtr() { return AllMemory + 1; } - TaskData *Init(TaskData *parent, int taskType) { + TaskData *Init(TaskData *parent, int taskType, const void *codePtr) { + CodePtr = codePtr; TaskType = taskType; Parent = parent; Team = Parent->Team; @@ -537,6 +577,8 @@ struct TaskData final : DataPoolEntry { // Copy over pointer to taskgroup. This task may set up its own stack // but for now belongs to its parent's taskgroup. TaskGroup = Parent->TaskGroup; + if (archer_flags->tasking && !isIncluded() && !isUntied()) + Fiber = TsanCreateFiber(0); } return this; } @@ -545,10 +587,17 @@ struct TaskData final : DataPoolEntry { TaskType = taskType; execution = 1; Team = team; + if (archer_flags->tasking) + Fiber = TsanGetCurrentFiber(); return this; } void Reset() { + if (archer_flags->tasking && !isImplicit() && Fiber) { + TsanDestroyFiber(Fiber); + } + CodePtr = nullptr; + Fiber = nullptr; InBarrier = false; TaskType = 0; execution = 0; @@ -557,6 +606,8 @@ struct TaskData final : DataPoolEntry { Parent = nullptr; Team = nullptr; TaskGroup = nullptr; + PrivateDataSize = 0; + PrivateDataAddr = nullptr; if (DependencyMap) { for (auto i : *DependencyMap) i.second->Delete(); @@ -572,8 +623,9 @@ struct TaskData final : DataPoolEntry { #endif } - static TaskData *New(TaskData *parent, int taskType) { - return DataPoolEntry::New()->Init(parent, taskType); + static TaskData *New(TaskData *parent, int taskType, + const void *codePtr = nullptr) { + return DataPoolEntry::New()->Init(parent, taskType, codePtr); } static TaskData *New(ParallelData *team, int taskType) { @@ -582,7 +634,6 @@ struct TaskData final : DataPoolEntry { TaskData(DataPool *dp) : DataPoolEntry(dp) {} }; -} // namespace static inline TaskData *ToTaskData(ompt_data_t *task_data) { if (task_data) @@ -608,6 +659,10 @@ static void ompt_tsan_thread_begin(ompt_thread_t thread_type, DependencyDataPool::ThreadDataPool = new DependencyDataPool; TsanNewMemory(DependencyDataPool::ThreadDataPool, sizeof(DependencyDataPool::ThreadDataPool)); + if (archer_flags->tasking) { + TsanGetCurrentFiber(); + } + thread_data->value = my_next_id(); } @@ -850,19 +905,21 @@ static void ompt_tsan_task_create( Data = TaskData::New(PData, type); new_task_data->ptr = Data; - } else if (type & ompt_task_undeferred) { - Data = TaskData::New(ToTaskData(parent_task_data), type); - new_task_data->ptr = Data; - } else if (type & ompt_task_explicit || type & ompt_task_target) { - Data = TaskData::New(ToTaskData(parent_task_data), type); + } else if (type & ompt_task_explicit || type & ompt_task_target || + type & ompt_task_taskwait) { + Data = TaskData::New(ToTaskData(parent_task_data), type, codeptr_ra); new_task_data->ptr = Data; - - // Use the newly created address. We cannot use a single address from the - // parent because that would declare wrong relationships with other - // sibling tasks that may be created before this task is started! - TsanHappensBefore(Data->GetTaskPtr()); - ToTaskData(parent_task_data)->execution++; + if (!Data->isIncluded()) { + // Use the newly created address. We cannot use a single address from the + // parent because that would declare wrong relationships with other + // sibling tasks that may be created before this task is started! + TsanHappensBefore(Data->GetTaskPtr()); + ToTaskData(parent_task_data)->execution++; + } } + if (archer_flags->tasking && Data->isUntied() && !archer_flags->untieds++) + fprintf(stderr, "Archer Warning: Task-level analysis not yet supported for " + "untied tasks\n"); } static void freeTask(TaskData *task) { @@ -950,16 +1007,10 @@ static void switchTasks(TaskData *FromTask, TaskData *ToTask) { TsanIgnoreWritesBegin(); } } - //// Not yet used - // if (FromTask) - // FromTask->deactivate(); - // if (ToTask) - // ToTask->activate(); -} - -static void endTask(TaskData *FromTask) { - if (!FromTask) - return; + if (FromTask) + FromTask->deactivate(); + if (ToTask) + ToTask->activate(); } static void startTask(TaskData *ToTask) { @@ -967,6 +1018,28 @@ static void startTask(TaskData *ToTask) { return; // Handle dependencies on first execution of the task if (ToTask->execution == 0) { + TsanFuncEntry(ToTask->CodePtr); + if (ompt_get_task_memory) { + void *addr; + size_t size; + int ret_task_memory = 0, block = 0; + do { + size = 0; + ret_task_memory = ompt_get_task_memory(&addr, &size, block++); + if (size > 0) { + TsanNewMemory((/*(void**)*/ addr), size + 8); + ToTask->PrivateDataAddr = addr; + ToTask->PrivateDataSize = size; + // printf("NewMemory(%p, %zu)\n",addr, size); + } + } while (ret_task_memory); + } + if (archer_flags->tasking) { + auto stack_size = archer_flags->stack_size; + TsanNewMemory((char *)__builtin_frame_address(0) - stack_size, + stack_size); + } + ToTask->execution++; acquireDependencies(ToTask); } @@ -975,6 +1048,17 @@ static void startTask(TaskData *ToTask) { TsanHappensAfter(ToTask->GetTaskPtr()); } +static void endTask(TaskData *FromTask) { + if (!FromTask) + return; + if (ompt_get_task_memory) { + if (FromTask->PrivateDataSize > 0) + TsanNewMemory((/*(void**)*/ FromTask->PrivateDataAddr), + FromTask->PrivateDataSize + 8); + } + TsanFuncExit(); +} + static void ompt_tsan_task_schedule(ompt_data_t *first_task_data, ompt_task_status_t prior_task_status, ompt_data_t *second_task_data) { @@ -983,11 +1067,14 @@ static void ompt_tsan_task_schedule(ompt_data_t *first_task_data, // The necessary action depends on prior_task_status: // // ompt_task_early_fulfill = 5, - // -> ignored + // -> first got fulfill event, second ignored // // ompt_task_late_fulfill = 6, // -> first completed, first freed, second ignored // + // ompt_taskwait_complete = 8, + // -> first starts, first completes, first freed, second ignored + // // ompt_task_complete = 1, // ompt_task_cancel = 3, // -> first completed, first freed, second starts @@ -1120,10 +1207,12 @@ static void ompt_tsan_mutex_released(ompt_mutex_t kind, ompt_wait_id_t wait_id, Lock.unlock(); } +} // namespace __archer + // callback , signature , variable to store result , required support level #define SET_OPTIONAL_CALLBACK_T(event, type, result, level) \ do { \ - ompt_callback_##type##_t tsan_##event = &ompt_tsan_##event; \ + ompt_callback_##type##_t tsan_##event = &__archer::ompt_tsan_##event; \ result = ompt_set_callback(ompt_callback_##event, \ (ompt_callback_t)tsan_##event); \ if (result < level) \ @@ -1147,11 +1236,12 @@ static void ompt_tsan_mutex_released(ompt_mutex_t kind, ompt_wait_id_t wait_id, } while (0) #define findTsanFunctionSilent(f, fSig) f = fSig dlsym(RTLD_DEFAULT, #f) +#define findTsanFunctionName(f, name, fSig) f = fSig dlsym(RTLD_DEFAULT, #name) static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num, ompt_data_t *tool_data) { const char *options = getenv("TSAN_OPTIONS"); - TsanFlags tsan_flags(options); + __archer::TsanFlags tsan_flags(options); ompt_set_callback_t ompt_set_callback = (ompt_set_callback_t)lookup("ompt_set_callback"); @@ -1161,7 +1251,7 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num, } ompt_get_parallel_info = (ompt_get_parallel_info_t)lookup("ompt_get_parallel_info"); - ompt_get_thread_data = (ompt_get_thread_data_t)lookup("ompt_get_thread_data"); + ompt_get_task_memory = (ompt_get_task_memory_t)lookup("ompt_get_task_memory"); if (ompt_get_parallel_info == NULL) { fprintf(stderr, "Could not get inquiry function 'ompt_get_parallel_info', " @@ -1180,6 +1270,10 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num, (void (*)(const char *, int, const volatile void *, size_t))); findTsanFunction(__tsan_func_entry, (void (*)(const void *))); findTsanFunction(__tsan_func_exit, (void (*)(void))); + findTsanFunction(__tsan_create_fiber, (void *(*)(unsigned int))); + findTsanFunction(__tsan_destroy_fiber, (void (*)(void *))); + findTsanFunction(__tsan_get_current_fiber, (void *(*)())); + findTsanFunction(__tsan_switch_to_fiber, (void (*)(void *, unsigned int))); SET_CALLBACK(thread_begin); SET_CALLBACK(thread_end); @@ -1202,37 +1296,37 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num, "Warning: please export " "TSAN_OPTIONS='ignore_noninstrumented_modules=1' " "to avoid false positive reports from the OpenMP runtime!\n"); - if (archer_flags->ignore_serial) + if (__archer::archer_flags->ignore_serial) TsanIgnoreWritesBegin(); return 1; // success } static void ompt_tsan_finalize(ompt_data_t *tool_data) { - if (archer_flags->ignore_serial) + if (__archer::archer_flags->ignore_serial) TsanIgnoreWritesEnd(); - if (archer_flags->print_max_rss) { + if (__archer::archer_flags->print_max_rss) { struct rusage end; getrusage(RUSAGE_SELF, &end); printf("MAX RSS[KBytes] during execution: %ld\n", end.ru_maxrss); } - if (archer_flags) - delete archer_flags; + if (__archer::archer_flags) + delete __archer::archer_flags; } extern "C" ompt_start_tool_result_t * ompt_start_tool(unsigned int omp_version, const char *runtime_version) { const char *options = getenv("ARCHER_OPTIONS"); - archer_flags = new ArcherFlags(options); - if (!archer_flags->enabled) { - if (archer_flags->verbose) + __archer::archer_flags = new __archer::ArcherFlags(options); + if (!__archer::archer_flags->enabled) { + if (__archer::archer_flags->verbose) std::cout << "Archer disabled, stopping operation" << std::endl; - delete archer_flags; + delete __archer::archer_flags; return NULL; } - pagesize = getpagesize(); + __archer::pagesize = getpagesize(); static ompt_start_tool_result_t ompt_start_tool_result = { &ompt_tsan_initialize, &ompt_tsan_finalize, {0}}; @@ -1247,17 +1341,23 @@ ompt_start_tool(unsigned int omp_version, const char *runtime_version) { if (!RunningOnValgrind) // if we are not running on TSAN, give a different // tool the chance to be loaded { - if (archer_flags->verbose) + if (__archer::archer_flags->verbose) std::cout << "Archer detected OpenMP application without TSan " "stopping operation" << std::endl; - delete archer_flags; + delete __archer::archer_flags; return NULL; } - if (archer_flags->verbose) - std::cout << "Archer detected OpenMP application with TSan, supplying " - "OpenMP synchronization semantics" - << std::endl; + if (__archer::archer_flags->verbose) { + if (__archer::archer_flags->tasking) + std::cout << "Archer detected OpenMP application with TSan, supplying " + "OpenMP tasking synchronization semantics" + << std::endl; + else + std::cout << "Archer detected OpenMP application with TSan, supplying " + "OpenMP synchronization semantics" + << std::endl; + } return &ompt_start_tool_result; } diff --git a/openmp/tools/archer/tests/.clang-format b/openmp/tools/archer/tests/.clang-format new file mode 100644 index 0000000000000..56fe9c2070b53 --- /dev/null +++ b/openmp/tools/archer/tests/.clang-format @@ -0,0 +1,4 @@ +BasedOnStyle: LLVM +ReflowComments: false +IndentPPDirectives: AfterHash +IncludeBlocks: Preserve diff --git a/openmp/tools/archer/tests/races/DRB027b-taskdependmissing-orig-yes.c b/openmp/tools/archer/tests/races/DRB027b-taskdependmissing-orig-yes.c new file mode 100644 index 0000000000000..0a453b3740d10 --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB027b-taskdependmissing-orig-yes.c @@ -0,0 +1,45 @@ +/* + * DRB027b-taskdependmissing-orig-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int main() { + int i = 0, sem = 0; +#pragma omp parallel shared(sem) num_threads(2) + { +#pragma omp masked + { +#pragma omp task + { + OMPT_SIGNAL(sem); + i = 1; + } +#pragma omp task + { + OMPT_SIGNAL(sem); + i = 2; + } +#pragma omp taskwait {} + } + OMPT_WAIT(sem, 2); + } + printf("i=%d\n", i); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB131b-taskdep4-orig-omp45-yes.c b/openmp/tools/archer/tests/races/DRB131b-taskdep4-orig-omp45-yes.c new file mode 100644 index 0000000000000..e8f15518da2d9 --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB131b-taskdep4-orig-omp45-yes.c @@ -0,0 +1,58 @@ +/* + * DRB131b-taskdep4-orig-omp45-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +void foo() { + + int x = 0, y = 2; + +#pragma omp task depend(inout : x) shared(x, sem) + { + OMPT_SIGNAL(sem); + x++; //1st Child Task + } + +#pragma omp task shared(y, sem) + { + OMPT_SIGNAL(sem); + y--; // 2nd child task + } + +#pragma omp task depend(in : x) if (0) // 1st taskwait + {} + + printf("x=%d\n", x); + printf("y=%d\n", y); +#pragma omp taskwait // 2nd taskwait +} + +int main() { +#pragma omp parallel + { +#pragma omp masked + foo(); + OMPT_WAIT(sem, 2); + } + + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB134b-taskdep5-orig-omp45-yes.c b/openmp/tools/archer/tests/races/DRB134b-taskdep5-orig-omp45-yes.c new file mode 100644 index 0000000000000..d746ee2fe1b11 --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB134b-taskdep5-orig-omp45-yes.c @@ -0,0 +1,58 @@ +/* + * DRB134b-taskdep5-orig-omp45-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +void foo() { + int x = 0, y = 2; + +#pragma omp task depend(inout : x) shared(x, sem) + { + OMPT_SIGNAL(sem); + x++; // 1st child task + } + +#pragma omp task depend(in : x) depend(inout : y) shared(x, y, sem) + { + OMPT_SIGNAL(sem); + y -= x; //2nd child task + } + +#pragma omp task depend(in : x) if (0) // 1st taskwait + {} + + printf("x=%d\n", x); + printf("y=%d\n", y); + +#pragma omp taskwait // 2nd taskwait +} + +int main() { +#pragma omp parallel num_threads(2) + { +#pragma omp masked + { foo(); } + OMPT_WAIT(sem, 2); + } + + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB136b-taskdep-mutexinoutset-orig-yes.c b/openmp/tools/archer/tests/races/DRB136b-taskdep-mutexinoutset-orig-yes.c new file mode 100644 index 0000000000000..9725abea80a7a --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB136b-taskdep-mutexinoutset-orig-yes.c @@ -0,0 +1,67 @@ +/* + * DRB136b-taskdep-mutexinoutset-orig-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int main() { + int a, b, c, d, sem = 0; + +#pragma omp parallel num_threads(2) + { +#pragma omp masked + { +#pragma omp task depend(out : c) + { + OMPT_SIGNAL(sem); + c = 1; + } +#pragma omp task depend(out : a) + { + OMPT_SIGNAL(sem); + a = 2; + } +#pragma omp task depend(out : b) + { + OMPT_SIGNAL(sem); + b = 3; + } +#pragma omp task depend(in : a) + { + OMPT_SIGNAL(sem); + c += a; + } +#pragma omp task depend(in : b) + { + OMPT_SIGNAL(sem); + c += b; + } +#pragma omp task depend(in : c) + { + OMPT_SIGNAL(sem); + d = c; + } +#pragma omp taskwait {} + } + OMPT_WAIT(sem, 6); + } + + printf("%d\n", d); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB165b-taskdep4-orig-omp50-yes.c b/openmp/tools/archer/tests/races/DRB165b-taskdep4-orig-omp50-yes.c new file mode 100644 index 0000000000000..9c2a60e948f31 --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB165b-taskdep4-orig-omp50-yes.c @@ -0,0 +1,57 @@ +/* + * DRB165b-taskdep4-orig-omp50-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +void foo() { + + int x = 0, y = 2; + +#pragma omp task depend(inout : x) shared(x, sem) + { + OMPT_SIGNAL(sem); + x++; //1st Child Task + } + +#pragma omp task shared(y, sem) + { + OMPT_SIGNAL(sem); + y--; // 2nd child task + } + +#pragma omp taskwait depend(in : x) // 1st taskwait + + printf("x=%d\n", x); + printf("y=%d\n", y); +#pragma omp taskwait // 2nd taskwait +} + +int main() { +#pragma omp parallel + { +#pragma omp masked + foo(); + OMPT_WAIT(sem, 2); + } + + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB168b-taskdep5-orig-omp50-yes.c b/openmp/tools/archer/tests/races/DRB168b-taskdep5-orig-omp50-yes.c new file mode 100644 index 0000000000000..723b81918f257 --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB168b-taskdep5-orig-omp50-yes.c @@ -0,0 +1,56 @@ +/* + * DRB168b-taskdep5-orig-omp50-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +void foo() { + int x = 0, y = 2; + +#pragma omp task depend(inout : x) shared(x, sem) + { + OMPT_SIGNAL(sem); + x++; // 1st child task + } + +#pragma omp task depend(in : x) depend(inout : y) shared(x, y, sem) + { + OMPT_SIGNAL(sem); + y -= x; //2nd child task + } + +#pragma omp taskwait depend(in : x) // 1st taskwait + + printf("x=%d\n", x); + printf("y=%d\n", y); +#pragma omp taskwait // 2nd taskwait +} + +int main() { +#pragma omp parallel num_threads(2) + { +#pragma omp masked + { foo(); } + OMPT_WAIT(sem, 2); + } + + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB173b-non-sibling-taskdep-yes.c b/openmp/tools/archer/tests/races/DRB173b-non-sibling-taskdep-yes.c new file mode 100644 index 0000000000000..c381b603b755d --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB173b-non-sibling-taskdep-yes.c @@ -0,0 +1,55 @@ +/* + * DRB173b-non-sibling-taskdep-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +// XFAIL: * +#include "ompt/ompt-signal.h" +#include +#include + +void foo() { + int a = 0, sem = 0; + +#pragma omp parallel num_threads(2) + { +#pragma omp masked +#pragma omp taskgroup + { +#pragma omp task depend(inout : a) shared(a) + { +#pragma omp task depend(inout : a) shared(a) + OMPT_SIGNAL(sem); + a++; + } + +#pragma omp task depend(inout : a) shared(a) + { +#pragma omp task depend(inout : a) shared(a) + OMPT_SIGNAL(sem); + a++; + } + } + OMPT_WAIT(sem, 2); + } + printf("a=%d\n", a); +} + +int main() { + foo(); + + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB175b-non-sibling-taskdep2-yes.c b/openmp/tools/archer/tests/races/DRB175b-non-sibling-taskdep2-yes.c new file mode 100644 index 0000000000000..ac25988d7e9dc --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB175b-non-sibling-taskdep2-yes.c @@ -0,0 +1,43 @@ +/* + * DRB175b-non-sibling-taskdep2-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +void foo() { + int a = 0, sem = 0; + +#pragma omp parallel + { +#pragma omp task depend(inout : a) shared(a) + { + OMPT_SIGNAL(sem); + a++; + } + if (omp_get_thread_num() != 0) + OMPT_WAIT(sem, omp_get_num_threads()); + } + printf("a=%d\n", a); +} + +int main() { + foo(); + + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/races/DRB177b-fib-taskdep-yes.c b/openmp/tools/archer/tests/races/DRB177b-fib-taskdep-yes.c new file mode 100644 index 0000000000000..f2d746eebafbf --- /dev/null +++ b/openmp/tools/archer/tests/races/DRB177b-fib-taskdep-yes.c @@ -0,0 +1,53 @@ +/* + * DRB177b-fib-taskdep-yes.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run-race | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run-race | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +int fib(int n) { + int i, j, s; + if (n < 2) + return n; +#pragma omp task shared(i, sem) depend(out : i) + { i = fib(n - 1); } +#pragma omp task shared(j, sem) depend(out : j) + { j = fib(n - 2); } +#pragma omp task shared(i, j, s, sem) depend(in : j) + { s = i + j; } +#pragma omp taskwait + return s; +} + +int main(int argc, char **argv) { + int n = 10; + if (argc > 1) + n = atoi(argv[1]); +#pragma omp parallel + { +#pragma omp masked + { + printf("fib(%i) = %i\n", n, fib(n)); + OMPT_SIGNAL(sem); + } + OMPT_WAIT(sem, 1); + } + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: ThreadSanitizer: reported {{[0-9]+}} warnings diff --git a/openmp/tools/archer/tests/task/DRB132b-taskdep4-orig-omp45-no.c b/openmp/tools/archer/tests/task/DRB132b-taskdep4-orig-omp45-no.c new file mode 100644 index 0000000000000..28fe17d71bd8b --- /dev/null +++ b/openmp/tools/archer/tests/task/DRB132b-taskdep4-orig-omp45-no.c @@ -0,0 +1,62 @@ +/* + * DRB132b-taskdep4-orig-omp45-no.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +void foo() { + + int x = 0, y = 2; + +#pragma omp task depend(inout : x) shared(x, sem) + { + OMPT_SIGNAL(sem); + x++; //1st Child Task + } + +#pragma omp task shared(y, sem) + { + OMPT_SIGNAL(sem); + y--; // 2nd child task + } + +#pragma omp task depend(in : x) if (0) // 1st taskwait + {} + + printf("x=%d\n", x); + +#pragma omp taskwait // 2nd taskwait + + printf("y=%d\n", y); +} + +int main() { +#pragma omp parallel + { +#pragma omp masked + foo(); + OMPT_WAIT(sem, 2); + } + + fprintf(stderr, "DONE.\n"); + return 0; +} + +// CHECK-NOT: ThreadSanitizer: data race +// CHECK-NOT: ThreadSanitizer: reported +// CHECK: DONE diff --git a/openmp/tools/archer/tests/task/DRB133b-taskdep5-orig-omp45-no.c b/openmp/tools/archer/tests/task/DRB133b-taskdep5-orig-omp45-no.c new file mode 100644 index 0000000000000..c0fa67e1575ba --- /dev/null +++ b/openmp/tools/archer/tests/task/DRB133b-taskdep5-orig-omp45-no.c @@ -0,0 +1,61 @@ +/* + * DRB133b-taskdep5-orig-omp45-no.c -- Archer testcase + */ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// +// See tools/archer/LICENSE.txt for details. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1 %libarcher-run | FileCheck %s +// RUN: %libarcher-compile && env ARCHER_OPTIONS=tasking=1:ignore_serial=1 %libarcher-run | FileCheck %s +// REQUIRES: tsan +#include "ompt/ompt-signal.h" +#include +#include + +int sem = 0; + +void foo() { + int x = 0, y = 2; + +#pragma omp task depend(inout : x) shared(x, sem) + { + OMPT_SIGNAL(sem); + x++; // 1st child task + } + +#pragma omp task depend(in : x) depend(inout : y) shared(x, y, sem) + { + OMPT_SIGNAL(sem); + y -= x; //2nd child task + } + +#pragma omp task depend(in : x) if (0) // 1st taskwait + {} + + printf("x=%d\n", x); + +#pragma omp taskwait // 2nd taskwait + + printf("y=%d\n", y); +} + +int main() { +#pragma omp parallel num_threads(2) + { +#pragma omp masked + { foo(); } + OMPT_WAIT(sem, 2); + } + + fprintf(stderr, "DONE.\n"); + return 0; +} + +// CHECK-NOT: ThreadSanitizer: data race +// CHECK-NOT: ThreadSanitizer: reported +// CHECK: DONE