[Openmp-commits] [openmp] [OpenMP][Archer] Allow stop-start via omp_control_tool (PR #137939)

via Openmp-commits openmp-commits at lists.llvm.org
Wed Apr 30 02:10:34 PDT 2025


https://github.com/felilxtomski created https://github.com/llvm/llvm-project/pull/137939

Allows Archer to be paused, restarted and completely ended via `omp_control_tool`. TSan will also ignore memory accesses (writes) when Archer is paused or ended.

>From 741838fd30551cb2f4338966915361b90f50b078 Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Tue, 8 Apr 2025 09:37:02 +0200
Subject: [PATCH 1/9] [Archer] Add support for omp_control_tool

---
 openmp/tools/archer/ompt-tsan.cpp | 43 +++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index bb60fc6b603f4..0f7ed862d91c2 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -32,6 +32,7 @@
 #include <vector>
 
 #include "omp-tools.h"
+#include "omp.h" /* For omp_control_tool_result_t */
 
 // Define attribute that indicates that the fall through from the previous
 // case label is intentional and should not be diagnosed by a compiler
@@ -601,6 +602,44 @@ static inline TaskData *ToTaskData(ompt_data_t *task_data) {
 static std::unordered_map<ompt_wait_id_t, std::mutex> Locks;
 static std::mutex LocksMutex;
 
+enum ArcherState { ACTIVE = 0, PAUSED, ENDED };
+static ArcherState archer_state{ACTIVE};
+
+static int ompt_tsan_control_tool(uint64_t command, uint64_t modifier,
+                                  void *arg, const void *codeptr_ra) {
+  omp_control_tool_result_t res = omp_control_tool_ignored;
+  switch (command) {
+  case omp_control_tool_start:
+    if (archer_state == ENDED || archer_state == ACTIVE)
+      return omp_control_tool_ignored;
+    if (archer_flags->verbose)
+      std::cout << "[Archer] Started operation\n";
+    archer_state = ACTIVE;
+    TsanIgnoreWritesEnd();
+    return omp_control_tool_success;
+  case omp_control_tool_pause:
+    if (archer_flags->verbose)
+      std::cout << "[Archer] Paused operation\n";
+    if (archer_state != ENDED) {
+      TsanIgnoreWritesBegin();
+      archer_state = PAUSED;
+    }
+    return omp_control_tool_success;
+  case omp_control_tool_flush:
+    return omp_control_tool_ignored;
+  case omp_control_tool_end:
+    archer_state = ENDED;
+    if (archer_flags->verbose) {
+      std::cout << "[Archer] Ended operation\n";
+    }
+    TsanIgnoreWritesBegin();
+    return omp_control_tool_success;
+  default:
+    return omp_control_tool_ignored;
+  }
+  return res;
+}
+
 static void ompt_tsan_thread_begin(ompt_thread_t thread_type,
                                    ompt_data_t *thread_data) {
   ParallelDataPool::ThreadDataPool = new ParallelDataPool;
@@ -1191,6 +1230,7 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
   findTsanFunction(__tsan_func_entry, (void (*)(const void *)));
   findTsanFunction(__tsan_func_exit, (void (*)(void)));
 
+  SET_CALLBACK(control_tool);
   SET_CALLBACK(thread_begin);
   SET_CALLBACK(thread_end);
   SET_CALLBACK(parallel_begin);
@@ -1221,6 +1261,8 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
 static void ompt_tsan_finalize(ompt_data_t *tool_data) {
   if (archer_flags->ignore_serial)
     TsanIgnoreWritesEnd();
+  if (archer_state == PAUSED || archer_state == ENDED)
+    TsanIgnoreWritesEnd();
   if (archer_flags->print_max_rss) {
     struct rusage end;
     getrusage(RUSAGE_SELF, &end);
@@ -1238,6 +1280,7 @@ ompt_start_tool(unsigned int omp_version, const char *runtime_version) {
   if (!archer_flags->enabled) {
     if (archer_flags->verbose)
       std::cout << "Archer disabled, stopping operation" << std::endl;
+    archer_state = ENDED;
     delete archer_flags;
     return NULL;
   }

>From ccf97a6892ba56d5434f5e6cf65810821a193d6e Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Tue, 8 Apr 2025 09:51:46 +0200
Subject: [PATCH 2/9] [Archer] Make archer state thread local

---
 openmp/tools/archer/ompt-tsan.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index 0f7ed862d91c2..7a231a68d36f9 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -603,7 +603,7 @@ static std::unordered_map<ompt_wait_id_t, std::mutex> Locks;
 static std::mutex LocksMutex;
 
 enum ArcherState { ACTIVE = 0, PAUSED, ENDED };
-static ArcherState archer_state{ACTIVE};
+static thread_local ArcherState archer_state{ACTIVE};
 
 static int ompt_tsan_control_tool(uint64_t command, uint64_t modifier,
                                   void *arg, const void *codeptr_ra) {

>From 3429780da9a879ae323df8339ebfb7833594abf2 Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Tue, 29 Apr 2025 15:33:11 +0200
Subject: [PATCH 3/9] [Archer] Add tests for omp_control_tool

---
 .../tests/control-tool/skipped-access.c       | 42 +++++++++++++++++
 .../tests/control-tool/skipped-barrier.c      | 44 ++++++++++++++++++
 .../tests/control-tool/verbose-output.c       | 46 +++++++++++++++++++
 openmp/tools/archer/tests/lit.cfg             |  6 +++
 4 files changed, 138 insertions(+)
 create mode 100644 openmp/tools/archer/tests/control-tool/skipped-access.c
 create mode 100644 openmp/tools/archer/tests/control-tool/skipped-barrier.c
 create mode 100644 openmp/tools/archer/tests/control-tool/verbose-output.c

diff --git a/openmp/tools/archer/tests/control-tool/skipped-access.c b/openmp/tools/archer/tests/control-tool/skipped-access.c
new file mode 100644
index 0000000000000..db386154e1fdb
--- /dev/null
+++ b/openmp/tools/archer/tests/control-tool/skipped-access.c
@@ -0,0 +1,42 @@
+/*
+ * barrier.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-and-run-verbose | FileCheck %s
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  int var = 0;
+
+#pragma omp parallel num_threads(2) shared(var)
+  {
+    if (omp_get_thread_num() == 0) {
+      var++;
+    }
+
+    /* We miss the race due to Archer being paused */
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+    if (omp_get_thread_num() == 1) {
+      var++;
+    }
+    omp_control_tool(omp_control_tool_start, 0, NULL);
+  }
+
+  fprintf(stderr, "DONE\n");
+  return 0;
+}
+
+// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: reported
+// CHECK: DONE
diff --git a/openmp/tools/archer/tests/control-tool/skipped-barrier.c b/openmp/tools/archer/tests/control-tool/skipped-barrier.c
new file mode 100644
index 0000000000000..f3b1d17b7cfec
--- /dev/null
+++ b/openmp/tools/archer/tests/control-tool/skipped-barrier.c
@@ -0,0 +1,44 @@
+/*
+ * barrier.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-and-run-race-verbose | FileCheck %s
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  int var = 0;
+
+#pragma omp parallel num_threads(2) shared(var)
+  {
+    if (omp_get_thread_num() == 0) {
+      var++;
+    }
+
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+#pragma omp barrier
+    omp_control_tool(omp_control_tool_start, 0, NULL);
+
+    if (omp_get_thread_num() == 1) {
+      var++;
+    }
+  }
+
+  fprintf(stderr, "DONE\n");
+  int error = (var != 2);
+  return error;
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: DONE
+// CHECK: ThreadSanitizer: reported {{[1]}} warnings
diff --git a/openmp/tools/archer/tests/control-tool/verbose-output.c b/openmp/tools/archer/tests/control-tool/verbose-output.c
new file mode 100644
index 0000000000000..8979118758bf4
--- /dev/null
+++ b/openmp/tools/archer/tests/control-tool/verbose-output.c
@@ -0,0 +1,46 @@
+/*
+ * verbose-output.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-and-run-verbose | FileCheck %s
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+
+#pragma omp parallel num_threads(1)
+{
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+//    omp_control_tool(omp_control_tool_start, 0, NULL);
+//    omp_control_tool(omp_control_tool_end, 0, NULL);
+}
+
+//#pragma omp parallel num_threads(2)
+//{
+//    omp_control_tool(omp_control_tool_pause, 0, NULL);
+//    omp_control_tool(omp_control_tool_start, 0, NULL);
+//}
+
+  fprintf(stderr, "DONE\n");
+  return 0;
+}
+
+// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: reported
+// CHECK-NOT: Warning: please export TSAN_OPTIONS
+// CHECK: DONE
+// CHECK: [Archer] Paused operation
+// CHECK: [Archer] Started operation
+// CHECK: [Archer] Ended operation
+
diff --git a/openmp/tools/archer/tests/lit.cfg b/openmp/tools/archer/tests/lit.cfg
index f8fbcad752a4c..a4383ac759b0b 100644
--- a/openmp/tools/archer/tests/lit.cfg
+++ b/openmp/tools/archer/tests/lit.cfg
@@ -104,10 +104,16 @@ config.environment['ARCHER_OPTIONS'] = "report_data_leak=1"
 config.substitutions.append(("%libarcher-compile-and-run-race-noserial", \
     "%%libarcher-compile && env ARCHER_OPTIONS=\"ignore_serial=1 %s\" %%libarcher-run-race" \
     % config.environment['ARCHER_OPTIONS']))
+config.substitutions.append(("%libarcher-compile-and-run-race-verbose", \
+    "%%libarcher-compile && env ARCHER_OPTIONS=\"verbose=1 %s\" %%libarcher-run-race" \
+    % config.environment['ARCHER_OPTIONS']))
 config.substitutions.append(("%libarcher-compile-and-run-race", \
     "%libarcher-compile && %libarcher-run-race"))
 config.substitutions.append(("%libarcher-compile-and-run-nosuppression", \
                              "%libarcher-compile && %libarcher-run-nosuppression"))
+config.substitutions.append(("%libarcher-compile-and-run-verbose", \
+    "%%libarcher-compile && env ARCHER_OPTIONS=\"verbose=1 %s\" %%libarcher-run" \
+    % config.environment['ARCHER_OPTIONS']))
 config.substitutions.append(("%libarcher-compile-and-run", \
                              "%libarcher-compile && %libarcher-run"))
 config.substitutions.append(("%libarcher-cxx-compile-and-run", \

>From dd13584f1bef4dc4df030f2f3737bf9fce7c603c Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 30 Apr 2025 08:09:18 +0200
Subject: [PATCH 4/9] Fix mismatch between TsanIgnoreWritesBegin and End

---
 openmp/tools/archer/ompt-tsan.cpp | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index 7a231a68d36f9..f6897da0bddf9 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -620,7 +620,7 @@ static int ompt_tsan_control_tool(uint64_t command, uint64_t modifier,
   case omp_control_tool_pause:
     if (archer_flags->verbose)
       std::cout << "[Archer] Paused operation\n";
-    if (archer_state != ENDED) {
+    if (archer_state == ACTIVE) {
       TsanIgnoreWritesBegin();
       archer_state = PAUSED;
     }
@@ -628,11 +628,12 @@ static int ompt_tsan_control_tool(uint64_t command, uint64_t modifier,
   case omp_control_tool_flush:
     return omp_control_tool_ignored;
   case omp_control_tool_end:
-    archer_state = ENDED;
     if (archer_flags->verbose) {
       std::cout << "[Archer] Ended operation\n";
     }
-    TsanIgnoreWritesBegin();
+    if (archer_state == ACTIVE)
+      TsanIgnoreWritesBegin();
+    archer_state = ENDED;
     return omp_control_tool_success;
   default:
     return omp_control_tool_ignored;
@@ -664,6 +665,8 @@ static void ompt_tsan_thread_end(ompt_data_t *thread_data) {
   delete TaskDataPool::ThreadDataPool;
   delete DependencyDataPool::ThreadDataPool;
   TsanIgnoreWritesEnd();
+  if (archer_state != ACTIVE)
+    TsanIgnoreWritesEnd();
 }
 
 /// OMPT event callbacks for handling parallel regions.
@@ -1261,8 +1264,8 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
 static void ompt_tsan_finalize(ompt_data_t *tool_data) {
   if (archer_flags->ignore_serial)
     TsanIgnoreWritesEnd();
-  if (archer_state == PAUSED || archer_state == ENDED)
-    TsanIgnoreWritesEnd();
+//  if (archer_state == PAUSED || archer_state == ENDED)
+//    TsanIgnoreWritesEnd();
   if (archer_flags->print_max_rss) {
     struct rusage end;
     getrusage(RUSAGE_SELF, &end);

>From c4838773539c28a01d7cf22d7488467d77ac0716 Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 30 Apr 2025 09:35:12 +0200
Subject: [PATCH 5/9] [Archer] Ignore happens before/after if archer is
 disabled

---
 openmp/tools/archer/ompt-tsan.cpp | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index f6897da0bddf9..d2563bc79874d 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -53,6 +53,9 @@
 
 static int hasReductionCallback;
 
+enum ArcherState { ACTIVE = 0, PAUSED, ENDED };
+static thread_local ArcherState archer_state{ACTIVE};
+
 namespace {
 class ArcherFlags {
 public:
@@ -172,10 +175,18 @@ DECLARE_TSAN_FUNCTION(__tsan_func_exit)
 // This marker is used to define a happens-before arc. The race detector will
 // infer an arc from the begin to the end when they share the same pointer
 // argument.
-#define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__, __LINE__, cv)
+#define TsanHappensBefore(cv) \
+do { \ 
+  if (archer_state ==ACTIVE) \
+      AnnotateHappensBefore(__FILE__, __LINE__, cv); \
+} while(0)
 
 // This marker defines the destination of a happens-before arc.
-#define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__, __LINE__, cv)
+#define TsanHappensAfter(cv) \
+do { \ 
+  if (archer_state ==ACTIVE) \
+      AnnotateHappensAfter(__FILE__, __LINE__, cv); \
+} while(0)
 
 // Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
 #define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
@@ -602,9 +613,6 @@ static inline TaskData *ToTaskData(ompt_data_t *task_data) {
 static std::unordered_map<ompt_wait_id_t, std::mutex> Locks;
 static std::mutex LocksMutex;
 
-enum ArcherState { ACTIVE = 0, PAUSED, ENDED };
-static thread_local ArcherState archer_state{ACTIVE};
-
 static int ompt_tsan_control_tool(uint64_t command, uint64_t modifier,
                                   void *arg, const void *codeptr_ra) {
   omp_control_tool_result_t res = omp_control_tool_ignored;

>From b5e8b27d1a912c4ffe19c8c1e972f0e300f197c9 Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 30 Apr 2025 09:35:40 +0200
Subject: [PATCH 6/9] [Archer] More extensive tests for tool control

---
 .../tests/control-tool/skipped-barrier.c      |  2 +-
 .../tests/control-tool/verbose-output.c       | 26 +++++++++++++------
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/openmp/tools/archer/tests/control-tool/skipped-barrier.c b/openmp/tools/archer/tests/control-tool/skipped-barrier.c
index f3b1d17b7cfec..f2f6544a38c0b 100644
--- a/openmp/tools/archer/tests/control-tool/skipped-barrier.c
+++ b/openmp/tools/archer/tests/control-tool/skipped-barrier.c
@@ -35,7 +35,7 @@ int main(int argc, char *argv[]) {
   }
 
   fprintf(stderr, "DONE\n");
-  int error = (var != 2);
+  int error = 1;
   return error;
 }
 
diff --git a/openmp/tools/archer/tests/control-tool/verbose-output.c b/openmp/tools/archer/tests/control-tool/verbose-output.c
index 8979118758bf4..9b1d8eb47948e 100644
--- a/openmp/tools/archer/tests/control-tool/verbose-output.c
+++ b/openmp/tools/archer/tests/control-tool/verbose-output.c
@@ -19,23 +19,33 @@
 
 int main(int argc, char *argv[]) {
 
+#pragma omp parallel num_threads(2)
+{
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+    omp_control_tool(omp_control_tool_start, 0, NULL);
+}
+
+#pragma omp parallel num_threads(2)
+{
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+}
+
 #pragma omp parallel num_threads(1)
 {
     omp_control_tool(omp_control_tool_pause, 0, NULL);
-//    omp_control_tool(omp_control_tool_start, 0, NULL);
-//    omp_control_tool(omp_control_tool_end, 0, NULL);
 }
 
-//#pragma omp parallel num_threads(2)
-//{
-//    omp_control_tool(omp_control_tool_pause, 0, NULL);
-//    omp_control_tool(omp_control_tool_start, 0, NULL);
-//}
+#pragma omp parallel num_threads(2)
+{
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+    omp_control_tool(omp_control_tool_start, 0, NULL);
+    omp_control_tool(omp_control_tool_end, 0, NULL);
+}
 
   fprintf(stderr, "DONE\n");
   return 0;
 }
-
+// CHECK-NOT: One of the following ignores was not ended
 // CHECK-NOT: ThreadSanitizer: data race
 // CHECK-NOT: ThreadSanitizer: reported
 // CHECK-NOT: Warning: please export TSAN_OPTIONS

>From 7b2a6c6697911e95c1cb4447b3e32cabe40ccef0 Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 30 Apr 2025 09:36:36 +0200
Subject: [PATCH 7/9] [Archer] clang-format

---
 openmp/tools/archer/ompt-tsan.cpp             | 22 +++++-----
 .../tools/archer/tests/control-tool/ended.c   | 43 +++++++++++++++++++
 .../tests/control-tool/skipped-access.c       |  2 +-
 .../tests/control-tool/skipped-barrier.c      |  3 +-
 .../tests/control-tool/verbose-output.c       | 20 ++++-----
 5 files changed, 64 insertions(+), 26 deletions(-)
 create mode 100644 openmp/tools/archer/tests/control-tool/ended.c

diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index d2563bc79874d..c08a1ec52b152 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -175,18 +175,18 @@ DECLARE_TSAN_FUNCTION(__tsan_func_exit)
 // This marker is used to define a happens-before arc. The race detector will
 // infer an arc from the begin to the end when they share the same pointer
 // argument.
-#define TsanHappensBefore(cv) \
-do { \ 
-  if (archer_state ==ACTIVE) \
-      AnnotateHappensBefore(__FILE__, __LINE__, cv); \
-} while(0)
+#define TsanHappensBefore(cv)                                                  \
+  do {                                                                         \
+    if (archer_state == ACTIVE)                                                \
+      AnnotateHappensBefore(__FILE__, __LINE__, cv);                           \
+  } while (0)
 
 // This marker defines the destination of a happens-before arc.
-#define TsanHappensAfter(cv) \
-do { \ 
-  if (archer_state ==ACTIVE) \
-      AnnotateHappensAfter(__FILE__, __LINE__, cv); \
-} while(0)
+#define TsanHappensAfter(cv)                                                   \
+  do {                                                                         \
+    if (archer_state == ACTIVE)                                                \
+      AnnotateHappensAfter(__FILE__, __LINE__, cv);                            \
+  } while (0)
 
 // Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
 #define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
@@ -1272,8 +1272,6 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
 static void ompt_tsan_finalize(ompt_data_t *tool_data) {
   if (archer_flags->ignore_serial)
     TsanIgnoreWritesEnd();
-//  if (archer_state == PAUSED || archer_state == ENDED)
-//    TsanIgnoreWritesEnd();
   if (archer_flags->print_max_rss) {
     struct rusage end;
     getrusage(RUSAGE_SELF, &end);
diff --git a/openmp/tools/archer/tests/control-tool/ended.c b/openmp/tools/archer/tests/control-tool/ended.c
new file mode 100644
index 0000000000000..1b49e0f119be3
--- /dev/null
+++ b/openmp/tools/archer/tests/control-tool/ended.c
@@ -0,0 +1,43 @@
+/*
+ * ended.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-and-run-verbose | FileCheck %s
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  int var = 0;
+
+#pragma omp parallel
+  { omp_control_tool(omp_control_tool_end, 0, NULL); }
+
+#pragma omp parallel num_threads(2) shared(var)
+  {
+    if (omp_get_thread_num() == 0) {
+      var++;
+    }
+
+    /* We miss the race due to Archer being paused */
+    if (omp_get_thread_num() == 1) {
+      var++;
+    }
+  }
+
+  fprintf(stderr, "DONE\n");
+  return 0;
+}
+
+// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: reported
+// CHECK: DONE
diff --git a/openmp/tools/archer/tests/control-tool/skipped-access.c b/openmp/tools/archer/tests/control-tool/skipped-access.c
index db386154e1fdb..5ac5a138d64c1 100644
--- a/openmp/tools/archer/tests/control-tool/skipped-access.c
+++ b/openmp/tools/archer/tests/control-tool/skipped-access.c
@@ -1,5 +1,5 @@
 /*
- * barrier.c -- Archer testcase
+ * skipped-access.c -- Archer testcase
  */
 
 //===----------------------------------------------------------------------===//
diff --git a/openmp/tools/archer/tests/control-tool/skipped-barrier.c b/openmp/tools/archer/tests/control-tool/skipped-barrier.c
index f2f6544a38c0b..626b450114a05 100644
--- a/openmp/tools/archer/tests/control-tool/skipped-barrier.c
+++ b/openmp/tools/archer/tests/control-tool/skipped-barrier.c
@@ -1,5 +1,5 @@
 /*
- * barrier.c -- Archer testcase
+ * skipped-barrier.c -- Archer testcase
  */
 
 //===----------------------------------------------------------------------===//
@@ -25,6 +25,7 @@ int main(int argc, char *argv[]) {
       var++;
     }
 
+    /* TSan detects a race as Archer does not see the barrier */
     omp_control_tool(omp_control_tool_pause, 0, NULL);
 #pragma omp barrier
     omp_control_tool(omp_control_tool_start, 0, NULL);
diff --git a/openmp/tools/archer/tests/control-tool/verbose-output.c b/openmp/tools/archer/tests/control-tool/verbose-output.c
index 9b1d8eb47948e..bd73593e72e82 100644
--- a/openmp/tools/archer/tests/control-tool/verbose-output.c
+++ b/openmp/tools/archer/tests/control-tool/verbose-output.c
@@ -11,7 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-
 // RUN: %libarcher-compile-and-run-verbose | FileCheck %s
 // REQUIRES: tsan
 #include <omp.h>
@@ -20,32 +19,30 @@
 int main(int argc, char *argv[]) {
 
 #pragma omp parallel num_threads(2)
-{
+  {
+    omp_control_tool(omp_control_tool_start, 0, NULL);
     omp_control_tool(omp_control_tool_pause, 0, NULL);
     omp_control_tool(omp_control_tool_start, 0, NULL);
-}
+  }
 
 #pragma omp parallel num_threads(2)
-{
-    omp_control_tool(omp_control_tool_pause, 0, NULL);
-}
+  { omp_control_tool(omp_control_tool_pause, 0, NULL); }
 
 #pragma omp parallel num_threads(1)
-{
-    omp_control_tool(omp_control_tool_pause, 0, NULL);
-}
+  { omp_control_tool(omp_control_tool_pause, 0, NULL); }
 
 #pragma omp parallel num_threads(2)
-{
+  {
     omp_control_tool(omp_control_tool_pause, 0, NULL);
     omp_control_tool(omp_control_tool_start, 0, NULL);
     omp_control_tool(omp_control_tool_end, 0, NULL);
-}
+  }
 
   fprintf(stderr, "DONE\n");
   return 0;
 }
 // CHECK-NOT: One of the following ignores was not ended
+// CHECK-NOT: finished with ignores enabled
 // CHECK-NOT: ThreadSanitizer: data race
 // CHECK-NOT: ThreadSanitizer: reported
 // CHECK-NOT: Warning: please export TSAN_OPTIONS
@@ -53,4 +50,3 @@ int main(int argc, char *argv[]) {
 // CHECK: [Archer] Paused operation
 // CHECK: [Archer] Started operation
 // CHECK: [Archer] Ended operation
-

>From 29f248ece35016f7292dff49733d30176d0ae9fd Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 30 Apr 2025 10:39:03 +0200
Subject: [PATCH 8/9] [Archer] Add info on omp_control_tool to readme

---
 openmp/tools/archer/README.md | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/openmp/tools/archer/README.md b/openmp/tools/archer/README.md
index b52626116d0f9..6cd614a418994 100644
--- a/openmp/tools/archer/README.md
+++ b/openmp/tools/archer/README.md
@@ -230,6 +230,35 @@ the report will look as follow:
 
 <a id="orgcc38a36"></a>
 
+## Pausing Analysis
+
+Archer's analysis may be paused, restarted or ended using OpenMP's
+omp_control_tool functionality with omp_control_tool_[pause|start|end].
+
+Suppose a parallel for loop shall not be considered by Archer:
+
+     1  #include <stdio.h>
+     2  #include <omp.h>
+     3
+     4  #define N 1000
+     5
+     6  int main (int argc, char **argv)
+     7  {
+     8    int a[N];
+     9
+    10  #pragma omp parallel
+    11  {
+    12    omp_control_tool(omp_control_tool_pause, 0, NULL);
+    13  #pragma omp for
+    14    for (int i = 0; i < N - 1; i++) {
+    15      a[i] = a[i + 1];
+    16    }
+    17    omp_control_tool(omp_control_tool_start, 0, NULL);
+    18  }
+    19  }
+
+For more information on the usage of omp_control_tool, see the OpenMP specification.
+
 # Contacts and Support
 
 -   [Google group](https://groups.google.com/forum/#!forum/archer-pruner)

>From 71e4b8eb8eaaed9c8e779e100816a3506378fb49 Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 30 Apr 2025 11:04:04 +0200
Subject: [PATCH 9/9] Add tasking constructs to control tool tests

---
 .../tests/control-tool/verbose-output.c       | 34 ++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/openmp/tools/archer/tests/control-tool/verbose-output.c b/openmp/tools/archer/tests/control-tool/verbose-output.c
index bd73593e72e82..528c83f840419 100644
--- a/openmp/tools/archer/tests/control-tool/verbose-output.c
+++ b/openmp/tools/archer/tests/control-tool/verbose-output.c
@@ -13,11 +13,41 @@
 
 // RUN: %libarcher-compile-and-run-verbose | FileCheck %s
 // REQUIRES: tsan
+#include "ompt/ompt-signal.h"
 #include <omp.h>
 #include <stdio.h>
 
-int main(int argc, char *argv[]) {
+void foo() {
+
+  int x = 0, y = 2, sem = 0;
 
+#pragma omp task depend(inout : x) shared(x, sem)
+  {
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+    OMPT_SIGNAL(sem);
+    x++; // 1st Child Task
+  }
+
+#pragma omp task shared(y, sem)
+  {
+    omp_control_tool(omp_control_tool_pause, 0, NULL);
+    OMPT_SIGNAL(sem);
+    y--; // 2nd child task
+  }
+
+  OMPT_WAIT(sem, 2);
+#pragma omp taskwait depend(in : x) // 1st taskwait
+
+  printf("x=%d\n", x);
+
+#pragma omp taskwait // 2nd taskwait
+
+  printf("y=%d\n", y);
+}
+
+int main(int argc, char *argv[]) {
+  /* Try out different OpenMP constructs to check whether Tsan IgnoreBegin/Ends
+   * are matched correctly */
 #pragma omp parallel num_threads(2)
   {
     omp_control_tool(omp_control_tool_start, 0, NULL);
@@ -38,6 +68,8 @@ int main(int argc, char *argv[]) {
     omp_control_tool(omp_control_tool_end, 0, NULL);
   }
 
+  foo();
+
   fprintf(stderr, "DONE\n");
   return 0;
 }



More information about the Openmp-commits mailing list