diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports --- a/openmp/runtime/src/dllexports +++ b/openmp/runtime/src/dllexports @@ -390,8 +390,9 @@ __kmpc_taskred_init 277 __kmpc_taskred_modifier_init 278 __kmpc_omp_target_task_alloc 279 + __kmpc_error 281 __kmpc_masked 282 - __kmpc_end_masked 283 + __kmpc_end_masked 283 %endif # User API entry points that have both lower- and upper- case versions for Fortran. diff --git a/openmp/runtime/src/i18n/en_US.txt b/openmp/runtime/src/i18n/en_US.txt --- a/openmp/runtime/src/i18n/en_US.txt +++ b/openmp/runtime/src/i18n/en_US.txt @@ -455,6 +455,8 @@ AffUseGlobCpuidL "%1$s: Affinity capable, using global cpuid leaf %2$d info" AffNotCapableUseLocCpuidL "%1$s: Affinity not capable, using local cpuid leaf %2$d info" AffNotUsingHwloc "%1$s: Affinity not capable, using hwloc." +UserDirectedError "%1$s: Encountered user-directed error: %2$s." +UserDirectedWarning "%1$s: Encountered user-directed warning: %2$s." FailedToCreateTeam "Failed to create teams between lower bound (%1$d) and upper bound (%2$d)." # -------------------------------------------------------------------------------------------------- diff --git a/openmp/runtime/src/include/omp-tools.h.var b/openmp/runtime/src/include/omp-tools.h.var --- a/openmp/runtime/src/include/omp-tools.h.var +++ b/openmp/runtime/src/include/omp-tools.h.var @@ -1099,6 +1099,13 @@ const void *codeptr_ra ); +typedef struct ompt_record_error_t { + ompt_severity_t severity; + const char *message; + size_t length; + const void *codeptr_ra; +} ompt_record_error_t; + typedef struct ompd_address_t { ompd_seg_t segment; ompd_addr_t address; diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -4087,6 +4087,13 @@ #define KMP_GTID_TO_SHADOW_GTID(gtid) \ ((gtid) % (__kmp_hidden_helper_threads_num - 1) + 2) +// Support for error directive +typedef enum kmp_severity_t { + severity_warning = 1, + severity_fatal = 2 +} kmp_severity_t; +extern void __kmpc_error(ident_t *loc, int severity, const char *message); + #ifdef __cplusplus } #endif diff --git a/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/runtime/src/kmp_csupport.cpp @@ -4357,3 +4357,35 @@ } return __kmp_pause_resource(level); } + +void __kmpc_error(ident_t *loc, int severity, const char *message) { + if (!__kmp_init_serial) + __kmp_serial_initialize(); + + KMP_ASSERT(severity == severity_warning || severity == severity_fatal); + +#if OMPT_SUPPORT + if (ompt_enabled.enabled && ompt_enabled.ompt_callback_error) { + ompt_callbacks.ompt_callback(ompt_callback_error)( + (ompt_severity_t)severity, message, KMP_STRLEN(message), + OMPT_GET_RETURN_ADDRESS(0)); + } +#endif // OMPT_SUPPORT + + char *src_loc; + if (loc && loc->psource) { + kmp_str_loc_t str_loc = __kmp_str_loc_init(loc->psource, false); + src_loc = + __kmp_str_format("%s:%s:%s", str_loc.file, str_loc.line, str_loc.col); + __kmp_str_loc_free(&str_loc); + } else { + src_loc = __kmp_str_format("unknown"); + } + + if (severity == severity_warning) + KMP_WARNING(UserDirectedWarning, src_loc, message); + else + KMP_FATAL(UserDirectedError, src_loc, message); + + __kmp_str_free(&src_loc); +} diff --git a/openmp/runtime/src/ompt-event-specific.h b/openmp/runtime/src/ompt-event-specific.h --- a/openmp/runtime/src/ompt-event-specific.h +++ b/openmp/runtime/src/ompt-event-specific.h @@ -106,6 +106,6 @@ #define ompt_callback_dispatch_implemented ompt_event_UNIMPLEMENTED -#define ompt_callback_error_implemented ompt_event_UNIMPLEMENTED +#define ompt_callback_error_implemented ompt_event_MAY_ALWAYS_OPTIONAL #endif diff --git a/openmp/runtime/test/ompt/callback.h b/openmp/runtime/test/ompt/callback.h --- a/openmp/runtime/test/ompt/callback.h +++ b/openmp/runtime/test/ompt/callback.h @@ -1124,6 +1124,15 @@ return 0; //success } +static void on_ompt_callback_error(ompt_severity_t severity, + const char *message, size_t length, + const void *codeptr_ra) { + printf("%" PRIu64 ": ompt_event_runtime_error: severity=%" PRIu32 + ", message=%s, length=%" PRIu64 ", codeptr_ra=%p\n", + ompt_get_thread_data()->value, severity, message, (uint64_t)length, + codeptr_ra); +} + int ompt_initialize( ompt_function_lookup_t lookup, int initial_device_num, @@ -1173,6 +1182,7 @@ register_ompt_callback(ompt_callback_task_dependence); register_ompt_callback(ompt_callback_thread_begin); register_ompt_callback(ompt_callback_thread_end); + register_ompt_callback(ompt_callback_error); printf("0: NULL_POINTER=%p\n", (void*)NULL); return 1; //success } diff --git a/openmp/runtime/test/ompt/misc/runtime_error.c b/openmp/runtime/test/ompt/misc/runtime_error.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/ompt/misc/runtime_error.c @@ -0,0 +1,35 @@ +// RUN: %libomp-compile-and-run 2>&1 | sort | FileCheck %s +// REQUIRES: ompt + +#include +#include +#include "callback.h" + +// TODO: use error directive when compiler suppors +typedef void ident_t; +extern void __kmpc_error(ident_t *, int, const char *); + +int main() { +#pragma omp parallel num_threads(2) + { + if (omp_get_thread_num() == 0) { + const char *msg = "User message goes here"; + printf("0: Message length=%" PRIu64 "\n", (uint64_t)strlen(msg)); + __kmpc_error(NULL, ompt_warning, msg); + } + } + return 0; +} + +// CHECK: {{^}}0: Message length=[[LENGTH:[0-9]+]] +// CHECK: {{^}}0: NULL_POINTER=[[NULL:.*$]] + +// CHECK: {{^}}[[PRIMARY_ID:[0-9]+]]: ompt_event_implicit_task_begin +// CHECK: {{^}}[[PRIMARY_ID]]: ompt_event_runtime_error +// CHECK-SAME: severity=1 +// CHECK-SAME: message=User message goes here +// CHECK-SAME: length=[[LENGTH]] +// CHECK-SAME: codeptr_ra={{0x[0-f]+}} + +// Message from runtime +// CHECK: {{^}}OMP: Warning{{.*}}User message goes here