1 //===-- OpenMP/Mapping.h - OpenMP/OpenACC pointer mapping -------*- C++ -*-===// 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 // Declarations for managing host-to-device pointer mappings. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef OMPTARGET_OPENMP_MAPPING_H 14 #define OMPTARGET_OPENMP_MAPPING_H 15 16 #include "ExclusiveAccess.h" 17 #include "Shared/EnvironmentVar.h" 18 #include "omptarget.h" 19 20 #include <cstdint> 21 #include <mutex> 22 #include <string> 23 24 #include "llvm/ADT/SmallSet.h" 25 26 struct DeviceTy; 27 class AsyncInfoTy; 28 29 using map_var_info_t = void *; 30 31 class MappingConfig { 32 MappingConfig()33 MappingConfig() { 34 BoolEnvar ForceAtomic = BoolEnvar("LIBOMPTARGET_MAP_FORCE_ATOMIC", true); 35 UseEventsForAtomicTransfers = ForceAtomic; 36 } 37 38 public: get()39 static const MappingConfig &get() { 40 static MappingConfig MP; 41 return MP; 42 }; 43 44 /// Flag to indicate if we use events to ensure the atomicity of 45 /// map clauses or not. Can be modified with an environment variable. 46 bool UseEventsForAtomicTransfers = true; 47 }; 48 49 /// Information about shadow pointers. 50 struct ShadowPtrInfoTy { 51 void **HstPtrAddr = nullptr; 52 void *HstPtrVal = nullptr; 53 void **TgtPtrAddr = nullptr; 54 void *TgtPtrVal = nullptr; 55 56 bool operator==(const ShadowPtrInfoTy &Other) const { 57 return HstPtrAddr == Other.HstPtrAddr; 58 } 59 }; 60 61 inline bool operator<(const ShadowPtrInfoTy &lhs, const ShadowPtrInfoTy &rhs) { 62 return lhs.HstPtrAddr < rhs.HstPtrAddr; 63 } 64 65 /// Map between host data and target data. 66 struct HostDataToTargetTy { 67 const uintptr_t HstPtrBase; // host info. 68 const uintptr_t HstPtrBegin; 69 const uintptr_t HstPtrEnd; // non-inclusive. 70 const map_var_info_t HstPtrName; // Optional source name of mapped variable. 71 72 const uintptr_t TgtAllocBegin; // allocated target memory 73 const uintptr_t TgtPtrBegin; // mapped target memory = TgtAllocBegin + padding 74 75 private: 76 static const uint64_t INFRefCount = ~(uint64_t)0; refCountToStrHostDataToTargetTy77 static std::string refCountToStr(uint64_t RefCount) { 78 return RefCount == INFRefCount ? "INF" : std::to_string(RefCount); 79 } 80 81 struct StatesTy { StatesTyHostDataToTargetTy::StatesTy82 StatesTy(uint64_t DRC, uint64_t HRC) 83 : DynRefCount(DRC), HoldRefCount(HRC) {} 84 /// The dynamic reference count is the standard reference count as of OpenMP 85 /// 4.5. The hold reference count is an OpenMP extension for the sake of 86 /// OpenACC support. 87 /// 88 /// The 'ompx_hold' map type modifier is permitted only on "omp target" and 89 /// "omp target data", and "delete" is permitted only on "omp target exit 90 /// data" and associated runtime library routines. As a result, we really 91 /// need to implement "reset" functionality only for the dynamic reference 92 /// counter. Likewise, only the dynamic reference count can be infinite 93 /// because, for example, omp_target_associate_ptr and "omp declare target 94 /// link" operate only on it. Nevertheless, it's actually easier to follow 95 /// the code (and requires less assertions for special cases) when we just 96 /// implement these features generally across both reference counters here. 97 /// Thus, it's the users of this class that impose those restrictions. 98 /// 99 uint64_t DynRefCount; 100 uint64_t HoldRefCount; 101 102 /// A map of shadow pointers associated with this entry, the keys are host 103 /// pointer addresses to identify stale entries. 104 llvm::SmallSet<ShadowPtrInfoTy, 2> ShadowPtrInfos; 105 106 /// Pointer to the event corresponding to the data update of this map. 107 /// Note: At present this event is created when the first data transfer from 108 /// host to device is issued, and only being used for H2D. It is not used 109 /// for data transfer in another direction (device to host). It is still 110 /// unclear whether we need it for D2H. If in the future we need similar 111 /// mechanism for D2H, and if the event cannot be shared between them, Event 112 /// should be written as <tt>void *Event[2]</tt>. 113 void *Event = nullptr; 114 115 /// Number of threads currently holding a reference to the entry at a 116 /// targetDataEnd. This is used to ensure that only the last thread that 117 /// references this entry will actually delete it. 118 int32_t DataEndThreadCount = 0; 119 }; 120 // When HostDataToTargetTy is used by std::set, std::set::iterator is const 121 // use unique_ptr to make States mutable. 122 const std::unique_ptr<StatesTy> States; 123 124 public: 125 HostDataToTargetTy(uintptr_t BP, uintptr_t B, uintptr_t E, 126 uintptr_t TgtAllocBegin, uintptr_t TgtPtrBegin, 127 bool UseHoldRefCount, map_var_info_t Name = nullptr, 128 bool IsINF = false) HstPtrBaseHostDataToTargetTy129 : HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E), HstPtrName(Name), 130 TgtAllocBegin(TgtAllocBegin), TgtPtrBegin(TgtPtrBegin), 131 States(std::make_unique<StatesTy>(UseHoldRefCount ? 0 132 : IsINF ? INFRefCount 133 : 1, 134 !UseHoldRefCount ? 0 135 : IsINF ? INFRefCount 136 : 1)) {} 137 138 /// Get the total reference count. This is smarter than just getDynRefCount() 139 /// + getHoldRefCount() because it handles the case where at least one is 140 /// infinity and the other is non-zero. getTotalRefCountHostDataToTargetTy141 uint64_t getTotalRefCount() const { 142 if (States->DynRefCount == INFRefCount || 143 States->HoldRefCount == INFRefCount) 144 return INFRefCount; 145 return States->DynRefCount + States->HoldRefCount; 146 } 147 148 /// Get the dynamic reference count. getDynRefCountHostDataToTargetTy149 uint64_t getDynRefCount() const { return States->DynRefCount; } 150 151 /// Get the hold reference count. getHoldRefCountHostDataToTargetTy152 uint64_t getHoldRefCount() const { return States->HoldRefCount; } 153 154 /// Get the event bound to this data map. getEventHostDataToTargetTy155 void *getEvent() const { return States->Event; } 156 157 /// Add a new event, if necessary. 158 /// Returns OFFLOAD_FAIL if something went wrong, OFFLOAD_SUCCESS otherwise. 159 int addEventIfNecessary(DeviceTy &Device, AsyncInfoTy &AsyncInfo) const; 160 161 /// Functions that manages the number of threads referencing the entry in a 162 /// targetDataEnd. incDataEndThreadCountHostDataToTargetTy163 void incDataEndThreadCount() { ++States->DataEndThreadCount; } 164 decDataEndThreadCountHostDataToTargetTy165 [[nodiscard]] int32_t decDataEndThreadCount() { 166 return --States->DataEndThreadCount; 167 } 168 getDataEndThreadCountHostDataToTargetTy169 [[nodiscard]] int32_t getDataEndThreadCount() const { 170 return States->DataEndThreadCount; 171 } 172 173 /// Set the event bound to this data map. setEventHostDataToTargetTy174 void setEvent(void *Event) const { States->Event = Event; } 175 176 /// Reset the specified reference count unless it's infinity. Reset to 1 177 /// (even if currently 0) so it can be followed by a decrement. resetRefCountHostDataToTargetTy178 void resetRefCount(bool UseHoldRefCount) const { 179 uint64_t &ThisRefCount = 180 UseHoldRefCount ? States->HoldRefCount : States->DynRefCount; 181 if (ThisRefCount != INFRefCount) 182 ThisRefCount = 1; 183 } 184 185 /// Increment the specified reference count unless it's infinity. incRefCountHostDataToTargetTy186 void incRefCount(bool UseHoldRefCount) const { 187 uint64_t &ThisRefCount = 188 UseHoldRefCount ? States->HoldRefCount : States->DynRefCount; 189 if (ThisRefCount != INFRefCount) { 190 ++ThisRefCount; 191 assert(ThisRefCount < INFRefCount && "refcount overflow"); 192 } 193 } 194 195 /// Decrement the specified reference count unless it's infinity or zero, and 196 /// return the total reference count. decRefCountHostDataToTargetTy197 uint64_t decRefCount(bool UseHoldRefCount) const { 198 uint64_t &ThisRefCount = 199 UseHoldRefCount ? States->HoldRefCount : States->DynRefCount; 200 uint64_t OtherRefCount = 201 UseHoldRefCount ? States->DynRefCount : States->HoldRefCount; 202 (void)OtherRefCount; 203 if (ThisRefCount != INFRefCount) { 204 if (ThisRefCount > 0) 205 --ThisRefCount; 206 else 207 assert(OtherRefCount >= 0 && "total refcount underflow"); 208 } 209 return getTotalRefCount(); 210 } 211 212 /// Is the dynamic (and thus the total) reference count infinite? isDynRefCountInfHostDataToTargetTy213 bool isDynRefCountInf() const { return States->DynRefCount == INFRefCount; } 214 215 /// Convert the dynamic reference count to a debug string. dynRefCountToStrHostDataToTargetTy216 std::string dynRefCountToStr() const { 217 return refCountToStr(States->DynRefCount); 218 } 219 220 /// Convert the hold reference count to a debug string. holdRefCountToStrHostDataToTargetTy221 std::string holdRefCountToStr() const { 222 return refCountToStr(States->HoldRefCount); 223 } 224 225 /// Should one decrement of the specified reference count (after resetting it 226 /// if \c AfterReset) remove this mapping? 227 bool decShouldRemove(bool UseHoldRefCount, bool AfterReset = false) const { 228 uint64_t ThisRefCount = 229 UseHoldRefCount ? States->HoldRefCount : States->DynRefCount; 230 uint64_t OtherRefCount = 231 UseHoldRefCount ? States->DynRefCount : States->HoldRefCount; 232 if (OtherRefCount > 0) 233 return false; 234 if (AfterReset) 235 return ThisRefCount != INFRefCount; 236 return ThisRefCount == 1; 237 } 238 239 /// Add the shadow pointer info \p ShadowPtrInfo to this entry but only if the 240 /// the target ptr value was not already present in the existing set of shadow 241 /// pointers. Return true if something was added. addShadowPointerHostDataToTargetTy242 bool addShadowPointer(const ShadowPtrInfoTy &ShadowPtrInfo) const { 243 auto Pair = States->ShadowPtrInfos.insert(ShadowPtrInfo); 244 if (Pair.second) 245 return true; 246 // Check for a stale entry, if found, replace the old one. 247 if ((*Pair.first).TgtPtrVal == ShadowPtrInfo.TgtPtrVal) 248 return false; 249 States->ShadowPtrInfos.erase(ShadowPtrInfo); 250 return addShadowPointer(ShadowPtrInfo); 251 } 252 253 /// Apply \p CB to all shadow pointers of this entry. Returns OFFLOAD_FAIL if 254 /// \p CB returned OFFLOAD_FAIL for any of them, otherwise this returns 255 /// OFFLOAD_SUCCESS. The entry is locked for this operation. foreachShadowPointerInfoHostDataToTargetTy256 template <typename CBTy> int foreachShadowPointerInfo(CBTy CB) const { 257 for (auto &It : States->ShadowPtrInfos) 258 if (CB(const_cast<ShadowPtrInfoTy &>(It)) == OFFLOAD_FAIL) 259 return OFFLOAD_FAIL; 260 return OFFLOAD_SUCCESS; 261 } 262 263 /// Lock this entry for exclusive access. Ensure to get exclusive access to 264 /// HDTTMap first! lockHostDataToTargetTy265 void lock() const { Mtx.lock(); } 266 267 /// Unlock this entry to allow other threads inspecting it. unlockHostDataToTargetTy268 void unlock() const { Mtx.unlock(); } 269 270 private: 271 // Mutex that needs to be held before the entry is inspected or modified. The 272 // HDTTMap mutex needs to be held before trying to lock any HDTT Entry. 273 mutable std::mutex Mtx; 274 }; 275 276 /// Wrapper around the HostDataToTargetTy to be used in the HDTT map. In 277 /// addition to the HDTT pointer we store the key value explicitly. This 278 /// allows the set to inspect (sort/search/...) this entry without an additional 279 /// load of HDTT. HDTT is a pointer to allow the modification of the set without 280 /// invalidating HDTT entries which can now be inspected at the same time. 281 struct HostDataToTargetMapKeyTy { 282 uintptr_t KeyValue; 283 HostDataToTargetMapKeyTyHostDataToTargetMapKeyTy284 HostDataToTargetMapKeyTy(void *Key) : KeyValue(uintptr_t(Key)) {} HostDataToTargetMapKeyTyHostDataToTargetMapKeyTy285 HostDataToTargetMapKeyTy(uintptr_t Key) : KeyValue(Key) {} HostDataToTargetMapKeyTyHostDataToTargetMapKeyTy286 HostDataToTargetMapKeyTy(HostDataToTargetTy *HDTT) 287 : KeyValue(HDTT->HstPtrBegin), HDTT(HDTT) {} 288 HostDataToTargetTy *HDTT; 289 }; 290 inline bool operator<(const HostDataToTargetMapKeyTy &LHS, 291 const uintptr_t &RHS) { 292 return LHS.KeyValue < RHS; 293 } 294 inline bool operator<(const uintptr_t &LHS, 295 const HostDataToTargetMapKeyTy &RHS) { 296 return LHS < RHS.KeyValue; 297 } 298 inline bool operator<(const HostDataToTargetMapKeyTy &LHS, 299 const HostDataToTargetMapKeyTy &RHS) { 300 return LHS.KeyValue < RHS.KeyValue; 301 } 302 303 /// This struct will be returned by \p DeviceTy::getTargetPointer which provides 304 /// more data than just a target pointer. A TargetPointerResultTy that has a non 305 /// null Entry owns the entry. As long as the TargetPointerResultTy (TPR) exists 306 /// the entry is locked. To give up ownership without destroying the TPR use the 307 /// reset() function. 308 struct TargetPointerResultTy { 309 struct FlagTy { 310 /// If the map table entry is just created 311 unsigned IsNewEntry : 1; 312 /// If the pointer is actually a host pointer (when unified memory enabled) 313 unsigned IsHostPointer : 1; 314 /// If the pointer is present in the mapping table. 315 unsigned IsPresent : 1; 316 /// Flag indicating that this was the last user of the entry and the ref 317 /// count is now 0. 318 unsigned IsLast : 1; 319 /// If the pointer is contained. 320 unsigned IsContained : 1; 321 } Flags = {0, 0, 0, 0, 0}; 322 323 TargetPointerResultTy(const TargetPointerResultTy &) = delete; 324 TargetPointerResultTy &operator=(const TargetPointerResultTy &TPR) = delete; TargetPointerResultTyTargetPointerResultTy325 TargetPointerResultTy() {} 326 TargetPointerResultTyTargetPointerResultTy327 TargetPointerResultTy(FlagTy Flags, HostDataToTargetTy *Entry, 328 void *TargetPointer) 329 : Flags(Flags), TargetPointer(TargetPointer), Entry(Entry) { 330 if (Entry) 331 Entry->lock(); 332 } 333 TargetPointerResultTyTargetPointerResultTy334 TargetPointerResultTy(TargetPointerResultTy &&TPR) 335 : Flags(TPR.Flags), TargetPointer(TPR.TargetPointer), Entry(TPR.Entry) { 336 TPR.Entry = nullptr; 337 } 338 339 TargetPointerResultTy &operator=(TargetPointerResultTy &&TPR) { 340 if (&TPR != this) { 341 std::swap(Flags, TPR.Flags); 342 std::swap(Entry, TPR.Entry); 343 std::swap(TargetPointer, TPR.TargetPointer); 344 } 345 return *this; 346 } 347 ~TargetPointerResultTyTargetPointerResultTy348 ~TargetPointerResultTy() { 349 if (Entry) 350 Entry->unlock(); 351 } 352 isPresentTargetPointerResultTy353 bool isPresent() const { return Flags.IsPresent; } 354 isHostPointerTargetPointerResultTy355 bool isHostPointer() const { return Flags.IsHostPointer; } 356 isContainedTargetPointerResultTy357 bool isContained() const { return Flags.IsContained; } 358 359 /// The corresponding target pointer 360 void *TargetPointer = nullptr; 361 getEntryTargetPointerResultTy362 HostDataToTargetTy *getEntry() const { return Entry; } 363 void setEntry(HostDataToTargetTy *HDTTT, 364 HostDataToTargetTy *OwnedTPR = nullptr) { 365 if (Entry) 366 Entry->unlock(); 367 Entry = HDTTT; 368 if (Entry && Entry != OwnedTPR) 369 Entry->lock(); 370 } 371 resetTargetPointerResultTy372 void reset() { *this = TargetPointerResultTy(); } 373 374 private: 375 /// The corresponding map table entry which is stable. 376 HostDataToTargetTy *Entry = nullptr; 377 }; 378 379 struct LookupResult { 380 struct { 381 unsigned IsContained : 1; 382 unsigned ExtendsBefore : 1; 383 unsigned ExtendsAfter : 1; 384 } Flags; 385 LookupResultLookupResult386 LookupResult() : Flags({0, 0, 0}), TPR() {} 387 388 TargetPointerResultTy TPR; 389 }; 390 391 // This structure stores information of a mapped memory region. 392 struct MapComponentInfoTy { 393 void *Base; 394 void *Begin; 395 int64_t Size; 396 int64_t Type; 397 void *Name; 398 MapComponentInfoTy() = default; MapComponentInfoTyMapComponentInfoTy399 MapComponentInfoTy(void *Base, void *Begin, int64_t Size, int64_t Type, 400 void *Name) 401 : Base(Base), Begin(Begin), Size(Size), Type(Type), Name(Name) {} 402 }; 403 404 // This structure stores all components of a user-defined mapper. The number of 405 // components are dynamically decided, so we utilize C++ STL vector 406 // implementation here. 407 struct MapperComponentsTy { 408 llvm::SmallVector<MapComponentInfoTy> Components; sizeMapperComponentsTy409 int32_t size() { return Components.size(); } 410 }; 411 412 // The mapper function pointer type. It follows the signature below: 413 // void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 414 // void *base, void *begin, 415 // size_t size, int64_t type, 416 // void * name); 417 typedef void (*MapperFuncPtrTy)(void *, void *, void *, int64_t, int64_t, 418 void *); 419 420 // Function pointer type for targetData* functions (targetDataBegin, 421 // targetDataEnd and targetDataUpdate). 422 typedef int (*TargetDataFuncPtrTy)(ident_t *, DeviceTy &, int32_t, void **, 423 void **, int64_t *, int64_t *, 424 map_var_info_t *, void **, AsyncInfoTy &, 425 bool); 426 427 void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device, 428 bool toStdOut = false); 429 430 int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum, 431 void **ArgsBase, void **Args, int64_t *ArgSizes, 432 int64_t *ArgTypes, map_var_info_t *ArgNames, 433 void **ArgMappers, AsyncInfoTy &AsyncInfo, 434 bool FromMapper = false); 435 436 int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum, 437 void **ArgBases, void **Args, int64_t *ArgSizes, 438 int64_t *ArgTypes, map_var_info_t *ArgNames, 439 void **ArgMappers, AsyncInfoTy &AsyncInfo, 440 bool FromMapper = false); 441 442 int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum, 443 void **ArgsBase, void **Args, int64_t *ArgSizes, 444 int64_t *ArgTypes, map_var_info_t *ArgNames, 445 void **ArgMappers, AsyncInfoTy &AsyncInfo, 446 bool FromMapper = false); 447 448 struct MappingInfoTy { MappingInfoTyMappingInfoTy449 MappingInfoTy(DeviceTy &Device) : Device(Device) {} 450 451 /// Host data to device map type with a wrapper key indirection that allows 452 /// concurrent modification of the entries without invalidating the underlying 453 /// entries. 454 using HostDataToTargetListTy = 455 std::set<HostDataToTargetMapKeyTy, std::less<>>; 456 457 /// The HDTTMap is a protected object that can only be accessed by one thread 458 /// at a time. 459 ProtectedObj<HostDataToTargetListTy> HostDataToTargetMap; 460 461 /// The type used to access the HDTT map. 462 using HDTTMapAccessorTy = decltype(HostDataToTargetMap)::AccessorTy; 463 464 /// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures 465 /// exclusive access to the HDTT map. 466 LookupResult lookupMapping(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, 467 int64_t Size, 468 HostDataToTargetTy *OwnedTPR = nullptr); 469 470 /// Get the target pointer based on host pointer begin and base. If the 471 /// mapping already exists, the target pointer will be returned directly. In 472 /// addition, if required, the memory region pointed by \p HstPtrBegin of size 473 /// \p Size will also be transferred to the device. If the mapping doesn't 474 /// exist, and if unified shared memory is not enabled, a new mapping will be 475 /// created and the data will also be transferred accordingly. nullptr will be 476 /// returned because of any of following reasons: 477 /// - Data allocation failed; 478 /// - The user tried to do an illegal mapping; 479 /// - Data transfer issue fails. 480 TargetPointerResultTy getTargetPointer( 481 HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase, 482 int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName, 483 bool HasFlagTo, bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount, 484 bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier, 485 AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR = nullptr, 486 bool ReleaseHDTTMap = true); 487 488 /// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor 489 /// ensures exclusive access to the HDTT map. 490 void *getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, 491 int64_t Size); 492 493 /// Return the target pointer begin (where the data will be moved). 494 /// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target. 495 /// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry 496 /// reference counters will be decremented. 497 /// - \p MustContain enforces that the query must not extend beyond an already 498 /// mapped entry to be valid. 499 /// - \p ForceDelete deletes the entry regardless of its reference counting 500 /// (unless it is infinite). 501 /// - \p FromDataEnd tracks the number of threads referencing the entry at 502 /// targetDataEnd for delayed deletion purpose. 503 [[nodiscard]] TargetPointerResultTy 504 getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool UpdateRefCount, 505 bool UseHoldRefCount, bool MustContain = false, 506 bool ForceDelete = false, bool FromDataEnd = false); 507 508 /// Remove the \p Entry from the data map. Expect the entry's total reference 509 /// count to be zero and the caller thread to be the last one using it. \p 510 /// HDTTMap ensure the caller holds exclusive access and can modify the map. 511 /// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c 512 /// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling 513 /// this function if the map entry is not expected to exist because \p 514 /// HstPtrBegin uses shared memory. 515 [[nodiscard]] int eraseMapEntry(HDTTMapAccessorTy &HDTTMap, 516 HostDataToTargetTy *Entry, int64_t Size); 517 518 /// Deallocate the \p Entry from the device memory and delete it. Return \c 519 /// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and 520 /// return \c OFFLOAD_FAIL otherwise. 521 [[nodiscard]] int deallocTgtPtrAndEntry(HostDataToTargetTy *Entry, 522 int64_t Size); 523 524 int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size); 525 int disassociatePtr(void *HstPtrBegin); 526 527 /// Print information about the transfer from \p HstPtr to \p TgtPtr (or vice 528 /// versa if \p H2D is false). If there is an existing mapping, or if \p Entry 529 /// is set, the associated metadata will be printed as well. 530 void printCopyInfo(void *TgtPtr, void *HstPtr, int64_t Size, bool H2D, 531 HostDataToTargetTy *Entry, 532 MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr); 533 534 private: 535 DeviceTy &Device; 536 }; 537 538 #endif // OMPTARGET_OPENMP_MAPPING_H 539