[llvm] [openmp] [OpenMP][OMPT] Error when registering EMI and non-EMI callbacks (PR #213697)
Jan André Reuter via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 3 08:29:57 PDT 2026
https://github.com/Thyre created https://github.com/llvm/llvm-project/pull/213697
The OpenMP specification includes a restriction for registering both EMI and non-EMI callbacks (e.g. `ompt_callback_target`, OpenMP v5.2, p. 503, l. 18-20):
These callbacks must not be registered at the same time.
However, this was not respected in the runtime. A tool was able to register both, receiving `ompt_set_always` for each `ompt_set_callback` call. When an event associated with the EMI or non-EMI callbacks was dispatched and both callbacks were registered, only the EMI version was dispatched.
To align the runtime behavior with the OpenMP specification, return `ompt_set_error` when a tool tries to register both the EMI and non-EMI variant for a callback. With this, only the tool's first registration is used.
Update the offload `veccopy_disallow_both.c` test, which already tested the prior, non-compliant, behavior.
>From dbd22185eb20279c40e21ed391f3993cbc917d5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Andr=C3=A9=20Reuter?= <jan at zyten.de>
Date: Mon, 3 Aug 2026 17:29:16 +0200
Subject: [PATCH] [OpenMP][OMPT] Error when registering EMI and non-EMI
callbacks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The OpenMP specification includes a restriction for registering both EMI and
non-EMI callbacks (e.g. `ompt_callback_target`, OpenMP v5.2, p. 503, l. 18-20):
These callbacks must not be registered at the same time.
However, this was not respected in the runtime. A tool was able to register
both, receiving `ompt_set_always` for each `ompt_set_callback` call.
When an event associated with the EMI or non-EMI callbacks was dispatched
and both callbacks were registered, only the EMI version was dispatched.
To align the runtime behavior with the OpenMP specification, return
`ompt_set_error` when a tool tries to register both the EMI and non-EMI variant
for a callback. With this, only the tool's first registration is used.
Update the offload `veccopy_disallow_both.c` test, which already tested the
prior, non-compliant, behavior.
Signed-off-by: Jan André Reuter <jan at zyten.de>
---
offload/test/ompt/register_both.h | 4 +++-
offload/test/ompt/veccopy_disallow_both.c | 19 ++++++++-------
openmp/runtime/src/include/omp-tools.h.var | 13 +++++++++++
openmp/runtime/src/ompt-general.cpp | 27 +++++++++++++++++++++-
4 files changed, 53 insertions(+), 10 deletions(-)
diff --git a/offload/test/ompt/register_both.h b/offload/test/ompt/register_both.h
index 77cb430aa1f97..4e9157c2b51ed 100644
--- a/offload/test/ompt/register_both.h
+++ b/offload/test/ompt/register_both.h
@@ -4,7 +4,9 @@
#define register_ompt_callback_t(name, type) \
do { \
type f_##name = &on_##name; \
- if (ompt_set_callback(name, (ompt_callback_t)f_##name) == ompt_set_never) \
+ ompt_set_result_t result = \
+ ompt_set_callback(name, (ompt_callback_t)f_##name); \
+ if (result == ompt_set_never || result == ompt_set_error) \
printf("0: Could not register callback '" #name "'\n"); \
} while (0)
diff --git a/offload/test/ompt/veccopy_disallow_both.c b/offload/test/ompt/veccopy_disallow_both.c
index bfc67c5f4d274..2e24529042b37 100644
--- a/offload/test/ompt/veccopy_disallow_both.c
+++ b/offload/test/ompt/veccopy_disallow_both.c
@@ -7,8 +7,9 @@
/*
* Example OpenMP program that shows that both EMI and non-EMI
* callbacks cannot be registered for the same type. In the
- * current implementation, the EMI callback overrides the non-EMI
- * callback.
+ * current implementation, the first registered callback takes
+ * precedence. Trying to register the other callback results in
+ * ompt_set_error for this callback.
*/
#include <omp.h>
@@ -57,9 +58,11 @@ int main() {
}
// clang-format off
+/// CHECK: [[THREAD_ID:[0-9]+]]: Could not register callback 'ompt_callback_target_data_op'
+/// CHECK: [[THREAD_ID]]: Could not register callback 'ompt_callback_target_emi'
/// CHECK: Callback Init:
/// CHECK: Callback Load:
-/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_begin
+/// CHECK: Callback Target: target_id=[[TARGET_ID:[0-9]+]] kind=ompt_target endpoint=ompt_scope_begin
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_alloc
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_alloc
/// CHECK-NOT: dest=(nil)
@@ -70,7 +73,7 @@ int main() {
/// CHECK-NOT: dest=(nil)
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_to_device
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_transfer_to_device
-/// CHECK: Callback Submit: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] req_num_teams=1
+/// CHECK: Callback Submit: target_id=[[TARGET_ID]] host_op_id=[[HOST_OP_ID:[0-9]+]] req_num_teams=1
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_from_device
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_transfer_from_device
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_from_device
@@ -79,8 +82,8 @@ int main() {
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_delete
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_delete
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_delete
-/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_end
-/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_begin
+/// CHECK: Callback Target: target_id=[[TARGET_ID]] kind=ompt_target endpoint=ompt_scope_end
+/// CHECK: Callback Target: target_id=[[TARGET_ID:[0-9]+]] kind=ompt_target endpoint=ompt_scope_begin
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_alloc
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_alloc
/// CHECK-NOT: dest=(nil)
@@ -91,7 +94,7 @@ int main() {
/// CHECK-NOT: dest=(nil)
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_to_device
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_transfer_to_device
-/// CHECK: Callback Submit: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] req_num_teams=0
+/// CHECK: Callback Submit: target_id=[[TARGET_ID]] host_op_id=[[HOST_OP_ID:[0-9]+]] req_num_teams=0
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_from_device
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_transfer_from_device
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_from_device
@@ -100,5 +103,5 @@ int main() {
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_delete
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_delete
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_delete
-/// CHECK: Callback Target EMI: kind=ompt_target endpoint=ompt_scope_end
+/// CHECK: Callback Target: target_id=[[TARGET_ID]] kind=ompt_target endpoint=ompt_scope_end
/// CHECK: Callback Fini:
diff --git a/openmp/runtime/src/include/omp-tools.h.var b/openmp/runtime/src/include/omp-tools.h.var
index af9213a7290e7..46643dff5feab 100644
--- a/openmp/runtime/src/include/omp-tools.h.var
+++ b/openmp/runtime/src/include/omp-tools.h.var
@@ -185,6 +185,19 @@
/* Optional Events */ \
macro (ompt_callback_target_map_emi, ompt_callback_target_map_emi_t, 36) /* target map */
+#define FOREACH_MAPPED_OMPT_TARGET_EVENT(macro) \
+ /* macro including correlated callback enum (e.g. target -- target_emi) for comparisons between both */ \
+ /*--- Mandatory Events ---*/ \
+ macro (ompt_callback_target, ompt_callback_target_emi, ompt_callback_target_t, 8) \
+ macro (ompt_callback_target_data_op, ompt_callback_target_data_op_emi, ompt_callback_target_data_op_t, 9) \
+ macro (ompt_callback_target_submit, ompt_callback_target_submit_emi, ompt_callback_target_submit_t, 10) \
+ macro (ompt_callback_target_emi, ompt_callback_target, ompt_callback_target_emi_t, 33) \
+ macro (ompt_callback_target_data_op_emi, ompt_callback_target_data_op, ompt_callback_target_data_op_emi_t, 34) \
+ macro (ompt_callback_target_submit_emi, ompt_callback_target_submit, ompt_callback_target_submit_emi_t, 35) \
+ /* Optional Events */ \
+ macro (ompt_callback_target_map, ompt_callback_target_map_emi, ompt_callback_target_map_t, 22) \
+ macro (ompt_callback_target_map_emi, ompt_callback_target_map, ompt_callback_target_map_emi_t, 36)
+
#define FOREACH_OMPT_50_TARGET_EVENT(macro) \
FOREACH_OMPT_DEVICE_EVENT(macro) \
FOREACH_OMPT_NOEMI_EVENT(macro)
diff --git a/openmp/runtime/src/ompt-general.cpp b/openmp/runtime/src/ompt-general.cpp
index 1682f7e74bd14..1cb2fb2693a2c 100644
--- a/openmp/runtime/src/ompt-general.cpp
+++ b/openmp/runtime/src/ompt-general.cpp
@@ -597,10 +597,35 @@ OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which,
else \
return ompt_set_always;
- FOREACH_OMPT_EVENT(ompt_event_macro)
+ FOREACH_OMPT_HOST_EVENT(ompt_event_macro)
+ FOREACH_OMPT_DEVICE_EVENT(ompt_event_macro)
#undef ompt_event_macro
+ // OpenMP v5.2, p. 503, l. 18-20:
+ // Restrictions to the ompt_callback_target_emi and ompt_callback_target
+ // callbacks are as follows:
+ // These callbacks must not be registered at the same time.
+ //
+ // Similar restrictions apply to target_data_op, target_submit,
+ // and target_map. Hence, handle registration of them separately to ensure
+ // only one can be registered at the same time. */
+#define ompt_target_event_macro(event_name, comparison_name, callback_type, \
+ event_id) \
+ case event_name: \
+ if (ompt_callbacks.ompt_callback(comparison_name)) \
+ return ompt_set_error; \
+ ompt_callbacks.ompt_callback(event_name) = (callback_type)callback; \
+ ompt_enabled.event_name = (callback != 0); \
+ if (callback) \
+ return ompt_event_implementation_status(event_name); \
+ else \
+ return ompt_set_always;
+
+ FOREACH_MAPPED_OMPT_TARGET_EVENT(ompt_target_event_macro);
+
+#undef ompt_target_event_macro
+
default:
return ompt_set_error;
}
More information about the llvm-commits
mailing list