xref: /llvm-project/offload/src/OpenMP/OMPT/Callback.cpp (revision d36f66b42d7abec73bb5b953612eef26e6c12e0a)
1330d8983SJohannes Doerfert //===-- OpenMP/OMPT/Callback.cpp - OpenMP Tooling Callback implementation -===//
2330d8983SJohannes Doerfert //
3330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information.
5330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6330d8983SJohannes Doerfert //
7330d8983SJohannes Doerfert //===----------------------------------------------------------------------===//
8330d8983SJohannes Doerfert //
9330d8983SJohannes Doerfert // Implementation of OMPT callback interfaces for target independent layer
10330d8983SJohannes Doerfert //
11330d8983SJohannes Doerfert //===----------------------------------------------------------------------===//
12330d8983SJohannes Doerfert 
13*d36f66b4SMichael Halkenhäuser #ifdef OMPT_SUPPORT
14330d8983SJohannes Doerfert 
15330d8983SJohannes Doerfert #include <cstdlib>
16330d8983SJohannes Doerfert #include <cstring>
17330d8983SJohannes Doerfert #include <memory>
18330d8983SJohannes Doerfert 
19330d8983SJohannes Doerfert #include "Shared/Debug.h"
20330d8983SJohannes Doerfert 
21330d8983SJohannes Doerfert #include "OpenMP/OMPT/Callback.h"
22330d8983SJohannes Doerfert #include "OpenMP/OMPT/Connector.h"
23330d8983SJohannes Doerfert #include "OpenMP/OMPT/Interface.h"
24330d8983SJohannes Doerfert 
25330d8983SJohannes Doerfert #include "llvm/Support/DynamicLibrary.h"
26330d8983SJohannes Doerfert 
27330d8983SJohannes Doerfert #undef DEBUG_PREFIX
28330d8983SJohannes Doerfert #define DEBUG_PREFIX "OMPT"
29330d8983SJohannes Doerfert 
30330d8983SJohannes Doerfert // Define OMPT callback functions (bound to actual callbacks later on)
31330d8983SJohannes Doerfert #define defineOmptCallback(Name, Type, Code)                                   \
32330d8983SJohannes Doerfert   Name##_t llvm::omp::target::ompt::Name##_fn = nullptr;
33330d8983SJohannes Doerfert FOREACH_OMPT_NOEMI_EVENT(defineOmptCallback)
34330d8983SJohannes Doerfert FOREACH_OMPT_EMI_EVENT(defineOmptCallback)
35330d8983SJohannes Doerfert #undef defineOmptCallback
36330d8983SJohannes Doerfert 
37*d36f66b4SMichael Halkenhäuser using namespace llvm::omp::target::ompt;
38*d36f66b4SMichael Halkenhäuser 
39330d8983SJohannes Doerfert /// Forward declaration
40330d8983SJohannes Doerfert class LibomptargetRtlFinalizer;
41330d8983SJohannes Doerfert 
42330d8983SJohannes Doerfert /// Object that will maintain the RTL finalizer from the plugin
43330d8983SJohannes Doerfert LibomptargetRtlFinalizer *LibraryFinalizer = nullptr;
44330d8983SJohannes Doerfert 
45330d8983SJohannes Doerfert thread_local Interface llvm::omp::target::ompt::RegionInterface;
46330d8983SJohannes Doerfert 
47330d8983SJohannes Doerfert thread_local void *llvm::omp::target::ompt::ReturnAddress = nullptr;
48330d8983SJohannes Doerfert 
49330d8983SJohannes Doerfert bool llvm::omp::target::ompt::Initialized = false;
50330d8983SJohannes Doerfert 
51330d8983SJohannes Doerfert ompt_get_callback_t llvm::omp::target::ompt::lookupCallbackByCode = nullptr;
52330d8983SJohannes Doerfert ompt_function_lookup_t llvm::omp::target::ompt::lookupCallbackByName = nullptr;
53330d8983SJohannes Doerfert ompt_get_target_task_data_t ompt_get_target_task_data_fn = nullptr;
54330d8983SJohannes Doerfert ompt_get_task_data_t ompt_get_task_data_fn = nullptr;
55330d8983SJohannes Doerfert 
56330d8983SJohannes Doerfert /// Unique correlation id
57330d8983SJohannes Doerfert static std::atomic<uint64_t> IdCounter(1);
58330d8983SJohannes Doerfert 
59330d8983SJohannes Doerfert /// Used to create a new correlation id
60330d8983SJohannes Doerfert static uint64_t createId() { return IdCounter.fetch_add(1); }
61330d8983SJohannes Doerfert 
62330d8983SJohannes Doerfert /// Create a new correlation id and update the operations id
63330d8983SJohannes Doerfert static uint64_t createOpId() {
64330d8983SJohannes Doerfert   uint64_t NewId = createId();
65330d8983SJohannes Doerfert   RegionInterface.setHostOpId(NewId);
66330d8983SJohannes Doerfert   return NewId;
67330d8983SJohannes Doerfert }
68330d8983SJohannes Doerfert 
69330d8983SJohannes Doerfert /// Create a new correlation id and update the target region id
70330d8983SJohannes Doerfert static uint64_t createRegionId() {
71330d8983SJohannes Doerfert   uint64_t NewId = createId();
72330d8983SJohannes Doerfert   RegionInterface.setTargetDataValue(NewId);
73330d8983SJohannes Doerfert   return NewId;
74330d8983SJohannes Doerfert }
75330d8983SJohannes Doerfert 
76330d8983SJohannes Doerfert void Interface::beginTargetDataAlloc(int64_t DeviceId, void *HstPtrBegin,
77330d8983SJohannes Doerfert                                      void **TgtPtrBegin, size_t Size,
78330d8983SJohannes Doerfert                                      void *Code) {
79330d8983SJohannes Doerfert   beginTargetDataOperation();
80330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
81330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
82330d8983SJohannes Doerfert     // callback
83330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
84330d8983SJohannes Doerfert         ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
85330d8983SJohannes Doerfert         ompt_target_data_alloc, HstPtrBegin,
86330d8983SJohannes Doerfert         /*SrcDeviceNum=*/omp_get_initial_device(), *TgtPtrBegin,
87330d8983SJohannes Doerfert         /*TgtDeviceNum=*/DeviceId, Size, Code);
88330d8983SJohannes Doerfert   } else if (ompt_callback_target_data_op_fn) {
89330d8983SJohannes Doerfert     // HostOpId is set by the runtime
90330d8983SJohannes Doerfert     HostOpId = createOpId();
91330d8983SJohannes Doerfert     // Invoke the tool supplied data op callback
92330d8983SJohannes Doerfert     ompt_callback_target_data_op_fn(
93330d8983SJohannes Doerfert         TargetData.value, HostOpId, ompt_target_data_alloc, HstPtrBegin,
94330d8983SJohannes Doerfert         /*SrcDeviceNum=*/omp_get_initial_device(), *TgtPtrBegin,
95330d8983SJohannes Doerfert         /*TgtDeviceNum=*/DeviceId, Size, Code);
96330d8983SJohannes Doerfert   }
97330d8983SJohannes Doerfert }
98330d8983SJohannes Doerfert 
99330d8983SJohannes Doerfert void Interface::endTargetDataAlloc(int64_t DeviceId, void *HstPtrBegin,
100330d8983SJohannes Doerfert                                    void **TgtPtrBegin, size_t Size,
101330d8983SJohannes Doerfert                                    void *Code) {
102330d8983SJohannes Doerfert   // Only EMI callback handles end scope
103330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
104330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
105330d8983SJohannes Doerfert     // callback
106330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
107330d8983SJohannes Doerfert         ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
108330d8983SJohannes Doerfert         ompt_target_data_alloc, HstPtrBegin,
109330d8983SJohannes Doerfert         /*SrcDeviceNum=*/omp_get_initial_device(), *TgtPtrBegin,
110330d8983SJohannes Doerfert         /*TgtDeviceNum=*/DeviceId, Size, Code);
111330d8983SJohannes Doerfert   }
112330d8983SJohannes Doerfert   endTargetDataOperation();
113330d8983SJohannes Doerfert }
114330d8983SJohannes Doerfert 
115330d8983SJohannes Doerfert void Interface::beginTargetDataSubmit(int64_t SrcDeviceId, void *SrcPtrBegin,
116330d8983SJohannes Doerfert                                       int64_t DstDeviceId, void *DstPtrBegin,
117330d8983SJohannes Doerfert                                       size_t Size, void *Code) {
118330d8983SJohannes Doerfert   beginTargetDataOperation();
119330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
120330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
121330d8983SJohannes Doerfert     // callback
122330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
123330d8983SJohannes Doerfert         ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
124330d8983SJohannes Doerfert         ompt_target_data_transfer_to_device, SrcPtrBegin, SrcDeviceId,
125330d8983SJohannes Doerfert         DstPtrBegin, DstDeviceId, Size, Code);
126330d8983SJohannes Doerfert   } else if (ompt_callback_target_data_op_fn) {
127330d8983SJohannes Doerfert     // HostOpId is set by the runtime
128330d8983SJohannes Doerfert     HostOpId = createOpId();
129330d8983SJohannes Doerfert     // Invoke the tool supplied data op callback
130330d8983SJohannes Doerfert     ompt_callback_target_data_op_fn(
131330d8983SJohannes Doerfert         TargetData.value, HostOpId, ompt_target_data_transfer_to_device,
132330d8983SJohannes Doerfert         SrcPtrBegin, SrcDeviceId, DstPtrBegin, DstDeviceId, Size, Code);
133330d8983SJohannes Doerfert   }
134330d8983SJohannes Doerfert }
135330d8983SJohannes Doerfert 
136330d8983SJohannes Doerfert void Interface::endTargetDataSubmit(int64_t SrcDeviceId, void *SrcPtrBegin,
137330d8983SJohannes Doerfert                                     int64_t DstDeviceId, void *DstPtrBegin,
138330d8983SJohannes Doerfert                                     size_t Size, void *Code) {
139330d8983SJohannes Doerfert   // Only EMI callback handles end scope
140330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
141330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
142330d8983SJohannes Doerfert     // callback
143330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
144330d8983SJohannes Doerfert         ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
145330d8983SJohannes Doerfert         ompt_target_data_transfer_to_device, SrcPtrBegin, SrcDeviceId,
146330d8983SJohannes Doerfert         DstPtrBegin, DstDeviceId, Size, Code);
147330d8983SJohannes Doerfert   }
148330d8983SJohannes Doerfert   endTargetDataOperation();
149330d8983SJohannes Doerfert }
150330d8983SJohannes Doerfert 
151330d8983SJohannes Doerfert void Interface::beginTargetDataDelete(int64_t DeviceId, void *TgtPtrBegin,
152330d8983SJohannes Doerfert                                       void *Code) {
153330d8983SJohannes Doerfert   beginTargetDataOperation();
154330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
155330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
156330d8983SJohannes Doerfert     // callback
157330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
158330d8983SJohannes Doerfert         ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
159330d8983SJohannes Doerfert         ompt_target_data_delete, TgtPtrBegin, DeviceId,
160330d8983SJohannes Doerfert         /*TgtPtrBegin=*/nullptr, /*TgtDeviceNum=*/-1, /*Bytes=*/0, Code);
161330d8983SJohannes Doerfert   } else if (ompt_callback_target_data_op_fn) {
162330d8983SJohannes Doerfert     // HostOpId is set by the runtime
163330d8983SJohannes Doerfert     HostOpId = createOpId();
164330d8983SJohannes Doerfert     // Invoke the tool supplied data op callback
165330d8983SJohannes Doerfert     ompt_callback_target_data_op_fn(TargetData.value, HostOpId,
166330d8983SJohannes Doerfert                                     ompt_target_data_delete, TgtPtrBegin,
167330d8983SJohannes Doerfert                                     DeviceId, /*TgtPtrBegin=*/nullptr,
168330d8983SJohannes Doerfert                                     /*TgtDeviceNum=*/-1, /*Bytes=*/0, Code);
169330d8983SJohannes Doerfert   }
170330d8983SJohannes Doerfert }
171330d8983SJohannes Doerfert 
172330d8983SJohannes Doerfert void Interface::endTargetDataDelete(int64_t DeviceId, void *TgtPtrBegin,
173330d8983SJohannes Doerfert                                     void *Code) {
174330d8983SJohannes Doerfert   // Only EMI callback handles end scope
175330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
176330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
177330d8983SJohannes Doerfert     // callback
178330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
179330d8983SJohannes Doerfert         ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
180330d8983SJohannes Doerfert         ompt_target_data_delete, TgtPtrBegin, DeviceId,
181330d8983SJohannes Doerfert         /*TgtPtrBegin=*/nullptr, /*TgtDeviceNum=*/-1, /*Bytes=*/0, Code);
182330d8983SJohannes Doerfert   }
183330d8983SJohannes Doerfert   endTargetDataOperation();
184330d8983SJohannes Doerfert }
185330d8983SJohannes Doerfert 
186330d8983SJohannes Doerfert void Interface::beginTargetDataRetrieve(int64_t SrcDeviceId, void *SrcPtrBegin,
187330d8983SJohannes Doerfert                                         int64_t DstDeviceId, void *DstPtrBegin,
188330d8983SJohannes Doerfert                                         size_t Size, void *Code) {
189330d8983SJohannes Doerfert   beginTargetDataOperation();
190330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
191330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
192330d8983SJohannes Doerfert     // callback
193330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
194330d8983SJohannes Doerfert         ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
195330d8983SJohannes Doerfert         ompt_target_data_transfer_from_device, SrcPtrBegin, SrcDeviceId,
196330d8983SJohannes Doerfert         DstPtrBegin, DstDeviceId, Size, Code);
197330d8983SJohannes Doerfert   } else if (ompt_callback_target_data_op_fn) {
198330d8983SJohannes Doerfert     // HostOpId is set by the runtime
199330d8983SJohannes Doerfert     HostOpId = createOpId();
200330d8983SJohannes Doerfert     // Invoke the tool supplied data op callback
201330d8983SJohannes Doerfert     ompt_callback_target_data_op_fn(
202330d8983SJohannes Doerfert         TargetData.value, HostOpId, ompt_target_data_transfer_from_device,
203330d8983SJohannes Doerfert         SrcPtrBegin, SrcDeviceId, DstPtrBegin, DstDeviceId, Size, Code);
204330d8983SJohannes Doerfert   }
205330d8983SJohannes Doerfert }
206330d8983SJohannes Doerfert 
207330d8983SJohannes Doerfert void Interface::endTargetDataRetrieve(int64_t SrcDeviceId, void *SrcPtrBegin,
208330d8983SJohannes Doerfert                                       int64_t DstDeviceId, void *DstPtrBegin,
209330d8983SJohannes Doerfert                                       size_t Size, void *Code) {
210330d8983SJohannes Doerfert   // Only EMI callback handles end scope
211330d8983SJohannes Doerfert   if (ompt_callback_target_data_op_emi_fn) {
212330d8983SJohannes Doerfert     // HostOpId will be set by the tool. Invoke the tool supplied data op EMI
213330d8983SJohannes Doerfert     // callback
214330d8983SJohannes Doerfert     ompt_callback_target_data_op_emi_fn(
215330d8983SJohannes Doerfert         ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
216330d8983SJohannes Doerfert         ompt_target_data_transfer_from_device, SrcPtrBegin, SrcDeviceId,
217330d8983SJohannes Doerfert         DstPtrBegin, DstDeviceId, Size, Code);
218330d8983SJohannes Doerfert   }
219330d8983SJohannes Doerfert   endTargetDataOperation();
220330d8983SJohannes Doerfert }
221330d8983SJohannes Doerfert 
222*d36f66b4SMichael Halkenhäuser void Interface::beginTargetSubmit(unsigned int NumTeams) {
223330d8983SJohannes Doerfert   if (ompt_callback_target_submit_emi_fn) {
224330d8983SJohannes Doerfert     // HostOpId is set by the tool. Invoke the tool supplied target submit EMI
225330d8983SJohannes Doerfert     // callback
226330d8983SJohannes Doerfert     ompt_callback_target_submit_emi_fn(ompt_scope_begin, &TargetData, &HostOpId,
227*d36f66b4SMichael Halkenhäuser                                        NumTeams);
228330d8983SJohannes Doerfert   } else if (ompt_callback_target_submit_fn) {
229330d8983SJohannes Doerfert     // HostOpId is set by the runtime
230330d8983SJohannes Doerfert     HostOpId = createOpId();
231*d36f66b4SMichael Halkenhäuser     ompt_callback_target_submit_fn(TargetData.value, HostOpId, NumTeams);
232330d8983SJohannes Doerfert   }
233330d8983SJohannes Doerfert }
234330d8983SJohannes Doerfert 
235*d36f66b4SMichael Halkenhäuser void Interface::endTargetSubmit(unsigned int NumTeams) {
236330d8983SJohannes Doerfert   // Only EMI callback handles end scope
237330d8983SJohannes Doerfert   if (ompt_callback_target_submit_emi_fn) {
238330d8983SJohannes Doerfert     // HostOpId is set by the tool. Invoke the tool supplied target submit EMI
239330d8983SJohannes Doerfert     // callback
240330d8983SJohannes Doerfert     ompt_callback_target_submit_emi_fn(ompt_scope_end, &TargetData, &HostOpId,
241*d36f66b4SMichael Halkenhäuser                                        NumTeams);
242330d8983SJohannes Doerfert   }
243330d8983SJohannes Doerfert }
244330d8983SJohannes Doerfert 
245330d8983SJohannes Doerfert void Interface::beginTargetDataEnter(int64_t DeviceId, void *Code) {
246330d8983SJohannes Doerfert   beginTargetRegion();
247330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
248330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
249330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target_enter_data, ompt_scope_begin,
250330d8983SJohannes Doerfert                                 DeviceId, TaskData, TargetTaskData, &TargetData,
251330d8983SJohannes Doerfert                                 Code);
252330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
253330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
254330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target_enter_data, ompt_scope_begin, DeviceId,
255330d8983SJohannes Doerfert                             TaskData, TargetData.value, Code);
256330d8983SJohannes Doerfert   }
257330d8983SJohannes Doerfert }
258330d8983SJohannes Doerfert 
259330d8983SJohannes Doerfert void Interface::endTargetDataEnter(int64_t DeviceId, void *Code) {
260330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
261330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
262330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target_enter_data, ompt_scope_end,
263330d8983SJohannes Doerfert                                 DeviceId, TaskData, TargetTaskData, &TargetData,
264330d8983SJohannes Doerfert                                 Code);
265330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
266330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
267330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target_enter_data, ompt_scope_end, DeviceId,
268330d8983SJohannes Doerfert                             TaskData, TargetData.value, Code);
269330d8983SJohannes Doerfert   }
270330d8983SJohannes Doerfert   endTargetRegion();
271330d8983SJohannes Doerfert }
272330d8983SJohannes Doerfert 
273330d8983SJohannes Doerfert void Interface::beginTargetDataExit(int64_t DeviceId, void *Code) {
274330d8983SJohannes Doerfert   beginTargetRegion();
275330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
276330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
277330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target_exit_data, ompt_scope_begin,
278330d8983SJohannes Doerfert                                 DeviceId, TaskData, TargetTaskData, &TargetData,
279330d8983SJohannes Doerfert                                 Code);
280330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
281330d8983SJohannes Doerfert     TargetData.value = createRegionId();
282330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
283330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target_exit_data, ompt_scope_begin, DeviceId,
284330d8983SJohannes Doerfert                             TaskData, TargetData.value, Code);
285330d8983SJohannes Doerfert   }
286330d8983SJohannes Doerfert }
287330d8983SJohannes Doerfert 
288330d8983SJohannes Doerfert void Interface::endTargetDataExit(int64_t DeviceId, void *Code) {
289330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
290330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
291330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target_exit_data, ompt_scope_end, DeviceId,
292330d8983SJohannes Doerfert                                 TaskData, TargetTaskData, &TargetData, Code);
293330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
294330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
295330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target_exit_data, ompt_scope_end, DeviceId,
296330d8983SJohannes Doerfert                             TaskData, TargetData.value, Code);
297330d8983SJohannes Doerfert   }
298330d8983SJohannes Doerfert   endTargetRegion();
299330d8983SJohannes Doerfert }
300330d8983SJohannes Doerfert 
301330d8983SJohannes Doerfert void Interface::beginTargetUpdate(int64_t DeviceId, void *Code) {
302330d8983SJohannes Doerfert   beginTargetRegion();
303330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
304330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
305330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target_update, ompt_scope_begin, DeviceId,
306330d8983SJohannes Doerfert                                 TaskData, TargetTaskData, &TargetData, Code);
307330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
308330d8983SJohannes Doerfert     TargetData.value = createRegionId();
309330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
310330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target_update, ompt_scope_begin, DeviceId,
311330d8983SJohannes Doerfert                             TaskData, TargetData.value, Code);
312330d8983SJohannes Doerfert   }
313330d8983SJohannes Doerfert }
314330d8983SJohannes Doerfert 
315330d8983SJohannes Doerfert void Interface::endTargetUpdate(int64_t DeviceId, void *Code) {
316330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
317330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
318330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target_update, ompt_scope_end, DeviceId,
319330d8983SJohannes Doerfert                                 TaskData, TargetTaskData, &TargetData, Code);
320330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
321330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
322330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target_update, ompt_scope_end, DeviceId,
323330d8983SJohannes Doerfert                             TaskData, TargetData.value, Code);
324330d8983SJohannes Doerfert   }
325330d8983SJohannes Doerfert   endTargetRegion();
326330d8983SJohannes Doerfert }
327330d8983SJohannes Doerfert 
328caaf8099SJan Patrick Lehr void Interface::beginTargetAssociatePointer(int64_t DeviceId, void *HstPtrBegin,
329caaf8099SJan Patrick Lehr                                             void *TgtPtrBegin, size_t Size,
330caaf8099SJan Patrick Lehr                                             void *Code) {
331caaf8099SJan Patrick Lehr   beginTargetDataOperation();
332caaf8099SJan Patrick Lehr   if (ompt_callback_target_data_op_emi_fn) {
333caaf8099SJan Patrick Lehr     ompt_callback_target_data_op_emi_fn(
334caaf8099SJan Patrick Lehr         ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
335caaf8099SJan Patrick Lehr         ompt_target_data_associate, HstPtrBegin, omp_get_initial_device(),
336caaf8099SJan Patrick Lehr         TgtPtrBegin, DeviceId, Size, Code);
337caaf8099SJan Patrick Lehr   } else if (ompt_callback_target_data_op_fn) {
338caaf8099SJan Patrick Lehr     HostOpId = createOpId();
339caaf8099SJan Patrick Lehr     ompt_callback_target_data_op_fn(
340caaf8099SJan Patrick Lehr         TargetData.value, HostOpId, ompt_target_data_associate, HstPtrBegin,
341caaf8099SJan Patrick Lehr         omp_get_initial_device(), TgtPtrBegin, DeviceId, Size, Code);
342caaf8099SJan Patrick Lehr   }
343caaf8099SJan Patrick Lehr }
344caaf8099SJan Patrick Lehr 
345caaf8099SJan Patrick Lehr void Interface::endTargetAssociatePointer(int64_t DeviceId, void *HstPtrBegin,
346caaf8099SJan Patrick Lehr                                           void *TgtPtrBegin, size_t Size,
347caaf8099SJan Patrick Lehr                                           void *Code) {
348caaf8099SJan Patrick Lehr   if (ompt_callback_target_data_op_emi_fn) {
349caaf8099SJan Patrick Lehr     ompt_callback_target_data_op_emi_fn(
350caaf8099SJan Patrick Lehr         ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
351caaf8099SJan Patrick Lehr         ompt_target_data_associate, HstPtrBegin, omp_get_initial_device(),
352caaf8099SJan Patrick Lehr         TgtPtrBegin, DeviceId, Size, Code);
353caaf8099SJan Patrick Lehr   }
354caaf8099SJan Patrick Lehr }
355caaf8099SJan Patrick Lehr 
356caaf8099SJan Patrick Lehr void Interface::beginTargetDisassociatePointer(int64_t DeviceId,
357caaf8099SJan Patrick Lehr                                                void *HstPtrBegin,
358caaf8099SJan Patrick Lehr                                                void *TgtPtrBegin, size_t Size,
359caaf8099SJan Patrick Lehr                                                void *Code) {
360caaf8099SJan Patrick Lehr   beginTargetDataOperation();
361caaf8099SJan Patrick Lehr   if (ompt_callback_target_data_op_emi_fn) {
362caaf8099SJan Patrick Lehr     ompt_callback_target_data_op_emi_fn(
363caaf8099SJan Patrick Lehr         ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
364caaf8099SJan Patrick Lehr         ompt_target_data_disassociate, HstPtrBegin, omp_get_initial_device(),
365caaf8099SJan Patrick Lehr         TgtPtrBegin, DeviceId, Size, Code);
366caaf8099SJan Patrick Lehr   } else if (ompt_callback_target_data_op_fn) {
367caaf8099SJan Patrick Lehr     HostOpId = createOpId();
368caaf8099SJan Patrick Lehr     ompt_callback_target_data_op_fn(
369caaf8099SJan Patrick Lehr         TargetData.value, HostOpId, ompt_target_data_disassociate, HstPtrBegin,
370caaf8099SJan Patrick Lehr         omp_get_initial_device(), TgtPtrBegin, DeviceId, Size, Code);
371caaf8099SJan Patrick Lehr   }
372caaf8099SJan Patrick Lehr }
373caaf8099SJan Patrick Lehr void Interface::endTargetDisassociatePointer(int64_t DeviceId,
374caaf8099SJan Patrick Lehr                                              void *HstPtrBegin,
375caaf8099SJan Patrick Lehr                                              void *TgtPtrBegin, size_t Size,
376caaf8099SJan Patrick Lehr                                              void *Code) {
377caaf8099SJan Patrick Lehr   if (ompt_callback_target_data_op_emi_fn) {
378caaf8099SJan Patrick Lehr     ompt_callback_target_data_op_emi_fn(
379caaf8099SJan Patrick Lehr         ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
380caaf8099SJan Patrick Lehr         ompt_target_data_disassociate, HstPtrBegin, omp_get_initial_device(),
381caaf8099SJan Patrick Lehr         TgtPtrBegin, DeviceId, Size, Code);
382caaf8099SJan Patrick Lehr   }
383caaf8099SJan Patrick Lehr }
384caaf8099SJan Patrick Lehr 
385330d8983SJohannes Doerfert void Interface::beginTarget(int64_t DeviceId, void *Code) {
386330d8983SJohannes Doerfert   beginTargetRegion();
387330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
388330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
389330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target, ompt_scope_begin, DeviceId,
390330d8983SJohannes Doerfert                                 TaskData, TargetTaskData, &TargetData, Code);
391330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
392330d8983SJohannes Doerfert     TargetData.value = createRegionId();
393330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
394330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target, ompt_scope_begin, DeviceId, TaskData,
395330d8983SJohannes Doerfert                             TargetData.value, Code);
396330d8983SJohannes Doerfert   }
397330d8983SJohannes Doerfert }
398330d8983SJohannes Doerfert 
399330d8983SJohannes Doerfert void Interface::endTarget(int64_t DeviceId, void *Code) {
400330d8983SJohannes Doerfert   if (ompt_callback_target_emi_fn) {
401330d8983SJohannes Doerfert     // Invoke the tool supplied target EMI callback
402330d8983SJohannes Doerfert     ompt_callback_target_emi_fn(ompt_target, ompt_scope_end, DeviceId, TaskData,
403330d8983SJohannes Doerfert                                 TargetTaskData, &TargetData, Code);
404330d8983SJohannes Doerfert   } else if (ompt_callback_target_fn) {
405330d8983SJohannes Doerfert     // Invoke the tool supplied target callback
406330d8983SJohannes Doerfert     ompt_callback_target_fn(ompt_target, ompt_scope_end, DeviceId, TaskData,
407330d8983SJohannes Doerfert                             TargetData.value, Code);
408330d8983SJohannes Doerfert   }
409330d8983SJohannes Doerfert   endTargetRegion();
410330d8983SJohannes Doerfert }
411330d8983SJohannes Doerfert 
412330d8983SJohannes Doerfert void Interface::beginTargetDataOperation() {
413330d8983SJohannes Doerfert   DP("in ompt_target_region_begin (TargetRegionId = %lu)\n", TargetData.value);
414330d8983SJohannes Doerfert }
415330d8983SJohannes Doerfert 
416330d8983SJohannes Doerfert void Interface::endTargetDataOperation() {
417330d8983SJohannes Doerfert   DP("in ompt_target_region_end (TargetRegionId = %lu)\n", TargetData.value);
418330d8983SJohannes Doerfert }
419330d8983SJohannes Doerfert 
420330d8983SJohannes Doerfert void Interface::beginTargetRegion() {
421330d8983SJohannes Doerfert   // Set up task state
422330d8983SJohannes Doerfert   assert(ompt_get_task_data_fn && "Calling a null task data function");
423330d8983SJohannes Doerfert   TaskData = ompt_get_task_data_fn();
424330d8983SJohannes Doerfert   // Set up target task state
425330d8983SJohannes Doerfert   assert(ompt_get_target_task_data_fn &&
426330d8983SJohannes Doerfert          "Calling a null target task data function");
427330d8983SJohannes Doerfert   TargetTaskData = ompt_get_target_task_data_fn();
428330d8983SJohannes Doerfert   // Target state will be set later
429330d8983SJohannes Doerfert   TargetData = ompt_data_none;
430330d8983SJohannes Doerfert }
431330d8983SJohannes Doerfert 
432330d8983SJohannes Doerfert void Interface::endTargetRegion() {
433330d8983SJohannes Doerfert   TaskData = 0;
434330d8983SJohannes Doerfert   TargetTaskData = 0;
435330d8983SJohannes Doerfert   TargetData = ompt_data_none;
436330d8983SJohannes Doerfert }
437330d8983SJohannes Doerfert 
438330d8983SJohannes Doerfert /// Used to maintain the finalization functions that are received
439330d8983SJohannes Doerfert /// from the plugins during connect.
440330d8983SJohannes Doerfert /// Note: Currently, there are no plugin-specific finalizations, so each plugin
441330d8983SJohannes Doerfert /// will call the same (empty) function.
442330d8983SJohannes Doerfert class LibomptargetRtlFinalizer {
443330d8983SJohannes Doerfert public:
444330d8983SJohannes Doerfert   LibomptargetRtlFinalizer() {}
445330d8983SJohannes Doerfert 
446330d8983SJohannes Doerfert   void registerRtl(ompt_finalize_t FinalizationFunction) {
447330d8983SJohannes Doerfert     if (FinalizationFunction) {
448330d8983SJohannes Doerfert       RtlFinalizationFunctions.emplace_back(FinalizationFunction);
449330d8983SJohannes Doerfert     }
450330d8983SJohannes Doerfert   }
451330d8983SJohannes Doerfert 
452330d8983SJohannes Doerfert   void finalize() {
453330d8983SJohannes Doerfert     for (auto FinalizationFunction : RtlFinalizationFunctions)
454*d36f66b4SMichael Halkenhäuser       FinalizationFunction(/*tool_data=*/nullptr);
455330d8983SJohannes Doerfert     RtlFinalizationFunctions.clear();
456330d8983SJohannes Doerfert   }
457330d8983SJohannes Doerfert 
458330d8983SJohannes Doerfert private:
459330d8983SJohannes Doerfert   llvm::SmallVector<ompt_finalize_t> RtlFinalizationFunctions;
460330d8983SJohannes Doerfert };
461330d8983SJohannes Doerfert 
462330d8983SJohannes Doerfert int llvm::omp::target::ompt::initializeLibrary(ompt_function_lookup_t lookup,
463330d8983SJohannes Doerfert                                                int initial_device_num,
464330d8983SJohannes Doerfert                                                ompt_data_t *tool_data) {
465*d36f66b4SMichael Halkenhäuser   DP("Executing initializeLibrary\n");
466330d8983SJohannes Doerfert #define bindOmptFunctionName(OmptFunction, DestinationFunction)                \
467*d36f66b4SMichael Halkenhäuser   if (lookup)                                                                  \
468330d8983SJohannes Doerfert     DestinationFunction = (OmptFunction##_t)lookup(#OmptFunction);             \
469*d36f66b4SMichael Halkenhäuser   DP("initializeLibrary bound %s=%p\n", #DestinationFunction,                  \
470330d8983SJohannes Doerfert      ((void *)(uint64_t)DestinationFunction));
471330d8983SJohannes Doerfert 
472330d8983SJohannes Doerfert   bindOmptFunctionName(ompt_get_callback, lookupCallbackByCode);
473330d8983SJohannes Doerfert   bindOmptFunctionName(ompt_get_task_data, ompt_get_task_data_fn);
474330d8983SJohannes Doerfert   bindOmptFunctionName(ompt_get_target_task_data, ompt_get_target_task_data_fn);
475330d8983SJohannes Doerfert #undef bindOmptFunctionName
476330d8983SJohannes Doerfert 
477330d8983SJohannes Doerfert   // Store pointer of 'ompt_libomp_target_fn_lookup' for use by libomptarget
478330d8983SJohannes Doerfert   lookupCallbackByName = lookup;
479330d8983SJohannes Doerfert 
480330d8983SJohannes Doerfert   assert(lookupCallbackByCode && "lookupCallbackByCode should be non-null");
481330d8983SJohannes Doerfert   assert(lookupCallbackByName && "lookupCallbackByName should be non-null");
482330d8983SJohannes Doerfert   assert(ompt_get_task_data_fn && "ompt_get_task_data_fn should be non-null");
483330d8983SJohannes Doerfert   assert(ompt_get_target_task_data_fn &&
484330d8983SJohannes Doerfert          "ompt_get_target_task_data_fn should be non-null");
485330d8983SJohannes Doerfert   assert(LibraryFinalizer == nullptr &&
486330d8983SJohannes Doerfert          "LibraryFinalizer should not be initialized yet");
487330d8983SJohannes Doerfert 
488330d8983SJohannes Doerfert   LibraryFinalizer = new LibomptargetRtlFinalizer();
489330d8983SJohannes Doerfert 
490330d8983SJohannes Doerfert   Initialized = true;
491330d8983SJohannes Doerfert 
492330d8983SJohannes Doerfert   return 0;
493330d8983SJohannes Doerfert }
494330d8983SJohannes Doerfert 
495330d8983SJohannes Doerfert void llvm::omp::target::ompt::finalizeLibrary(ompt_data_t *data) {
496*d36f66b4SMichael Halkenhäuser   DP("Executing finalizeLibrary\n");
497330d8983SJohannes Doerfert   // Before disabling OMPT, call the (plugin) finalizations that were registered
498330d8983SJohannes Doerfert   // with this library
499330d8983SJohannes Doerfert   LibraryFinalizer->finalize();
500330d8983SJohannes Doerfert   delete LibraryFinalizer;
501330d8983SJohannes Doerfert   Initialized = false;
502330d8983SJohannes Doerfert }
503330d8983SJohannes Doerfert 
504330d8983SJohannes Doerfert void llvm::omp::target::ompt::connectLibrary() {
505*d36f66b4SMichael Halkenhäuser   DP("Entering connectLibrary\n");
506330d8983SJohannes Doerfert   // Connect with libomp
507330d8983SJohannes Doerfert   static OmptLibraryConnectorTy LibompConnector("libomp");
508330d8983SJohannes Doerfert   static ompt_start_tool_result_t OmptResult;
509330d8983SJohannes Doerfert 
510330d8983SJohannes Doerfert   // Initialize OmptResult with the init and fini functions that will be
511330d8983SJohannes Doerfert   // called by the connector
512330d8983SJohannes Doerfert   OmptResult.initialize = ompt::initializeLibrary;
513330d8983SJohannes Doerfert   OmptResult.finalize = ompt::finalizeLibrary;
514330d8983SJohannes Doerfert   OmptResult.tool_data.value = 0;
515330d8983SJohannes Doerfert 
516330d8983SJohannes Doerfert   // Now call connect that causes the above init/fini functions to be called
517330d8983SJohannes Doerfert   LibompConnector.connect(&OmptResult);
518330d8983SJohannes Doerfert 
519330d8983SJohannes Doerfert #define bindOmptCallback(Name, Type, Code)                                     \
520330d8983SJohannes Doerfert   if (lookupCallbackByCode)                                                    \
521330d8983SJohannes Doerfert     lookupCallbackByCode(                                                      \
522330d8983SJohannes Doerfert         (ompt_callbacks_t)(Code),                                              \
523330d8983SJohannes Doerfert         (ompt_callback_t *)&(llvm::omp::target::ompt::Name##_fn));
524330d8983SJohannes Doerfert   FOREACH_OMPT_NOEMI_EVENT(bindOmptCallback)
525330d8983SJohannes Doerfert   FOREACH_OMPT_EMI_EVENT(bindOmptCallback)
526330d8983SJohannes Doerfert #undef bindOmptCallback
527330d8983SJohannes Doerfert 
528*d36f66b4SMichael Halkenhäuser   DP("Exiting connectLibrary\n");
529330d8983SJohannes Doerfert }
530330d8983SJohannes Doerfert 
531330d8983SJohannes Doerfert #endif // OMPT_SUPPORT
532