[llvm-branch-commits] [openmp] release/22.x: [OpenMP][OMPT] Fix `omp_control_tool` before any directive (#191429) (PR #192062)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Apr 14 06:56:30 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/192062

Backport c6bcd19

Requested by: @jprotze

>From 1f06cd11e311e9296272c391dca4c86708812d02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Andr=C3=A9=20Reuter?= <j.reuter at fz-juelich.de>
Date: Fri, 10 Apr 2026 17:07:07 +0200
Subject: [PATCH] [OpenMP][OMPT] Fix `omp_control_tool` before any directive
 (#191429)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When a user calls `omp_control_tool`, a tool is attached and it
registered the `ompt_control_tool` callback, the tool should receive a
callback with the users arguments.

However, in #112924, it was discovered that this only happens after at
least one host side directive or runtime call calling into
`__kmp_do_middle_initialize` has been executed.

The check for `__kmp_init_middle` in `FTN_CONTROL_TOOL` did not try to
do the middle initialization and instead always returned `-2` (no tool).
A tool therefore received no callback. The user program did not get the
info that there is a tool attached. To fix this, change the explicit
return to a call of `__kmp_middle_initialize()`, as done in several
other places of `libomp`.

Further handling is then done in `__kmp_control_tool`, where the values
`-2` (no tool), `-1` (no callback), or the tools return value are
returned.

Also expand the tests to introduce checks where no callaback is
registered, or `omp_control_tool` is called before any OpenMP directive.

Fixes #112924

CC @jprotze, @hansangbae

Signed-off-by: Jan André Reuter <j.reuter at fz-juelich.de>
(cherry picked from commit c6bcd194259e276aacadae8ac0d25680afc9489d)
---
 openmp/runtime/src/kmp_ftn_entry.h            |  2 +-
 openmp/runtime/test/ompt/callback.h           |  2 +
 openmp/runtime/test/ompt/misc/control_tool.c  |  5 ++-
 .../ompt/misc/control_tool_before_directive.c | 43 +++++++++++++++++++
 .../test/ompt/misc/control_tool_no_callback.c | 29 +++++++++++++
 .../ompt/misc/control_tool_no_ompt_support.c  | 10 ++++-
 6 files changed, 88 insertions(+), 3 deletions(-)
 create mode 100644 openmp/runtime/test/ompt/misc/control_tool_before_directive.c
 create mode 100644 openmp/runtime/test/ompt/misc/control_tool_no_callback.c

diff --git a/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h
index 6adf60e7ad210..dc57a6a74668e 100644
--- a/openmp/runtime/src/kmp_ftn_entry.h
+++ b/openmp/runtime/src/kmp_ftn_entry.h
@@ -387,7 +387,7 @@ int FTN_STDCALL FTN_CONTROL_TOOL(int command, int modifier, void *arg) {
 #else
   OMPT_STORE_RETURN_ADDRESS(__kmp_entry_gtid());
   if (!TCR_4(__kmp_init_middle)) {
-    return -2;
+    __kmp_middle_initialize();
   }
   kmp_info_t *this_thr = __kmp_threads[__kmp_entry_gtid()];
   ompt_task_info_t *parent_task_info = OMPT_CUR_TASK_INFO(this_thr);
diff --git a/openmp/runtime/test/ompt/callback.h b/openmp/runtime/test/ompt/callback.h
index cd8acb57ee2f7..bc4ce8b2c72df 100644
--- a/openmp/runtime/test/ompt/callback.h
+++ b/openmp/runtime/test/ompt/callback.h
@@ -1055,7 +1055,9 @@ int ompt_initialize(ompt_function_lookup_t lookup, int initial_device_num,
                            ompt_callback_sync_region_t);
   register_ompt_callback_t(ompt_callback_reduction,
                            ompt_callback_sync_region_t);
+#ifndef _OMPT_DISABLE_CONTROL_TOOL
   register_ompt_callback(ompt_callback_control_tool);
+#endif
   register_ompt_callback(ompt_callback_flush);
   register_ompt_callback(ompt_callback_cancel);
   register_ompt_callback(ompt_callback_implicit_task);
diff --git a/openmp/runtime/test/ompt/misc/control_tool.c b/openmp/runtime/test/ompt/misc/control_tool.c
index 4b671e9eeab4d..e4b0c82f83cbd 100644
--- a/openmp/runtime/test/ompt/misc/control_tool.c
+++ b/openmp/runtime/test/ompt/misc/control_tool.c
@@ -6,14 +6,16 @@
 #define TEST_NEED_PRINT_FRAME_FROM_OUTLINED_FN
 #include "callback.h"
 #include <omp.h>
+#include <stdio.h>
 
 int main() {
 #pragma omp parallel num_threads(1)
   {
     print_frame_from_outlined_fn(1);
     print_frame(0);
-    omp_control_tool(omp_control_tool_flush, 1, NULL);
+    int result = omp_control_tool(omp_control_tool_flush, 1, NULL);
     print_current_address(0);
+    printf("control_tool result = %d\n", result);
   }
 
   // clang-format off
@@ -26,6 +28,7 @@ int main() {
   // CHECK: {{^}}[[MASTER_ID]]: __builtin_frame_address(0)=[[REENTER_FRAME:(0x)?[0-f]*]]
   // CHECK: {{^}}[[MASTER_ID]]: ompt_event_control_tool: command=3, modifier=1, arg=[[NULL]], codeptr_ra=[[RETURN_ADDRESS:(0x)?[0-f]*]], current_task_frame.exit=[[EXIT_FRAME]], current_task_frame.reenter={{(0x)?[0-f]*}}
   // CHECK-NEXT: {{^}}[[MASTER_ID]]: current_address={{.*}}[[RETURN_ADDRESS]]
+  // CHECK-NEXT: control_tool result = 0
   // clang-format on
 
   return 0;
diff --git a/openmp/runtime/test/ompt/misc/control_tool_before_directive.c b/openmp/runtime/test/ompt/misc/control_tool_before_directive.c
new file mode 100644
index 0000000000000..52c3a21bbebcb
--- /dev/null
+++ b/openmp/runtime/test/ompt/misc/control_tool_before_directive.c
@@ -0,0 +1,43 @@
+// clang-format off
+// RUN: %libomp-compile-and-run | FileCheck %s
+// REQUIRES: ompt
+// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7
+// clang-format on
+#define TEST_NEED_PRINT_FRAME_FROM_OUTLINED_FN
+#include "callback.h"
+#include <omp.h>
+#include <stdio.h>
+
+int main() {
+  int result = omp_control_tool(omp_control_tool_flush, 1, NULL);
+  printf("control_tool result = %d\n", result);
+
+#pragma omp parallel num_threads(1)
+  {
+    print_frame_from_outlined_fn(1);
+    print_frame(0);
+    print_current_address(0);
+  }
+
+  result = omp_control_tool(omp_control_tool_flush, 1, NULL);
+  printf("control_tool result = %d\n", result);
+
+  // clang-format off
+
+  // Check if libomp allows interacting with an attached tool both before and after the first
+  // directive is being used.
+
+  // CHECK-NOT: {{^}}0: Could not register callback 'ompt_callback_control_tool'
+
+  // CHECK: 0: NULL_POINTER=[[NULL:.*$]]
+
+  // CHECK: {{^}}[[MASTER_ID:[0-9]+]]: ompt_event_control_tool: command=3, modifier=1, arg=[[NULL]], codeptr_ra={{(0x)?[0-f]*}}, current_task_frame.exit={{.*}}, current_task_frame.reenter={{(0x)?[0-f]*}}
+  // CHECK-NEXT: control_tool result = 0
+  
+  // CHECK: {{^}}[[MASTER_ID]]: ompt_event_control_tool: command=3, modifier=1, arg=[[NULL]], codeptr_ra={{(0x)?[0-f]*}}, current_task_frame.exit={{.*}}, current_task_frame.reenter={{(0x)?[0-f]*}}
+  // CHECK-NEXT: control_tool result = 0
+
+  // clang-format on
+
+  return 0;
+}
diff --git a/openmp/runtime/test/ompt/misc/control_tool_no_callback.c b/openmp/runtime/test/ompt/misc/control_tool_no_callback.c
new file mode 100644
index 0000000000000..c1cff24cfa43a
--- /dev/null
+++ b/openmp/runtime/test/ompt/misc/control_tool_no_callback.c
@@ -0,0 +1,29 @@
+// clang-format off
+// RUN: %libomp-compile-and-run | FileCheck %s
+// REQUIRES: ompt
+// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7
+// clang-format on
+#define TEST_NEED_PRINT_FRAME_FROM_OUTLINED_FN
+#define _OMPT_DISABLE_CONTROL_TOOL
+#include "callback.h"
+#include <omp.h>
+#include <stdio.h>
+
+int main() {
+#pragma omp parallel num_threads(1)
+  {
+    int result = omp_control_tool(omp_control_tool_flush, 1, NULL);
+    printf("control_tool result = %d\n", result);
+  }
+
+  // clang-format off
+  // Check if libomp returns -1 (no callback) when a tool is attached,
+  // but ompt_callback_control_tool is not registered
+
+  // CHECK: 0: NULL_POINTER=[[NULL:.*$]]
+  // CHECK: control_tool result = -1
+
+  // clang-format on
+
+  return 0;
+}
diff --git a/openmp/runtime/test/ompt/misc/control_tool_no_ompt_support.c b/openmp/runtime/test/ompt/misc/control_tool_no_ompt_support.c
index 276d7c4c77f1a..86602ff2ffaca 100644
--- a/openmp/runtime/test/ompt/misc/control_tool_no_ompt_support.c
+++ b/openmp/runtime/test/ompt/misc/control_tool_no_ompt_support.c
@@ -3,12 +3,20 @@
 // clang-format on
 
 #include <omp.h>
+#include <stdio.h>
 
 int main() {
 #pragma omp parallel num_threads(1)
   {
-    omp_control_tool(omp_control_tool_flush, 1, NULL);
+    int result = omp_control_tool(omp_control_tool_flush, 1, NULL);
+    printf("control_tool result = %d\n", result);
   }
 
+  // clang-format off
+  // Check if libomp correctly reports -2 (no tool) if no tool is attached.
+
+  // CHECK: control_tool result = -2
+  // clang-format on
+
   return 0;
 }



More information about the llvm-branch-commits mailing list