[Openmp-commits] [openmp] 09375e3 - [OpenMP][OMPT] Error when registering EMI and non-EMI callbacks (#213697)
via Openmp-commits
openmp-commits at lists.llvm.org
Fri Aug 7 03:42:04 PDT 2026
Author: Jan André Reuter
Date: 2026-08-07T12:41:59+02:00
New Revision: 09375e336d7cdbe96018300ef69d2be7d3c441a2
URL: https://github.com/llvm/llvm-project/commit/09375e336d7cdbe96018300ef69d2be7d3c441a2
DIFF: https://github.com/llvm/llvm-project/commit/09375e336d7cdbe96018300ef69d2be7d3c441a2.diff
LOG: [OpenMP][OMPT] Error when registering EMI and non-EMI callbacks (#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.
Closes #212959
Signed-off-by: Jan André Reuter <jan at zyten.de>
Added:
Modified:
offload/test/ompt/register_both.h
offload/test/ompt/veccopy_disallow_both.c
openmp/runtime/src/include/omp-tools.h.var
openmp/runtime/src/ompt-general.cpp
Removed:
################################################################################
diff --git a/offload/test/ompt/register_both.h b/offload/test/ompt/register_both.h
index 77cb430aa1f97..a20b42bad2196 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..8f1ba4910815e 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 Openmp-commits
mailing list