brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.9 KiB · 45bd9c6 Raw
628 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Declarations for managing host-to-device pointer mappings.10//11//===----------------------------------------------------------------------===//12 13#ifndef OMPTARGET_OPENMP_MAPPING_H14#define OMPTARGET_OPENMP_MAPPING_H15 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 26struct DeviceTy;27class AsyncInfoTy;28 29using map_var_info_t = void *;30 31class MappingConfig {32 33  MappingConfig() {34    BoolEnvar ForceAtomic = BoolEnvar("LIBOMPTARGET_MAP_FORCE_ATOMIC", true);35    UseEventsForAtomicTransfers = ForceAtomic;36  }37 38public: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 of45  /// map clauses or not. Can be modified with an environment variable.46  bool UseEventsForAtomicTransfers = true;47};48 49/// Information about shadow pointers.50struct ShadowPtrInfoTy {51  void **HstPtrAddr = nullptr;52  void **TgtPtrAddr = nullptr;53  int64_t PtrSize = sizeof(void *); // Size of the pointer/descriptor54 55  // Store the complete contents for both host and target pointers/descriptors.56  // 96 bytes is chosen as the "Small" size to cover simple Fortran57  // descriptors of up to 3 dimensions.58  llvm::SmallVector<char, 96> HstPtrContent;59  llvm::SmallVector<char, 96> TgtPtrContent;60 61  ShadowPtrInfoTy(void **HstPtrAddr, void **TgtPtrAddr, void *TgtPteeBase,62                  int64_t PtrSize)63      : HstPtrAddr(HstPtrAddr), TgtPtrAddr(TgtPtrAddr), PtrSize(PtrSize),64        HstPtrContent(PtrSize), TgtPtrContent(PtrSize) {65    constexpr int64_t VoidPtrSize = sizeof(void *);66    assert(HstPtrAddr != nullptr && "HstPtrAddr is nullptr");67    assert(TgtPtrAddr != nullptr && "TgtPtrAddr is nullptr");68    assert(PtrSize >= VoidPtrSize && "PtrSize is less than sizeof(void *)");69 70    void *HstPteeBase = *HstPtrAddr;71    // The first VoidPtrSize bytes for HstPtrContent/TgtPtrContent are from72    // HstPteeBase/TgtPteeBase.73    std::memcpy(HstPtrContent.data(), &HstPteeBase, VoidPtrSize);74    std::memcpy(TgtPtrContent.data(), &TgtPteeBase, VoidPtrSize);75 76    // If we are not dealing with Fortran descriptors (pointers larger than77    // VoidPtrSize), then that's that.78    if (PtrSize <= VoidPtrSize)79      return;80 81    // For larger pointers, i.e. Fortran descriptors, the remaining contents of82    // the descriptor come from the host descriptor, i.e. HstPtrAddr.83    std::memcpy(HstPtrContent.data() + VoidPtrSize,84                reinterpret_cast<char *>(HstPtrAddr) + VoidPtrSize,85                PtrSize - VoidPtrSize);86    std::memcpy(TgtPtrContent.data() + VoidPtrSize,87                reinterpret_cast<char *>(HstPtrAddr) + VoidPtrSize,88                PtrSize - VoidPtrSize);89  }90 91  ShadowPtrInfoTy() = delete;92 93  bool operator==(const ShadowPtrInfoTy &Other) const {94    return HstPtrAddr == Other.HstPtrAddr;95  }96};97 98inline bool operator<(const ShadowPtrInfoTy &lhs, const ShadowPtrInfoTy &rhs) {99  return lhs.HstPtrAddr < rhs.HstPtrAddr;100}101 102/// Map between host data and target data.103struct HostDataToTargetTy {104  const uintptr_t HstPtrBase; // host info.105  const uintptr_t HstPtrBegin;106  const uintptr_t HstPtrEnd;       // non-inclusive.107  const map_var_info_t HstPtrName; // Optional source name of mapped variable.108 109  const uintptr_t TgtAllocBegin; // allocated target memory110  const uintptr_t TgtPtrBegin; // mapped target memory = TgtAllocBegin + padding111 112private:113  static const uint64_t INFRefCount = ~(uint64_t)0;114  static std::string refCountToStr(uint64_t RefCount) {115    return RefCount == INFRefCount ? "INF" : std::to_string(RefCount);116  }117 118  struct StatesTy {119    StatesTy(uint64_t DRC, uint64_t HRC)120        : DynRefCount(DRC), HoldRefCount(HRC) {}121    /// The dynamic reference count is the standard reference count as of OpenMP122    /// 4.5.  The hold reference count is an OpenMP extension for the sake of123    /// OpenACC support.124    ///125    /// The 'ompx_hold' map type modifier is permitted only on "omp target" and126    /// "omp target data", and "delete" is permitted only on "omp target exit127    /// data" and associated runtime library routines.  As a result, we really128    /// need to implement "reset" functionality only for the dynamic reference129    /// counter.  Likewise, only the dynamic reference count can be infinite130    /// because, for example, omp_target_associate_ptr and "omp declare target131    /// link" operate only on it.  Nevertheless, it's actually easier to follow132    /// the code (and requires less assertions for special cases) when we just133    /// implement these features generally across both reference counters here.134    /// Thus, it's the users of this class that impose those restrictions.135    ///136    uint64_t DynRefCount;137    uint64_t HoldRefCount;138 139    /// A map of shadow pointers associated with this entry, the keys are host140    /// pointer addresses to identify stale entries.141    llvm::SmallSet<ShadowPtrInfoTy, 2> ShadowPtrInfos;142 143    /// Pointer to the event corresponding to the data update of this map.144    /// Note: At present this event is created when the first data transfer from145    /// host to device is issued, and only being used for H2D. It is not used146    /// for data transfer in another direction (device to host). It is still147    /// unclear whether we need it for D2H. If in the future we need similar148    /// mechanism for D2H, and if the event cannot be shared between them, Event149    /// should be written as <tt>void *Event[2]</tt>.150    void *Event = nullptr;151 152    /// Number of threads currently holding a reference to the entry at a153    /// targetDataEnd. This is used to ensure that only the last thread that154    /// references this entry will actually delete it.155    int32_t DataEndThreadCount = 0;156  };157  // When HostDataToTargetTy is used by std::set, std::set::iterator is const158  // use unique_ptr to make States mutable.159  const std::unique_ptr<StatesTy> States;160 161public:162  HostDataToTargetTy(uintptr_t BP, uintptr_t B, uintptr_t E,163                     uintptr_t TgtAllocBegin, uintptr_t TgtPtrBegin,164                     bool UseHoldRefCount, map_var_info_t Name = nullptr,165                     bool IsINF = false)166      : HstPtrBase(BP), HstPtrBegin(B), HstPtrEnd(E), HstPtrName(Name),167        TgtAllocBegin(TgtAllocBegin), TgtPtrBegin(TgtPtrBegin),168        States(std::make_unique<StatesTy>(UseHoldRefCount ? 0169                                          : IsINF         ? INFRefCount170                                                          : 1,171                                          !UseHoldRefCount ? 0172                                          : IsINF          ? INFRefCount173                                                           : 1)) {}174 175  /// Get the total reference count.  This is smarter than just getDynRefCount()176  /// + getHoldRefCount() because it handles the case where at least one is177  /// infinity and the other is non-zero.178  uint64_t getTotalRefCount() const {179    if (States->DynRefCount == INFRefCount ||180        States->HoldRefCount == INFRefCount)181      return INFRefCount;182    return States->DynRefCount + States->HoldRefCount;183  }184 185  /// Get the dynamic reference count.186  uint64_t getDynRefCount() const { return States->DynRefCount; }187 188  /// Get the hold reference count.189  uint64_t getHoldRefCount() const { return States->HoldRefCount; }190 191  /// Get the event bound to this data map.192  void *getEvent() const { return States->Event; }193 194  /// Add a new event, if necessary.195  /// Returns OFFLOAD_FAIL if something went wrong, OFFLOAD_SUCCESS otherwise.196  int addEventIfNecessary(DeviceTy &Device, AsyncInfoTy &AsyncInfo) const;197 198  /// Functions that manages the number of threads referencing the entry in a199  /// targetDataEnd.200  void incDataEndThreadCount() { ++States->DataEndThreadCount; }201 202  [[nodiscard]] int32_t decDataEndThreadCount() {203    return --States->DataEndThreadCount;204  }205 206  [[nodiscard]] int32_t getDataEndThreadCount() const {207    return States->DataEndThreadCount;208  }209 210  /// Set the event bound to this data map.211  void setEvent(void *Event) const { States->Event = Event; }212 213  /// Reset the specified reference count unless it's infinity.  Reset to 1214  /// (even if currently 0) so it can be followed by a decrement.215  void resetRefCount(bool UseHoldRefCount) const {216    uint64_t &ThisRefCount =217        UseHoldRefCount ? States->HoldRefCount : States->DynRefCount;218    if (ThisRefCount != INFRefCount)219      ThisRefCount = 1;220  }221 222  /// Increment the specified reference count unless it's infinity.223  void incRefCount(bool UseHoldRefCount) const {224    uint64_t &ThisRefCount =225        UseHoldRefCount ? States->HoldRefCount : States->DynRefCount;226    if (ThisRefCount != INFRefCount) {227      ++ThisRefCount;228      assert(ThisRefCount < INFRefCount && "refcount overflow");229    }230  }231 232  /// Decrement the specified reference count unless it's infinity or zero, and233  /// return the total reference count.234  uint64_t decRefCount(bool UseHoldRefCount) const {235    uint64_t &ThisRefCount =236        UseHoldRefCount ? States->HoldRefCount : States->DynRefCount;237    uint64_t OtherRefCount =238        UseHoldRefCount ? States->DynRefCount : States->HoldRefCount;239    (void)OtherRefCount;240    if (ThisRefCount != INFRefCount) {241      if (ThisRefCount > 0)242        --ThisRefCount;243      else244        assert(OtherRefCount >= 0 && "total refcount underflow");245    }246    return getTotalRefCount();247  }248 249  /// Is the dynamic (and thus the total) reference count infinite?250  bool isDynRefCountInf() const { return States->DynRefCount == INFRefCount; }251 252  /// Convert the dynamic reference count to a debug string.253  std::string dynRefCountToStr() const {254    return refCountToStr(States->DynRefCount);255  }256 257  /// Convert the hold reference count to a debug string.258  std::string holdRefCountToStr() const {259    return refCountToStr(States->HoldRefCount);260  }261 262  /// Should one decrement of the specified reference count (after resetting it263  /// if \c AfterReset) remove this mapping?264  bool decShouldRemove(bool UseHoldRefCount, bool AfterReset = false) const {265    uint64_t ThisRefCount =266        UseHoldRefCount ? States->HoldRefCount : States->DynRefCount;267    uint64_t OtherRefCount =268        UseHoldRefCount ? States->DynRefCount : States->HoldRefCount;269    if (OtherRefCount > 0)270      return false;271    if (AfterReset)272      return ThisRefCount != INFRefCount;273    return ThisRefCount == 1;274  }275 276  /// Add the shadow pointer info \p ShadowPtrInfo to this entry but only if the277  /// the target ptr value was not already present in the existing set of shadow278  /// pointers. Return true if something was added.279  bool addShadowPointer(const ShadowPtrInfoTy &ShadowPtrInfo) const {280    auto Pair = States->ShadowPtrInfos.insert(ShadowPtrInfo);281    if (Pair.second)282      return true;283 284    // Check for a stale entry, if found, replace the old one.285 286    // For Fortran descriptors, we need to compare their full contents,287    // as the starting address may be the same while other fields have288    // been updated. e.g.289    //290    //   !$omp target enter data map(x(1:100)) !             (1)291    //   p => x(10: 19)292    //   !$omp target enter data map(p, p(:)) !              (2)293    //   p => x(5: 9)294    //   !$omp target enter data map(attach(always): p(:)) ! (3)295    //296    // While &desc_p and &p(1) (TgtPtrAddr and first "sizeof(void*)" bytes of297    // TgtPtrContent) are same for (2) and (3), the pointer attachment for (3)298    // needs to update the bounds information in the descriptor of p on device.299    if ((*Pair.first).TgtPtrContent == ShadowPtrInfo.TgtPtrContent)300      return false;301 302    States->ShadowPtrInfos.erase(ShadowPtrInfo);303    return addShadowPointer(ShadowPtrInfo);304  }305 306  /// Apply \p CB to all shadow pointers of this entry. Returns OFFLOAD_FAIL if307  /// \p CB returned OFFLOAD_FAIL for any of them, otherwise this returns308  /// OFFLOAD_SUCCESS. The entry is locked for this operation.309  template <typename CBTy> int foreachShadowPointerInfo(CBTy CB) const {310    for (auto &It : States->ShadowPtrInfos)311      if (CB(const_cast<ShadowPtrInfoTy &>(It)) == OFFLOAD_FAIL)312        return OFFLOAD_FAIL;313    return OFFLOAD_SUCCESS;314  }315 316  /// Lock this entry for exclusive access. Ensure to get exclusive access to317  /// HDTTMap first!318  void lock() const { Mtx.lock(); }319 320  /// Unlock this entry to allow other threads inspecting it.321  void unlock() const { Mtx.unlock(); }322 323private:324  // Mutex that needs to be held before the entry is inspected or modified. The325  // HDTTMap mutex needs to be held before trying to lock any HDTT Entry.326  mutable std::mutex Mtx;327};328 329/// Wrapper around the HostDataToTargetTy to be used in the HDTT map. In330/// addition to the HDTT pointer we store the key value explicitly. This331/// allows the set to inspect (sort/search/...) this entry without an additional332/// load of HDTT. HDTT is a pointer to allow the modification of the set without333/// invalidating HDTT entries which can now be inspected at the same time.334struct HostDataToTargetMapKeyTy {335  uintptr_t KeyValue;336 337  HostDataToTargetMapKeyTy(void *Key) : KeyValue(uintptr_t(Key)) {}338  HostDataToTargetMapKeyTy(uintptr_t Key) : KeyValue(Key) {}339  HostDataToTargetMapKeyTy(HostDataToTargetTy *HDTT)340      : KeyValue(HDTT->HstPtrBegin), HDTT(HDTT) {}341  HostDataToTargetTy *HDTT;342};343inline bool operator<(const HostDataToTargetMapKeyTy &LHS,344                      const uintptr_t &RHS) {345  return LHS.KeyValue < RHS;346}347inline bool operator<(const uintptr_t &LHS,348                      const HostDataToTargetMapKeyTy &RHS) {349  return LHS < RHS.KeyValue;350}351inline bool operator<(const HostDataToTargetMapKeyTy &LHS,352                      const HostDataToTargetMapKeyTy &RHS) {353  return LHS.KeyValue < RHS.KeyValue;354}355 356/// This struct will be returned by \p DeviceTy::getTargetPointer which provides357/// more data than just a target pointer. A TargetPointerResultTy that has a non358/// null Entry owns the entry. As long as the TargetPointerResultTy (TPR) exists359/// the entry is locked. To give up ownership without destroying the TPR use the360/// reset() function.361struct TargetPointerResultTy {362  struct FlagTy {363    /// If the map table entry is just created364    unsigned IsNewEntry : 1;365    /// If the pointer is actually a host pointer (when unified memory enabled)366    unsigned IsHostPointer : 1;367    /// If the pointer is present in the mapping table.368    unsigned IsPresent : 1;369    /// Flag indicating that this was the last user of the entry and the ref370    /// count is now 0.371    unsigned IsLast : 1;372    /// If the pointer is contained.373    unsigned IsContained : 1;374  } Flags = {0, 0, 0, 0, 0};375 376  TargetPointerResultTy(const TargetPointerResultTy &) = delete;377  TargetPointerResultTy &operator=(const TargetPointerResultTy &TPR) = delete;378  TargetPointerResultTy() {}379 380  TargetPointerResultTy(FlagTy Flags, HostDataToTargetTy *Entry,381                        void *TargetPointer)382      : Flags(Flags), TargetPointer(TargetPointer), Entry(Entry) {383    if (Entry)384      Entry->lock();385  }386 387  TargetPointerResultTy(TargetPointerResultTy &&TPR)388      : Flags(TPR.Flags), TargetPointer(TPR.TargetPointer), Entry(TPR.Entry) {389    TPR.Entry = nullptr;390  }391 392  TargetPointerResultTy &operator=(TargetPointerResultTy &&TPR) {393    if (&TPR != this) {394      std::swap(Flags, TPR.Flags);395      std::swap(Entry, TPR.Entry);396      std::swap(TargetPointer, TPR.TargetPointer);397    }398    return *this;399  }400 401  ~TargetPointerResultTy() {402    if (Entry)403      Entry->unlock();404  }405 406  bool isPresent() const { return Flags.IsPresent; }407 408  bool isHostPointer() const { return Flags.IsHostPointer; }409 410  bool isContained() const { return Flags.IsContained; }411 412  /// The corresponding target pointer413  void *TargetPointer = nullptr;414 415  HostDataToTargetTy *getEntry() const { return Entry; }416  void setEntry(HostDataToTargetTy *HDTTT,417                HostDataToTargetTy *OwnedTPR = nullptr) {418    if (Entry)419      Entry->unlock();420    Entry = HDTTT;421    if (Entry && Entry != OwnedTPR)422      Entry->lock();423  }424 425  void reset() { *this = TargetPointerResultTy(); }426 427private:428  /// The corresponding map table entry which is stable.429  HostDataToTargetTy *Entry = nullptr;430};431 432struct LookupResult {433  struct {434    unsigned IsContained : 1;435    unsigned ExtendsBefore : 1;436    unsigned ExtendsAfter : 1;437  } Flags;438 439  LookupResult() : Flags({0, 0, 0}), TPR() {}440 441  TargetPointerResultTy TPR;442};443 444// This structure stores information of a mapped memory region.445struct MapComponentInfoTy {446  void *Base;447  void *Begin;448  int64_t Size;449  int64_t Type;450  void *Name;451  MapComponentInfoTy() = default;452  MapComponentInfoTy(void *Base, void *Begin, int64_t Size, int64_t Type,453                     void *Name)454      : Base(Base), Begin(Begin), Size(Size), Type(Type), Name(Name) {}455};456 457// This structure stores all components of a user-defined mapper. The number of458// components are dynamically decided, so we utilize C++ STL vector459// implementation here.460struct MapperComponentsTy {461  llvm::SmallVector<MapComponentInfoTy> Components;462  int32_t size() { return Components.size(); }463};464 465// The mapper function pointer type. It follows the signature below:466// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,467//                                           void *base, void *begin,468//                                           size_t size, int64_t type,469//                                           void * name);470typedef void (*MapperFuncPtrTy)(void *, void *, void *, int64_t, int64_t,471                                void *);472 473/// Structure to store information about a single ATTACH map entry.474struct AttachMapInfo {475  void *PointerBase;476  void *PointeeBegin;477  int64_t PointerSize;478  int64_t MapType;479  map_var_info_t Pointername;480 481  AttachMapInfo(void *PointerBase, void *PointeeBegin, int64_t Size,482                int64_t Type, map_var_info_t Name)483      : PointerBase(PointerBase), PointeeBegin(PointeeBegin), PointerSize(Size),484        MapType(Type), Pointername(Name) {}485};486 487/// Structure to track ATTACH entries and new allocations across recursive calls488/// (for handling mappers) to targetDataBegin for a given construct.489struct AttachInfoTy {490  /// ATTACH map entries for deferred processing.491  llvm::SmallVector<AttachMapInfo> AttachEntries;492 493  /// Key: host pointer, Value: allocation size.494  llvm::DenseMap<void *, int64_t> NewAllocations;495 496  AttachInfoTy() = default;497 498  // Delete copy constructor and copy assignment operator to prevent copying499  AttachInfoTy(const AttachInfoTy &) = delete;500  AttachInfoTy &operator=(const AttachInfoTy &) = delete;501};502 503// Function pointer type for targetData* functions (targetDataBegin,504// targetDataEnd and targetDataUpdate).505typedef int (*TargetDataFuncPtrTy)(ident_t *, DeviceTy &, int32_t, void **,506                                   void **, int64_t *, int64_t *,507                                   map_var_info_t *, void **, AsyncInfoTy &,508                                   AttachInfoTy *, bool);509 510void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device,511                               bool toStdOut = false);512 513int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,514                    void **ArgsBase, void **Args, int64_t *ArgSizes,515                    int64_t *ArgTypes, map_var_info_t *ArgNames,516                    void **ArgMappers, AsyncInfoTy &AsyncInfo,517                    AttachInfoTy *AttachInfo = nullptr,518                    bool FromMapper = false);519 520int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,521                  void **ArgBases, void **Args, int64_t *ArgSizes,522                  int64_t *ArgTypes, map_var_info_t *ArgNames,523                  void **ArgMappers, AsyncInfoTy &AsyncInfo,524                  AttachInfoTy *AttachInfo = nullptr, bool FromMapper = false);525 526int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,527                     void **ArgsBase, void **Args, int64_t *ArgSizes,528                     int64_t *ArgTypes, map_var_info_t *ArgNames,529                     void **ArgMappers, AsyncInfoTy &AsyncInfo,530                     AttachInfoTy *AttachInfo = nullptr,531                     bool FromMapper = false);532 533// Process deferred ATTACH map entries collected during targetDataBegin.534int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,535                         AsyncInfoTy &AsyncInfo);536 537struct MappingInfoTy {538  MappingInfoTy(DeviceTy &Device) : Device(Device) {}539 540  /// Host data to device map type with a wrapper key indirection that allows541  /// concurrent modification of the entries without invalidating the underlying542  /// entries.543  using HostDataToTargetListTy =544      std::set<HostDataToTargetMapKeyTy, std::less<>>;545 546  /// The HDTTMap is a protected object that can only be accessed by one thread547  /// at a time.548  ProtectedObj<HostDataToTargetListTy> HostDataToTargetMap;549 550  /// The type used to access the HDTT map.551  using HDTTMapAccessorTy = decltype(HostDataToTargetMap)::AccessorTy;552 553  /// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures554  /// exclusive access to the HDTT map.555  LookupResult lookupMapping(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,556                             int64_t Size,557                             HostDataToTargetTy *OwnedTPR = nullptr);558 559  /// Get the target pointer based on host pointer begin and base. If the560  /// mapping already exists, the target pointer will be returned directly. In561  /// addition, if required, the memory region pointed by \p HstPtrBegin of size562  /// \p Size will also be transferred to the device. If the mapping doesn't563  /// exist, and if unified shared memory is not enabled, a new mapping will be564  /// created and the data will also be transferred accordingly. nullptr will be565  /// returned because of any of following reasons:566  /// - Data allocation failed;567  /// - The user tried to do an illegal mapping;568  /// - Data transfer issue fails.569  TargetPointerResultTy getTargetPointer(570      HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin, void *HstPtrBase,571      int64_t TgtPadding, int64_t Size, map_var_info_t HstPtrName,572      bool HasFlagTo, bool HasFlagAlways, bool IsImplicit, bool UpdateRefCount,573      bool HasCloseModifier, bool HasPresentModifier, bool HasHoldModifier,574      AsyncInfoTy &AsyncInfo, HostDataToTargetTy *OwnedTPR = nullptr,575      bool ReleaseHDTTMap = true);576 577  /// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor578  /// ensures exclusive access to the HDTT map.579  void *getTgtPtrBegin(HDTTMapAccessorTy &HDTTMap, void *HstPtrBegin,580                       int64_t Size);581 582  /// Return the target pointer begin (where the data will be moved).583  /// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target.584  /// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry585  /// reference counters will be decremented.586  /// - \p MustContain enforces that the query must not extend beyond an already587  /// mapped entry to be valid.588  /// - \p ForceDelete deletes the entry regardless of its reference counting589  /// (unless it is infinite).590  /// - \p FromDataEnd tracks the number of threads referencing the entry at591  /// targetDataEnd for delayed deletion purpose.592  [[nodiscard]] TargetPointerResultTy593  getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool UpdateRefCount,594                 bool UseHoldRefCount, bool MustContain = false,595                 bool ForceDelete = false, bool FromDataEnd = false);596 597  /// Remove the \p Entry from the data map. Expect the entry's total reference598  /// count to be zero and the caller thread to be the last one using it. \p599  /// HDTTMap ensure the caller holds exclusive access and can modify the map.600  /// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c601  /// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling602  /// this function if the map entry is not expected to exist because \p603  /// HstPtrBegin uses shared memory.604  [[nodiscard]] int eraseMapEntry(HDTTMapAccessorTy &HDTTMap,605                                  HostDataToTargetTy *Entry, int64_t Size);606 607  /// Deallocate the \p Entry from the device memory and delete it. Return \c608  /// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and609  /// return \c OFFLOAD_FAIL otherwise.610  [[nodiscard]] int deallocTgtPtrAndEntry(HostDataToTargetTy *Entry,611                                          int64_t Size);612 613  int associatePtr(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size);614  int disassociatePtr(void *HstPtrBegin);615 616  /// Print information about the transfer from \p HstPtr to \p TgtPtr (or vice617  /// versa if \p H2D is false). If there is an existing mapping, or if \p Entry618  /// is set, the associated metadata will be printed as well.619  void printCopyInfo(void *TgtPtr, void *HstPtr, int64_t Size, bool H2D,620                     HostDataToTargetTy *Entry,621                     MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr);622 623private:624  DeviceTy &Device;625};626 627#endif // OMPTARGET_OPENMP_MAPPING_H628