| 1 | // RUN: %libomp-compile-and-run | %sort-threads | FileCheck %s |
| 2 | // REQUIRES: ompt |
| 3 | |
| 4 | // This test checks that values stored in task_data in a barrier_begin event |
| 5 | // are still present in the corresponding barrier_end event. |
| 6 | // Therefore, callback implementations different from the ones in callback.h are necessary. |
| 7 | // This is a test for an issue reported in |
| 8 | // https://github.com/OpenMPToolsInterface/LLVM-openmp/issues/39 |
| 9 | |
| 10 | #define _BSD_SOURCE |
| 11 | #include <stdio.h> |
| 12 | #include <unistd.h> |
| 13 | #include <inttypes.h> |
| 14 | #include <omp.h> |
| 15 | #include <omp-tools.h> |
| 16 | |
| 17 | static const char* ompt_thread_t_values[] = { |
| 18 | NULL, |
| 19 | "ompt_thread_initial" , |
| 20 | "ompt_thread_worker" , |
| 21 | "ompt_thread_other" |
| 22 | }; |
| 23 | |
| 24 | static ompt_get_unique_id_t ompt_get_unique_id; |
| 25 | static ompt_get_thread_data_t ompt_get_thread_data; |
| 26 | |
| 27 | int main() |
| 28 | { |
| 29 | #pragma omp parallel num_threads(4) |
| 30 | { |
| 31 | #pragma omp master |
| 32 | { |
| 33 | sleep(seconds: 1); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | // clang-format off |
| 38 | // Check if libomp supports the callbacks for this test. |
| 39 | // CHECK-NOT: {{^}}0: Could not register callback 'ompt_callback_sync_region' |
| 40 | // CHECK-NOT: {{^}}0: Could not register callback 'ompt_callback_sync_region_wait' |
| 41 | |
| 42 | // CHECK: 0: NULL_POINTER=[[NULL:.*$]] |
| 43 | |
| 44 | // master thread implicit barrier at parallel end |
| 45 | // CHECK: {{^}}[[MASTER_ID:[0-9]+]]: ompt_event_barrier_implicit_parallel_begin: parallel_id=0, task_id=[[TASK_ID:[0-9]+]], codeptr_ra={{(0x)?[0-f]*}} |
| 46 | // CHECK: {{^}}[[MASTER_ID]]: ompt_event_wait_barrier_implicit_parallel_begin: parallel_id=0, task_id=[[TASK_ID]], codeptr_ra={{(0x)?[0-f]*}} |
| 47 | // CHECK: {{^}}[[MASTER_ID]]: ompt_event_wait_barrier_implicit_parallel_end: parallel_id=0, task_id=[[TASK_ID]], codeptr_ra={{(0x)?[0-f]*}} |
| 48 | // CHECK: {{^}}[[MASTER_ID]]: ompt_event_barrier_implicit_parallel_end: parallel_id=0, task_id=[[TASK_ID]], codeptr_ra={{(0x)?[0-f]*}} |
| 49 | |
| 50 | |
| 51 | // worker thread implicit barrier at parallel end |
| 52 | // CHECK: {{^}}[[THREAD_ID:[0-9]+]]: ompt_event_barrier_implicit_parallel_begin: parallel_id=0, task_id=[[TASK_ID:[0-9]+]], codeptr_ra=[[NULL]] |
| 53 | // CHECK: {{^}}[[THREAD_ID]]: ompt_event_wait_barrier_implicit_parallel_begin: parallel_id=0, task_id=[[TASK_ID]], codeptr_ra=[[NULL]] |
| 54 | // CHECK: {{^}}[[THREAD_ID]]: ompt_event_wait_barrier_implicit_parallel_end: parallel_id=0, task_id=[[TASK_ID]], codeptr_ra=[[NULL]] |
| 55 | // CHECK: {{^}}[[THREAD_ID]]: ompt_event_barrier_implicit_parallel_end: parallel_id=0, task_id=[[TASK_ID]], codeptr_ra=[[NULL]] |
| 56 | // clang-format on |
| 57 | |
| 58 | return 0; |
| 59 | } |
| 60 | |
| 61 | static void |
| 62 | on_ompt_callback_thread_begin( |
| 63 | ompt_thread_t thread_type, |
| 64 | ompt_data_t *thread_data) |
| 65 | { |
| 66 | if(thread_data->ptr) |
| 67 | printf(format: "%s\n" , "0: thread_data initially not null" ); |
| 68 | thread_data->value = ompt_get_unique_id(); |
| 69 | printf(format: "%" PRIu64 ": ompt_event_thread_begin: thread_type=%s=%d, thread_id=%" PRIu64 "\n" , ompt_get_thread_data()->value, ompt_thread_t_values[thread_type], thread_type, thread_data->value); |
| 70 | } |
| 71 | |
| 72 | static void |
| 73 | on_ompt_callback_sync_region( |
| 74 | ompt_sync_region_t kind, |
| 75 | ompt_scope_endpoint_t endpoint, |
| 76 | ompt_data_t *parallel_data, |
| 77 | ompt_data_t *task_data, |
| 78 | const void *codeptr_ra) |
| 79 | { |
| 80 | // We only expect implicit parallel barrier in this code. |
| 81 | if (kind != ompt_sync_region_barrier_implicit_parallel) { |
| 82 | printf(format: "unexpected ompt_sync_region_t passed to %s\n" , __func__); |
| 83 | exit(status: -1); |
| 84 | } |
| 85 | const char *event_name = NULL; |
| 86 | if (endpoint == ompt_scope_begin) { |
| 87 | event_name = "ompt_event_barrier_implicit_parallel_begin" ; |
| 88 | task_data->value = ompt_get_unique_id(); |
| 89 | } else if (endpoint == ompt_scope_end) { |
| 90 | event_name = "ompt_event_barrier_implicit_parallel_end" ; |
| 91 | } else { |
| 92 | printf(format: "ompt_scope_beginend should never be passed to %s\n" , __func__); |
| 93 | exit(status: -1); |
| 94 | } |
| 95 | printf(format: "%" PRIu64 ": %s: parallel_id=%" PRIu64 ", task_id=%" PRIu64 |
| 96 | ", codeptr_ra=%p\n" , |
| 97 | ompt_get_thread_data()->value, event_name, |
| 98 | parallel_data ? parallel_data->value : 0, task_data->value, |
| 99 | codeptr_ra); |
| 100 | } |
| 101 | |
| 102 | static void |
| 103 | on_ompt_callback_sync_region_wait( |
| 104 | ompt_sync_region_t kind, |
| 105 | ompt_scope_endpoint_t endpoint, |
| 106 | ompt_data_t *parallel_data, |
| 107 | ompt_data_t *task_data, |
| 108 | const void *codeptr_ra) |
| 109 | { |
| 110 | if (kind != ompt_sync_region_barrier_implicit_parallel) { |
| 111 | printf(format: "unexpected ompt_sync_region_t passed to %s\n" , __func__); |
| 112 | exit(status: -1); |
| 113 | } |
| 114 | const char *event_name = NULL; |
| 115 | if (endpoint == ompt_scope_begin) { |
| 116 | event_name = "ompt_event_wait_barrier_implicit_parallel_begin" ; |
| 117 | } else if (endpoint == ompt_scope_end) { |
| 118 | event_name = "ompt_event_wait_barrier_implicit_parallel_end" ; |
| 119 | } else { |
| 120 | printf(format: "ompt_scope_beginend should never be passed to %s\n" , __func__); |
| 121 | exit(status: -1); |
| 122 | } |
| 123 | printf(format: "%" PRIu64 ": %s: parallel_id=%" PRIu64 ", task_id=%" PRIu64 |
| 124 | ", codeptr_ra=%p\n" , |
| 125 | ompt_get_thread_data()->value, event_name, |
| 126 | parallel_data ? parallel_data->value : 0, task_data->value, |
| 127 | codeptr_ra); |
| 128 | } |
| 129 | |
| 130 | #define register_ompt_callback_t(name, type) \ |
| 131 | do{ \ |
| 132 | type f_##name = &on_##name; \ |
| 133 | if (ompt_set_callback(name, (ompt_callback_t)f_##name) == \ |
| 134 | ompt_set_never) \ |
| 135 | printf("0: Could not register callback '" #name "'\n"); \ |
| 136 | }while(0) |
| 137 | |
| 138 | #define register_ompt_callback(name) register_ompt_callback_t(name, name##_t) |
| 139 | |
| 140 | int ompt_initialize(ompt_function_lookup_t lookup, int initial_device_num, |
| 141 | ompt_data_t *tool_data) { |
| 142 | ompt_set_callback_t ompt_set_callback; |
| 143 | ompt_set_callback = (ompt_set_callback_t) lookup("ompt_set_callback" ); |
| 144 | ompt_get_unique_id = (ompt_get_unique_id_t) lookup("ompt_get_unique_id" ); |
| 145 | ompt_get_thread_data = (ompt_get_thread_data_t) lookup("ompt_get_thread_data" ); |
| 146 | register_ompt_callback(ompt_callback_sync_region); |
| 147 | register_ompt_callback_t(ompt_callback_sync_region_wait, ompt_callback_sync_region_t); |
| 148 | register_ompt_callback(ompt_callback_thread_begin); |
| 149 | printf(format: "0: NULL_POINTER=%p\n" , (void*)NULL); |
| 150 | return 1; //success |
| 151 | } |
| 152 | |
| 153 | void ompt_finalize(ompt_data_t *tool_data) |
| 154 | { |
| 155 | printf(format: "0: ompt_event_runtime_shutdown\n" ); |
| 156 | } |
| 157 | |
| 158 | ompt_start_tool_result_t* ompt_start_tool( |
| 159 | unsigned int omp_version, |
| 160 | const char *runtime_version) |
| 161 | { |
| 162 | static ompt_start_tool_result_t ompt_start_tool_result = {.initialize: &ompt_initialize,.finalize: &ompt_finalize, .tool_data.value: 0}; |
| 163 | return &ompt_start_tool_result; |
| 164 | } |
| 165 | |