1 | //===-- OpenMP/Mapping.cpp - OpenMP/OpenACC pointer mapping impl. ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | //===----------------------------------------------------------------------===// |
10 | |
11 | #include "OpenMP/Mapping.h" |
12 | |
13 | #include "PluginManager.h" |
14 | #include "Shared/Debug.h" |
15 | #include "Shared/Requirements.h" |
16 | #include "device.h" |
17 | |
18 | /// Dump a table of all the host-target pointer pairs on failure |
19 | void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device, |
20 | bool toStdOut) { |
21 | MappingInfoTy::HDTTMapAccessorTy HDTTMap = |
22 | Device.getMappingInfo().HostDataToTargetMap.getExclusiveAccessor(); |
23 | if (HDTTMap->empty()) { |
24 | DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, |
25 | "OpenMP Host-Device pointer mappings table empty\n" ); |
26 | return; |
27 | } |
28 | |
29 | SourceInfo Kernel(Loc); |
30 | DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, |
31 | "OpenMP Host-Device pointer mappings after block at %s:%d:%d:\n" , |
32 | Kernel.getFilename(), Kernel.getLine(), Kernel.getColumn()); |
33 | DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, |
34 | "%-18s %-18s %s %s %s %s\n" , "Host Ptr" , "Target Ptr" , "Size (B)" , |
35 | "DynRefCount" , "HoldRefCount" , "Declaration" ); |
36 | for (const auto &It : *HDTTMap) { |
37 | HostDataToTargetTy &HDTT = *It.HDTT; |
38 | SourceInfo Info(HDTT.HstPtrName); |
39 | DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, |
40 | DPxMOD " " DPxMOD " %-8" PRIuPTR " %-11s %-12s %s at %s:%d:%d\n" , |
41 | DPxPTR(HDTT.HstPtrBegin), DPxPTR(HDTT.TgtPtrBegin), |
42 | HDTT.HstPtrEnd - HDTT.HstPtrBegin, |
43 | HDTT.dynRefCountToStr().c_str(), HDTT.holdRefCountToStr().c_str(), |
44 | Info.getName(), Info.getFilename(), Info.getLine(), |
45 | Info.getColumn()); |
46 | } |
47 | } |
48 | |
49 | int MappingInfoTy::associatePtr(void *HstPtrBegin, void *TgtPtrBegin, |
50 | int64_t Size) { |
51 | HDTTMapAccessorTy HDTTMap = HostDataToTargetMap.getExclusiveAccessor(); |
52 | |
53 | // Check if entry exists |
54 | auto It = HDTTMap->find(HstPtrBegin); |
55 | if (It != HDTTMap->end()) { |
56 | HostDataToTargetTy &HDTT = *It->HDTT; |
57 | std::lock_guard<HostDataToTargetTy> LG(HDTT); |
58 | // Mapping already exists |
59 | bool IsValid = HDTT.HstPtrEnd == (uintptr_t)HstPtrBegin + Size && |
60 | HDTT.TgtPtrBegin == (uintptr_t)TgtPtrBegin; |
61 | if (IsValid) { |
62 | DP("Attempt to re-associate the same device ptr+offset with the same " |
63 | "host ptr, nothing to do\n" ); |
64 | return OFFLOAD_SUCCESS; |
65 | } |
66 | REPORT("Not allowed to re-associate a different device ptr+offset with " |
67 | "the same host ptr\n" ); |
68 | return OFFLOAD_FAIL; |
69 | } |
70 | |
71 | // Mapping does not exist, allocate it with refCount=INF |
72 | const HostDataToTargetTy &NewEntry = |
73 | *HDTTMap |
74 | ->emplace(new HostDataToTargetTy( |
75 | /*HstPtrBase=*/(uintptr_t)HstPtrBegin, |
76 | /*HstPtrBegin=*/(uintptr_t)HstPtrBegin, |
77 | /*HstPtrEnd=*/(uintptr_t)HstPtrBegin + Size, |
78 | /*TgtAllocBegin=*/(uintptr_t)TgtPtrBegin, |
79 | /*TgtPtrBegin=*/(uintptr_t)TgtPtrBegin, |
80 | /*UseHoldRefCount=*/false, /*Name=*/nullptr, |
81 | /*IsRefCountINF=*/true)) |
82 | .first->HDTT; |
83 | DP("Creating new map entry: HstBase=" DPxMOD ", HstBegin=" DPxMOD |
84 | ", HstEnd=" DPxMOD ", TgtBegin=" DPxMOD ", DynRefCount=%s, " |
85 | "HoldRefCount=%s\n" , |
86 | DPxPTR(NewEntry.HstPtrBase), DPxPTR(NewEntry.HstPtrBegin), |
87 | DPxPTR(NewEntry.HstPtrEnd), DPxPTR(NewEntry.TgtPtrBegin), |
88 | NewEntry.dynRefCountToStr().c_str(), NewEntry.holdRefCountToStr().c_str()); |
89 | (void)NewEntry; |
90 | |
91 | // Notify the plugin about the new mapping. |
92 | return Device.notifyDataMapped(HstPtrBegin, Size); |
93 | } |
94 | |
95 | int MappingInfoTy::disassociatePtr(void *HstPtrBegin) { |
96 | HDTTMapAccessorTy HDTTMap = HostDataToTargetMap.getExclusiveAccessor(); |
97 | |
98 | auto It = HDTTMap->find(HstPtrBegin); |
99 | if (It == HDTTMap->end()) { |
100 | REPORT("Association not found\n" ); |
101 | return OFFLOAD_FAIL; |
102 | } |
103 | // Mapping exists |
104 | HostDataToTargetTy &HDTT = *It->HDTT; |
105 | std::lock_guard<HostDataToTargetTy> LG(HDTT); |
106 | |
107 | if (HDTT.getHoldRefCount()) { |
108 | // This is based on OpenACC 3.1, sec 3.2.33 "acc_unmap_data", L3656-3657: |
109 | // "It is an error to call acc_unmap_data if the structured reference |
110 | // count for the pointer is not zero." |
111 | REPORT("Trying to disassociate a pointer with a non-zero hold reference " |
112 | "count\n" ); |
113 | return OFFLOAD_FAIL; |
114 | } |
115 | |
116 | if (HDTT.isDynRefCountInf()) { |
117 | DP("Association found, removing it\n" ); |
118 | void *Event = HDTT.getEvent(); |
119 | delete &HDTT; |
120 | if (Event) |
121 | Device.destroyEvent(Event); |
122 | HDTTMap->erase(It); |
123 | return Device.notifyDataUnmapped(HstPtrBegin); |
124 | } |
125 | |
126 | REPORT("Trying to disassociate a pointer which was not mapped via " |
127 | "omp_target_associate_ptr\n" ); |
128 | return OFFLOAD_FAIL; |
129 | } |
130 | |
131 | LookupResult MappingInfoTy::lookupMapping(HDTTMapAccessorTy &HDTTMap, |
132 | void *HstPtrBegin, int64_t Size, |
133 | HostDataToTargetTy *OwnedTPR) { |
134 | |
135 | uintptr_t HP = (uintptr_t)HstPtrBegin; |
136 | LookupResult LR; |
137 | |
138 | DP("Looking up mapping(HstPtrBegin=" DPxMOD ", Size=%" PRId64 ")...\n" , |
139 | DPxPTR(HP), Size); |
140 | |
141 | if (HDTTMap->empty()) |
142 | return LR; |
143 | |
144 | // HDTTMap is std::set, ordered by HstPtrBegin. |
145 | // Upper is the first element whose HstPtrBegin > HP. |
146 | auto Upper = HDTTMap->upper_bound(HP); |
147 | |
148 | if (Size == 0) { |
149 | // HP satisfies |
150 | // std::prev(Upper)->HDTT.HstPtrBegin <= HP < Upper->HDTT.HstPtrBegin |
151 | if (Upper != HDTTMap->begin()) { |
152 | LR.TPR.setEntry(std::prev(Upper)->HDTT, OwnedTPR); |
153 | // We know that HP >= LR.TPR.getEntry()->HstPtrBegin |
154 | LR.Flags.IsContained = HP < LR.TPR.getEntry()->HstPtrEnd; |
155 | } |
156 | |
157 | if (!LR.Flags.IsContained && Upper != HDTTMap->end()) { |
158 | LR.TPR.setEntry(Upper->HDTT, OwnedTPR); |
159 | // This is a special case: HP is not really contained in the mapped |
160 | // address range, but it's contained in the extended address range, |
161 | // which suffices to get the mapping of the base pointer. |
162 | // We know that HP < LR.TPR.getEntry()->HstPtrBegin |
163 | LR.Flags.IsContained = HP >= LR.TPR.getEntry()->HstPtrBase; |
164 | } |
165 | } else { |
166 | if (Upper != HDTTMap->begin()) { |
167 | LR.TPR.setEntry(std::prev(Upper)->HDTT, OwnedTPR); |
168 | // We know that HP >= LR.TPR.getEntry()->HstPtrBegin |
169 | LR.Flags.IsContained = HP < LR.TPR.getEntry()->HstPtrEnd && |
170 | (HP + Size) <= LR.TPR.getEntry()->HstPtrEnd; |
171 | // Does it extend beyond the mapped address range? |
172 | LR.Flags.ExtendsAfter = HP < LR.TPR.getEntry()->HstPtrEnd && |
173 | (HP + Size) > LR.TPR.getEntry()->HstPtrEnd; |
174 | } |
175 | |
176 | if (!(LR.Flags.IsContained || LR.Flags.ExtendsAfter) && |
177 | Upper != HDTTMap->end()) { |
178 | LR.TPR.setEntry(Upper->HDTT, OwnedTPR); |
179 | // Does it extend into an already mapped address range? |
180 | // We know that HP < LR.TPR.getEntry()->HstPtrBegin |
181 | LR.Flags.ExtendsBefore = (HP + Size) > LR.TPR.getEntry()->HstPtrBegin; |
182 | // Does it extend beyond the mapped address range? |
183 | LR.Flags.ExtendsAfter = HP < LR.TPR.getEntry()->HstPtrEnd && |
184 | (HP + Size) > LR.TPR.getEntry()->HstPtrEnd; |
185 | } |
186 | |
187 | if (LR.Flags.ExtendsBefore) { |
188 | DP("WARNING: Pointer is not mapped but section extends into already " |
189 | "mapped data\n" ); |
190 | } |
191 | if (LR.Flags.ExtendsAfter) { |
192 | DP("WARNING: Pointer is already mapped but section extends beyond mapped " |
193 | "region\n" ); |
194 | } |
195 | } |
196 | |
197 | return LR; |
198 | } |
199 | |
200 | TargetPointerResultTy MappingInfoTy::getTargetPointer( |
201 | HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase, |
202 | int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName, bool HasFlagTo, |
203 | bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount, |
204 | bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier, |
205 | AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR, bool ReleaseHDTTMap) { |
206 | |
207 | LookupResult LR = lookupMapping(HDTTMap, HstPtrBegin, Size, OwnedTPR); |
208 | LR.TPR.Flags.IsPresent = true; |
209 | |
210 | // Release the mapping table lock only after the entry is locked by |
211 | // attaching it to TPR. Once TPR is destroyed it will release the lock |
212 | // on entry. If it is returned the lock will move to the returned object. |
213 | // If LR.Entry is already owned/locked we avoid trying to lock it again. |
214 | |
215 | // Check if the pointer is contained. |
216 | // If a variable is mapped to the device manually by the user - which would |
217 | // lead to the IsContained flag to be true - then we must ensure that the |
218 | // device address is returned even under unified memory conditions. |
219 | if (LR.Flags.IsContained || |
220 | ((LR.Flags.ExtendsBefore || LR.Flags.ExtendsAfter) && IsImplicit)) { |
221 | const char *RefCountAction; |
222 | if (UpdateRefCount) { |
223 | // After this, reference count >= 1. If the reference count was 0 but the |
224 | // entry was still there we can reuse the data on the device and avoid a |
225 | // new submission. |
226 | LR.TPR.getEntry()->incRefCount(HasHoldModifier); |
227 | RefCountAction = " (incremented)" ; |
228 | } else { |
229 | // It might have been allocated with the parent, but it's still new. |
230 | LR.TPR.Flags.IsNewEntry = LR.TPR.getEntry()->getTotalRefCount() == 1; |
231 | RefCountAction = " (update suppressed)" ; |
232 | } |
233 | const char *DynRefCountAction = HasHoldModifier ? "" : RefCountAction; |
234 | const char *HoldRefCountAction = HasHoldModifier ? RefCountAction : "" ; |
235 | uintptr_t Ptr = LR.TPR.getEntry()->TgtPtrBegin + |
236 | ((uintptr_t)HstPtrBegin - LR.TPR.getEntry()->HstPtrBegin); |
237 | INFO(OMP_INFOTYPE_MAPPING_EXISTS, Device.DeviceID, |
238 | "Mapping exists%s with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD |
239 | ", Size=%" PRId64 ", DynRefCount=%s%s, HoldRefCount=%s%s, Name=%s\n" , |
240 | (IsImplicit ? " (implicit)" : "" ), DPxPTR(HstPtrBegin), DPxPTR(Ptr), |
241 | Size, LR.TPR.getEntry()->dynRefCountToStr().c_str(), DynRefCountAction, |
242 | LR.TPR.getEntry()->holdRefCountToStr().c_str(), HoldRefCountAction, |
243 | (HstPtrName) ? getNameFromMapping(HstPtrName).c_str() : "unknown" ); |
244 | LR.TPR.TargetPointer = (void *)Ptr; |
245 | } else if ((LR.Flags.ExtendsBefore || LR.Flags.ExtendsAfter) && !IsImplicit) { |
246 | // Explicit extension of mapped data - not allowed. |
247 | MESSAGE("explicit extension not allowed: host address specified is " DPxMOD |
248 | " (%" PRId64 |
249 | " bytes), but device allocation maps to host at " DPxMOD |
250 | " (%" PRId64 " bytes)" , |
251 | DPxPTR(HstPtrBegin), Size, DPxPTR(LR.TPR.getEntry()->HstPtrBegin), |
252 | LR.TPR.getEntry()->HstPtrEnd - LR.TPR.getEntry()->HstPtrBegin); |
253 | if (HasPresentModifier) |
254 | MESSAGE("device mapping required by 'present' map type modifier does not " |
255 | "exist for host address " DPxMOD " (%" PRId64 " bytes)" , |
256 | DPxPTR(HstPtrBegin), Size); |
257 | } else if ((PM->getRequirements() & OMP_REQ_UNIFIED_SHARED_MEMORY && |
258 | !HasCloseModifier) || |
259 | (PM->getRequirements() & OMPX_REQ_AUTO_ZERO_COPY)) { |
260 | |
261 | // If unified shared memory is active, implicitly mapped variables that are |
262 | // not privatized use host address. Any explicitly mapped variables also use |
263 | // host address where correctness is not impeded. In all other cases maps |
264 | // are respected. |
265 | // In addition to the mapping rules above, the close map modifier forces the |
266 | // mapping of the variable to the device. |
267 | if (Size) { |
268 | INFO(OMP_INFOTYPE_MAPPING_CHANGED, Device.DeviceID, |
269 | "Return HstPtrBegin " DPxMOD " Size=%" PRId64 " for unified shared " |
270 | "memory\n" , |
271 | DPxPTR((uintptr_t)HstPtrBegin), Size); |
272 | DP("Return HstPtrBegin " DPxMOD " Size=%" PRId64 " for unified shared " |
273 | "memory\n" , |
274 | DPxPTR((uintptr_t)HstPtrBegin), Size); |
275 | LR.TPR.Flags.IsPresent = false; |
276 | LR.TPR.Flags.IsHostPointer = true; |
277 | LR.TPR.TargetPointer = HstPtrBegin; |
278 | } |
279 | } else if (HasPresentModifier) { |
280 | DP("Mapping required by 'present' map type modifier does not exist for " |
281 | "HstPtrBegin=" DPxMOD ", Size=%" PRId64 "\n" , |
282 | DPxPTR(HstPtrBegin), Size); |
283 | MESSAGE("device mapping required by 'present' map type modifier does not " |
284 | "exist for host address " DPxMOD " (%" PRId64 " bytes)" , |
285 | DPxPTR(HstPtrBegin), Size); |
286 | } else if (Size) { |
287 | // If it is not contained and Size > 0, we should create a new entry for it. |
288 | LR.TPR.Flags.IsNewEntry = true; |
289 | uintptr_t TgtAllocBegin = |
290 | (uintptr_t)Device.allocData(TgtPadding + Size, HstPtrBegin); |
291 | uintptr_t TgtPtrBegin = TgtAllocBegin + TgtPadding; |
292 | // Release the mapping table lock only after the entry is locked by |
293 | // attaching it to TPR. |
294 | LR.TPR.setEntry(HDTTMap |
295 | ->emplace(new HostDataToTargetTy( |
296 | (uintptr_t)HstPtrBase, (uintptr_t)HstPtrBegin, |
297 | (uintptr_t)HstPtrBegin + Size, TgtAllocBegin, |
298 | TgtPtrBegin, HasHoldModifier, HstPtrName)) |
299 | .first->HDTT); |
300 | INFO(OMP_INFOTYPE_MAPPING_CHANGED, Device.DeviceID, |
301 | "Creating new map entry with HstPtrBase=" DPxMOD |
302 | ", HstPtrBegin=" DPxMOD ", TgtAllocBegin=" DPxMOD |
303 | ", TgtPtrBegin=" DPxMOD |
304 | ", Size=%ld, DynRefCount=%s, HoldRefCount=%s, Name=%s\n" , |
305 | DPxPTR(HstPtrBase), DPxPTR(HstPtrBegin), DPxPTR(TgtAllocBegin), |
306 | DPxPTR(TgtPtrBegin), Size, |
307 | LR.TPR.getEntry()->dynRefCountToStr().c_str(), |
308 | LR.TPR.getEntry()->holdRefCountToStr().c_str(), |
309 | (HstPtrName) ? getNameFromMapping(HstPtrName).c_str() : "unknown" ); |
310 | LR.TPR.TargetPointer = (void *)TgtPtrBegin; |
311 | |
312 | // Notify the plugin about the new mapping. |
313 | if (Device.notifyDataMapped(HstPtrBegin, Size)) |
314 | return TargetPointerResultTy{}; |
315 | } else { |
316 | // This entry is not present and we did not create a new entry for it. |
317 | LR.TPR.Flags.IsPresent = false; |
318 | } |
319 | |
320 | // All mapping table modifications have been made. If the user requested it we |
321 | // give up the lock. |
322 | if (ReleaseHDTTMap) |
323 | HDTTMap.destroy(); |
324 | |
325 | // If the target pointer is valid, and we need to transfer data, issue the |
326 | // data transfer. |
327 | if (LR.TPR.TargetPointer && !LR.TPR.Flags.IsHostPointer && HasFlagTo && |
328 | (LR.TPR.Flags.IsNewEntry || HasFlagAlways) && Size != 0) { |
329 | DP("Moving %" PRId64 " bytes (hst:" DPxMOD ") -> (tgt:" DPxMOD ")\n" , Size, |
330 | DPxPTR(HstPtrBegin), DPxPTR(LR.TPR.TargetPointer)); |
331 | |
332 | int Ret = Device.submitData(LR.TPR.TargetPointer, HstPtrBegin, Size, |
333 | AsyncInfo, LR.TPR.getEntry()); |
334 | if (Ret != OFFLOAD_SUCCESS) { |
335 | REPORT("Copying data to device failed.\n" ); |
336 | // We will also return nullptr if the data movement fails because that |
337 | // pointer points to a corrupted memory region so it doesn't make any |
338 | // sense to continue to use it. |
339 | LR.TPR.TargetPointer = nullptr; |
340 | } else if (LR.TPR.getEntry()->addEventIfNecessary(Device, AsyncInfo) != |
341 | OFFLOAD_SUCCESS) |
342 | return TargetPointerResultTy{}; |
343 | } else { |
344 | // If not a host pointer and no present modifier, we need to wait for the |
345 | // event if it exists. |
346 | // Note: Entry might be nullptr because of zero length array section. |
347 | if (LR.TPR.getEntry() && !LR.TPR.Flags.IsHostPointer && |
348 | !HasPresentModifier) { |
349 | void *Event = LR.TPR.getEntry()->getEvent(); |
350 | if (Event) { |
351 | int Ret = Device.waitEvent(Event, AsyncInfo); |
352 | if (Ret != OFFLOAD_SUCCESS) { |
353 | // If it fails to wait for the event, we need to return nullptr in |
354 | // case of any data race. |
355 | REPORT("Failed to wait for event " DPxMOD ".\n" , DPxPTR(Event)); |
356 | return TargetPointerResultTy{}; |
357 | } |
358 | } |
359 | } |
360 | } |
361 | |
362 | return std::move(LR.TPR); |
363 | } |
364 | |
365 | TargetPointerResultTy MappingInfoTy::getTgtPtrBegin( |
366 | void *HstPtrBegin, int64_t Size, bool UpdateRefCount, bool UseHoldRefCount, |
367 | bool MustContain, bool ForceDelete, bool FromDataEnd) { |
368 | HDTTMapAccessorTy HDTTMap = HostDataToTargetMap.getExclusiveAccessor(); |
369 | |
370 | LookupResult LR = lookupMapping(HDTTMap, HstPtrBegin, Size); |
371 | |
372 | LR.TPR.Flags.IsPresent = true; |
373 | |
374 | if (LR.Flags.IsContained || |
375 | (!MustContain && (LR.Flags.ExtendsBefore || LR.Flags.ExtendsAfter))) { |
376 | LR.TPR.Flags.IsLast = |
377 | LR.TPR.getEntry()->decShouldRemove(UseHoldRefCount, ForceDelete); |
378 | |
379 | if (ForceDelete) { |
380 | LR.TPR.getEntry()->resetRefCount(UseHoldRefCount); |
381 | assert(LR.TPR.Flags.IsLast == |
382 | LR.TPR.getEntry()->decShouldRemove(UseHoldRefCount) && |
383 | "expected correct IsLast prediction for reset" ); |
384 | } |
385 | |
386 | // Increment the number of threads that is using the entry on a |
387 | // targetDataEnd, tracking the number of possible "deleters". A thread may |
388 | // come to own the entry deletion even if it was not the last one querying |
389 | // for it. Thus, we must track every query on targetDataEnds to ensure only |
390 | // the last thread that holds a reference to an entry actually deletes it. |
391 | if (FromDataEnd) |
392 | LR.TPR.getEntry()->incDataEndThreadCount(); |
393 | |
394 | const char *RefCountAction; |
395 | if (!UpdateRefCount) { |
396 | RefCountAction = " (update suppressed)" ; |
397 | } else if (LR.TPR.Flags.IsLast) { |
398 | LR.TPR.getEntry()->decRefCount(UseHoldRefCount); |
399 | assert(LR.TPR.getEntry()->getTotalRefCount() == 0 && |
400 | "Expected zero reference count when deletion is scheduled" ); |
401 | if (ForceDelete) |
402 | RefCountAction = " (reset, delayed deletion)" ; |
403 | else |
404 | RefCountAction = " (decremented, delayed deletion)" ; |
405 | } else { |
406 | LR.TPR.getEntry()->decRefCount(UseHoldRefCount); |
407 | RefCountAction = " (decremented)" ; |
408 | } |
409 | const char *DynRefCountAction = UseHoldRefCount ? "" : RefCountAction; |
410 | const char *HoldRefCountAction = UseHoldRefCount ? RefCountAction : "" ; |
411 | uintptr_t TP = LR.TPR.getEntry()->TgtPtrBegin + |
412 | ((uintptr_t)HstPtrBegin - LR.TPR.getEntry()->HstPtrBegin); |
413 | INFO(OMP_INFOTYPE_MAPPING_EXISTS, Device.DeviceID, |
414 | "Mapping exists with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD ", " |
415 | "Size=%" PRId64 ", DynRefCount=%s%s, HoldRefCount=%s%s\n" , |
416 | DPxPTR(HstPtrBegin), DPxPTR(TP), Size, |
417 | LR.TPR.getEntry()->dynRefCountToStr().c_str(), DynRefCountAction, |
418 | LR.TPR.getEntry()->holdRefCountToStr().c_str(), HoldRefCountAction); |
419 | LR.TPR.TargetPointer = (void *)TP; |
420 | } else if (PM->getRequirements() & OMP_REQ_UNIFIED_SHARED_MEMORY || |
421 | PM->getRequirements() & OMPX_REQ_AUTO_ZERO_COPY) { |
422 | // If the value isn't found in the mapping and unified shared memory |
423 | // is on then it means we have stumbled upon a value which we need to |
424 | // use directly from the host. |
425 | DP("Get HstPtrBegin " DPxMOD " Size=%" PRId64 " for unified shared " |
426 | "memory\n" , |
427 | DPxPTR((uintptr_t)HstPtrBegin), Size); |
428 | LR.TPR.Flags.IsPresent = false; |
429 | LR.TPR.Flags.IsHostPointer = true; |
430 | LR.TPR.TargetPointer = HstPtrBegin; |
431 | } else { |
432 | // OpenMP Specification v5.2: if a matching list item is not found, the |
433 | // pointer retains its original value as per firstprivate semantics. |
434 | LR.TPR.Flags.IsPresent = false; |
435 | LR.TPR.Flags.IsHostPointer = false; |
436 | LR.TPR.TargetPointer = HstPtrBegin; |
437 | } |
438 | |
439 | return std::move(LR.TPR); |
440 | } |
441 | |
442 | // Return the target pointer begin (where the data will be moved). |
443 | void *MappingInfoTy::getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, |
444 | void *HstPtrBegin, int64_t Size) { |
445 | uintptr_t HP = (uintptr_t)HstPtrBegin; |
446 | LookupResult LR = lookupMapping(HDTTMap, HstPtrBegin, Size); |
447 | if (LR.Flags.IsContained || LR.Flags.ExtendsBefore || LR.Flags.ExtendsAfter) { |
448 | uintptr_t TP = |
449 | LR.TPR.getEntry()->TgtPtrBegin + (HP - LR.TPR.getEntry()->HstPtrBegin); |
450 | return (void *)TP; |
451 | } |
452 | |
453 | return NULL; |
454 | } |
455 | |
456 | int MappingInfoTy::eraseMapEntry(HDTTMapAccessorTy &HDTTMap, |
457 | HostDataToTargetTy *Entry, int64_t Size) { |
458 | assert(Entry && "Trying to delete a null entry from the HDTT map." ); |
459 | assert(Entry->getTotalRefCount() == 0 && |
460 | Entry->getDataEndThreadCount() == 0 && |
461 | "Trying to delete entry that is in use or owned by another thread." ); |
462 | |
463 | INFO(OMP_INFOTYPE_MAPPING_CHANGED, Device.DeviceID, |
464 | "Removing map entry with HstPtrBegin=" DPxMOD ", TgtPtrBegin=" DPxMOD |
465 | ", Size=%" PRId64 ", Name=%s\n" , |
466 | DPxPTR(Entry->HstPtrBegin), DPxPTR(Entry->TgtPtrBegin), Size, |
467 | (Entry->HstPtrName) ? getNameFromMapping(Entry->HstPtrName).c_str() |
468 | : "unknown" ); |
469 | |
470 | if (HDTTMap->erase(Entry) == 0) { |
471 | REPORT("Trying to remove a non-existent map entry\n" ); |
472 | return OFFLOAD_FAIL; |
473 | } |
474 | |
475 | return OFFLOAD_SUCCESS; |
476 | } |
477 | |
478 | int MappingInfoTy::deallocTgtPtrAndEntry(HostDataToTargetTy *Entry, |
479 | int64_t Size) { |
480 | assert(Entry && "Trying to deallocate a null entry." ); |
481 | |
482 | DP("Deleting tgt data " DPxMOD " of size %" PRId64 " by freeing allocation " |
483 | "starting at " DPxMOD "\n" , |
484 | DPxPTR(Entry->TgtPtrBegin), Size, DPxPTR(Entry->TgtAllocBegin)); |
485 | |
486 | void *Event = Entry->getEvent(); |
487 | if (Event && Device.destroyEvent(Event) != OFFLOAD_SUCCESS) { |
488 | REPORT("Failed to destroy event " DPxMOD "\n" , DPxPTR(Event)); |
489 | return OFFLOAD_FAIL; |
490 | } |
491 | |
492 | int Ret = Device.deleteData((void *)Entry->TgtAllocBegin); |
493 | |
494 | // Notify the plugin about the unmapped memory. |
495 | Ret |= Device.notifyDataUnmapped((void *)Entry->HstPtrBegin); |
496 | |
497 | delete Entry; |
498 | |
499 | return Ret; |
500 | } |
501 | |
502 | static void printCopyInfoImpl(int DeviceId, bool H2D, void *SrcPtrBegin, |
503 | void *DstPtrBegin, int64_t Size, |
504 | HostDataToTargetTy *HT) { |
505 | |
506 | INFO(OMP_INFOTYPE_DATA_TRANSFER, DeviceId, |
507 | "Copying data from %s to %s, %sPtr=" DPxMOD ", %sPtr=" DPxMOD |
508 | ", Size=%" PRId64 ", Name=%s\n" , |
509 | H2D ? "host" : "device" , H2D ? "device" : "host" , H2D ? "Hst" : "Tgt" , |
510 | DPxPTR(H2D ? SrcPtrBegin : DstPtrBegin), H2D ? "Tgt" : "Hst" , |
511 | DPxPTR(H2D ? DstPtrBegin : SrcPtrBegin), Size, |
512 | (HT && HT->HstPtrName) ? getNameFromMapping(HT->HstPtrName).c_str() |
513 | : "unknown" ); |
514 | } |
515 | |
516 | void MappingInfoTy::printCopyInfo( |
517 | void *TgtPtrBegin, void *HstPtrBegin, int64_t Size, bool H2D, |
518 | HostDataToTargetTy *Entry, MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr) { |
519 | auto HDTTMap = |
520 | HostDataToTargetMap.getExclusiveAccessor(!!Entry || !!HDTTMapPtr); |
521 | LookupResult LR; |
522 | if (!Entry) { |
523 | LR = lookupMapping(HDTTMapPtr ? *HDTTMapPtr : HDTTMap, HstPtrBegin, Size); |
524 | Entry = LR.TPR.getEntry(); |
525 | } |
526 | printCopyInfoImpl(Device.DeviceID, H2D, HstPtrBegin, TgtPtrBegin, Size, |
527 | Entry); |
528 | } |
529 | |