[compiler-rt] [openmp] [OpenMP][Archer][TSan] Use TSan fibers to implement task-centric analysis for OpenMP tasks (PR #74646)

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 6 11:18:15 PST 2023


https://github.com/jprotze created https://github.com/llvm/llvm-project/pull/74646

Current thread-level analysis can hide a lot of data races in OpenMP tasking codes, when tasks are randomly scheduled to the same thread, but even worse when unrelated task dependencies introduce random synchronization between different threads.
This patch introduces a new analysis mode for Archer activated at runtime by exporting `ARCHER_OPTION=tasking=1`, where OpenMP tasks are explicitly mapped to TSan fibers.

@dvyukov For debugging some corner cases, we found it helpful to add some assertions to the fiber interface. Furthermore, the FiberCreate function at the moment ignores the flag argument, so we added handling for the flag. For FiberSwitch, we would simply return immediately, if the Fiber is already active.

>From dc6034ec517ea1188e803a5651f2e2f497ee508a Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Fri, 1 Dec 2023 00:18:56 +0100
Subject: [PATCH] Add tasking support in archer via fibers

---
 compiler-rt/lib/tsan/rtl/tsan_rtl.h           |   1 +
 compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp  |   6 +
 openmp/runtime/src/ompt-specific.cpp          |   4 +
 openmp/tools/archer/ompt-tsan.cpp             | 235 +++++++++++++-----
 .../DRB027b-taskdependmissing-orig-yes.c      |  46 ++++
 .../races/DRB131b-taskdep4-orig-omp45-yes.c   |  59 +++++
 .../races/DRB134b-taskdep5-orig-omp45-yes.c   |  62 +++++
 .../DRB136b-taskdep-mutexinoutset-orig-yes.c  |  67 +++++
 .../races/DRB165b-taskdep4-orig-omp50-yes.c   |  58 +++++
 .../races/DRB168b-taskdep5-orig-omp50-yes.c   |  60 +++++
 .../races/DRB173b-non-sibling-taskdep-yes.c   |  55 ++++
 .../races/DRB175b-non-sibling-taskdep2-yes.c  |  43 ++++
 .../tests/races/DRB177b-fib-taskdep-yes.c     |  59 +++++
 .../task/DRB132b-taskdep4-orig-omp45-no.c     |  63 +++++
 .../task/DRB133b-taskdep5-orig-omp45-no.c     |  63 +++++
 15 files changed, 814 insertions(+), 67 deletions(-)
 create mode 100644 openmp/tools/archer/tests/races/DRB027b-taskdependmissing-orig-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB131b-taskdep4-orig-omp45-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB134b-taskdep5-orig-omp45-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB136b-taskdep-mutexinoutset-orig-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB165b-taskdep4-orig-omp50-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB168b-taskdep5-orig-omp50-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB173b-non-sibling-taskdep-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB175b-non-sibling-taskdep2-yes.c
 create mode 100644 openmp/tools/archer/tests/races/DRB177b-fib-taskdep-yes.c
 create mode 100644 openmp/tools/archer/tests/task/DRB132b-taskdep4-orig-omp45-no.c
 create mode 100644 openmp/tools/archer/tests/task/DRB133b-taskdep5-orig-omp45-no.c

diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index de4ea0bb5f487..559a10c4119f4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -801,6 +801,7 @@ void FuncExit(ThreadState *thr) {
 #if !SANITIZER_GO
   DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
 #endif
+  CHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
   thr->shadow_stack_pos--;
 }
 
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<ThreadState *>(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..28f9f82397742 100644
--- a/openmp/runtime/src/ompt-specific.cpp
+++ b/openmp/runtime/src/ompt-specific.cpp
@@ -476,9 +476,13 @@ 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..ab5dccfb39d0c 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 #include <cstdlib>
 #include <cstring>
+#include <dlfcn.h>
 #include <inttypes.h>
 #include <iostream>
 #include <list>
@@ -52,7 +53,7 @@
 
 static int hasReductionCallback;
 
-namespace {
+namespace __archer {
 class ArcherFlags {
 public:
 #if (LLVM_VERSION) >= 40
@@ -64,34 +65,50 @@ class ArcherFlags {
   int report_data_leak{0};
   int ignore_serial{0};
   std::atomic<int> all_memory{0};
+  int tasking{0};
+  int stack_size{1024};
+  std::atomic<int> untieds{0};
 
   ArcherFlags(const char *env) {
     if (env) {
       std::vector<std::string> 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<std::string>::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(it->c_str(), "verbose=%d", &verbose))
+        if (sscanf(token.c_str(), "report_data_leak=%d", &report_data_leak))
           continue;
-        if (sscanf(it->c_str(), "report_data_leak=%d", &report_data_leak))
+        if (sscanf(token.c_str(), "enable=%d", &enabled))
           continue;
-        if (sscanf(it->c_str(), "enable=%d", &enabled))
+        if (sscanf(token.c_str(), "tasking=%d", &tasking))
           continue;
-        if (sscanf(it->c_str(), "ignore_serial=%d", &ignore_serial))
+        if (sscanf(token.c_str(), "stack_size=%d", &stack_size))
           continue;
-        if (sscanf(it->c_str(), "all_memory=%d", &tmp_int)) {
+        if (sscanf(token.c_str(), "ignore_serial=%d", &ignore_serial))
+          continue;
+        if (sscanf(token.c_str(), "all_memory=%d", &tmp_int)) {
           all_memory = tmp_int;
           continue;
         }
@@ -135,7 +152,9 @@ class TsanFlags {
     }
   }
 };
-} // namespace
+
+static ArcherFlags *archer_flags;
+} // namespace __archer
 
 #if (LLVM_VERSION) >= 40
 extern "C" {
@@ -143,7 +162,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 +177,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 +211,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 +230,11 @@ static uint64_t my_next_id() {
   return ret;
 }
 
-static int pagesize{0};
-
 // Data structure to provide a threadsafe pool of reusable objects.
 // DataPool<Type of objects>
-namespace {
+namespace __archer {
+static int pagesize{0};
+
 template <typename T> struct DataPool final {
   static __thread DataPool<T> *ThreadDataPool;
   std::mutex DPMutex{};
@@ -399,7 +428,7 @@ struct ParallelData final : DataPoolEntry<ParallelData> {
   void *GetBarrierPtr(unsigned Index) { return &(Barrier[Index]); }
 
   ParallelData *Init(const void *codeptr) {
-    codePtr = codeptr;
+    this->codePtr = codeptr;
     return this;
   }
 
@@ -474,6 +503,10 @@ struct TaskData final : DataPoolEntry<TaskData> {
   /// 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 +536,13 @@ struct TaskData final : DataPoolEntry<TaskData> {
   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 +567,8 @@ struct TaskData final : DataPoolEntry<TaskData> {
   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 +578,8 @@ struct TaskData final : DataPoolEntry<TaskData> {
       // 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 +588,17 @@ struct TaskData final : DataPoolEntry<TaskData> {
     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 +607,8 @@ struct TaskData final : DataPoolEntry<TaskData> {
     Parent = nullptr;
     Team = nullptr;
     TaskGroup = nullptr;
+    PrivateDataSize = 0;
+    PrivateDataAddr = nullptr;
     if (DependencyMap) {
       for (auto i : *DependencyMap)
         i.second->Delete();
@@ -572,8 +624,9 @@ struct TaskData final : DataPoolEntry<TaskData> {
 #endif
   }
 
-  static TaskData *New(TaskData *parent, int taskType) {
-    return DataPoolEntry<TaskData>::New()->Init(parent, taskType);
+  static TaskData *New(TaskData *parent, int taskType,
+                       const void *codePtr = nullptr) {
+    return DataPoolEntry<TaskData>::New()->Init(parent, taskType, codePtr);
   }
 
   static TaskData *New(ParallelData *team, int taskType) {
@@ -582,7 +635,6 @@ struct TaskData final : DataPoolEntry<TaskData> {
 
   TaskData(DataPool<TaskData> *dp) : DataPoolEntry<TaskData>(dp) {}
 };
-} // namespace
 
 static inline TaskData *ToTaskData(ompt_data_t *task_data) {
   if (task_data)
@@ -608,6 +660,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 +906,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);
+  } 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;
-  } else if (type & ompt_task_explicit || type & ompt_task_target) {
-    Data = TaskData::New(ToTaskData(parent_task_data), type);
-    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 +1008,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 +1019,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 +1049,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 +1068,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 +1208,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 +1237,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 +1252,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 +1271,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 +1297,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 +1342,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/races/DRB027b-taskdependmissing-orig-yes.c b/openmp/tools/archer/tests/races/DRB027b-taskdependmissing-orig-yes.c
new file mode 100644
index 0000000000000..cd1fec9ec63f8
--- /dev/null
+++ b/openmp/tools/archer/tests/races/DRB027b-taskdependmissing-orig-yes.c
@@ -0,0 +1,46 @@
+/*
+ * 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 <assert.h> 
+#include <stdio.h> 
+#include "ompt/ompt-signal.h"
+
+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..01535a696b7e0
--- /dev/null
+++ b/openmp/tools/archer/tests/races/DRB131b-taskdep4-orig-omp45-yes.c
@@ -0,0 +1,59 @@
+/*
+ * 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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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..d18ad43c259b9
--- /dev/null
+++ b/openmp/tools/archer/tests/races/DRB134b-taskdep5-orig-omp45-yes.c
@@ -0,0 +1,62 @@
+/*
+ * 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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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..39d991c18b48e
--- /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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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..d2b14aee4b406
--- /dev/null
+++ b/openmp/tools/archer/tests/races/DRB165b-taskdep4-orig-omp50-yes.c
@@ -0,0 +1,58 @@
+/*
+ * 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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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..67db4aa942256
--- /dev/null
+++ b/openmp/tools/archer/tests/races/DRB168b-taskdep5-orig-omp50-yes.c
@@ -0,0 +1,60 @@
+/*
+ * 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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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..a5651ae74151f
--- /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 <omp.h>
+#include <stdio.h>
+#include "ompt/ompt-signal.h"
+
+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..f38b916cea919
--- /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 <omp.h>
+#include <stdio.h>
+#include "ompt/ompt-signal.h"
+
+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..a6a49018bbedf
--- /dev/null
+++ b/openmp/tools/archer/tests/races/DRB177b-fib-taskdep-yes.c
@@ -0,0 +1,59 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "ompt/ompt-signal.h"
+
+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..0aa254661593d
--- /dev/null
+++ b/openmp/tools/archer/tests/task/DRB132b-taskdep4-orig-omp45-no.c
@@ -0,0 +1,63 @@
+/*
+ * 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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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..4745fa1b32113
--- /dev/null
+++ b/openmp/tools/archer/tests/task/DRB133b-taskdep5-orig-omp45-no.c
@@ -0,0 +1,63 @@
+/*
+ * 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 <stdio.h>
+#include <omp.h>
+#include "ompt/ompt-signal.h"
+
+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



More information about the llvm-commits mailing list