1 //===----------- device.h - Target independent OpenMP target RTL ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // Declarations for managing devices that are handled by RTL plugins.
11 //===----------------------------------------------------------------------===//
13 #ifndef _OMPTARGET_DEVICE_H
14 #define _OMPTARGET_DEVICE_H
27 #include "ExclusiveAccess.h"
28 #include "omptarget.h"
30 #include "llvm/ADT/SmallSet.h"
31 #include "llvm/ADT/SmallVector.h"
33 // Forward declarations.
35 struct __tgt_bin_desc
;
36 struct __tgt_target_table
;
38 using map_var_info_t
= void *;
40 // enum for OMP_TARGET_OFFLOAD; keep in sync with kmp.h definition
41 enum kmp_target_offload_kind
{
46 typedef enum kmp_target_offload_kind kmp_target_offload_kind_t
;
48 /// Information about shadow pointers.
49 struct ShadowPtrInfoTy
{
50 void **HstPtrAddr
= nullptr;
51 void *HstPtrVal
= nullptr;
52 void **TgtPtrAddr
= nullptr;
53 void *TgtPtrVal
= nullptr;
55 bool operator==(const ShadowPtrInfoTy
&Other
) const {
56 return HstPtrAddr
== Other
.HstPtrAddr
;
60 inline bool operator<(const ShadowPtrInfoTy
&lhs
, const ShadowPtrInfoTy
&rhs
) {
61 return lhs
.HstPtrAddr
< rhs
.HstPtrAddr
;
64 /// Map between host data and target data.
65 struct HostDataToTargetTy
{
66 const uintptr_t HstPtrBase
; // host info.
67 const uintptr_t HstPtrBegin
;
68 const uintptr_t HstPtrEnd
; // non-inclusive.
69 const map_var_info_t HstPtrName
; // Optional source name of mapped variable.
71 const uintptr_t TgtAllocBegin
; // allocated target memory
72 const uintptr_t TgtPtrBegin
; // mapped target memory = TgtAllocBegin + padding
75 static const uint64_t INFRefCount
= ~(uint64_t)0;
76 static std::string
refCountToStr(uint64_t RefCount
) {
77 return RefCount
== INFRefCount
? "INF" : std::to_string(RefCount
);
81 StatesTy(uint64_t DRC
, uint64_t HRC
)
82 : DynRefCount(DRC
), HoldRefCount(HRC
) {}
83 /// The dynamic reference count is the standard reference count as of OpenMP
84 /// 4.5. The hold reference count is an OpenMP extension for the sake of
87 /// The 'ompx_hold' map type modifier is permitted only on "omp target" and
88 /// "omp target data", and "delete" is permitted only on "omp target exit
89 /// data" and associated runtime library routines. As a result, we really
90 /// need to implement "reset" functionality only for the dynamic reference
91 /// counter. Likewise, only the dynamic reference count can be infinite
92 /// because, for example, omp_target_associate_ptr and "omp declare target
93 /// link" operate only on it. Nevertheless, it's actually easier to follow
94 /// the code (and requires less assertions for special cases) when we just
95 /// implement these features generally across both reference counters here.
96 /// Thus, it's the users of this class that impose those restrictions.
99 uint64_t HoldRefCount
;
101 /// A map of shadow pointers associated with this entry, the keys are host
102 /// pointer addresses to identify stale entries.
103 llvm::SmallSet
<ShadowPtrInfoTy
, 2> ShadowPtrInfos
;
105 /// Pointer to the event corresponding to the data update of this map.
106 /// Note: At present this event is created when the first data transfer from
107 /// host to device is issued, and only being used for H2D. It is not used
108 /// for data transfer in another direction (device to host). It is still
109 /// unclear whether we need it for D2H. If in the future we need similar
110 /// mechanism for D2H, and if the event cannot be shared between them, Event
111 /// should be written as <tt>void *Event[2]</tt>.
112 void *Event
= nullptr;
114 /// Number of threads currently holding a reference to the entry at a
115 /// targetDataEnd. This is used to ensure that only the last thread that
116 /// references this entry will actually delete it.
117 int32_t DataEndThreadCount
= 0;
119 // When HostDataToTargetTy is used by std::set, std::set::iterator is const
120 // use unique_ptr to make States mutable.
121 const std::unique_ptr
<StatesTy
> States
;
124 HostDataToTargetTy(uintptr_t BP
, uintptr_t B
, uintptr_t E
,
125 uintptr_t TgtAllocBegin
, uintptr_t TgtPtrBegin
,
126 bool UseHoldRefCount
, map_var_info_t Name
= nullptr,
128 : HstPtrBase(BP
), HstPtrBegin(B
), HstPtrEnd(E
), HstPtrName(Name
),
129 TgtAllocBegin(TgtAllocBegin
), TgtPtrBegin(TgtPtrBegin
),
130 States(std::make_unique
<StatesTy
>(UseHoldRefCount
? 0
131 : IsINF
? INFRefCount
134 : IsINF
? INFRefCount
137 /// Get the total reference count. This is smarter than just getDynRefCount()
138 /// + getHoldRefCount() because it handles the case where at least one is
139 /// infinity and the other is non-zero.
140 uint64_t getTotalRefCount() const {
141 if (States
->DynRefCount
== INFRefCount
||
142 States
->HoldRefCount
== INFRefCount
)
144 return States
->DynRefCount
+ States
->HoldRefCount
;
147 /// Get the dynamic reference count.
148 uint64_t getDynRefCount() const { return States
->DynRefCount
; }
150 /// Get the hold reference count.
151 uint64_t getHoldRefCount() const { return States
->HoldRefCount
; }
153 /// Get the event bound to this data map.
154 void *getEvent() const { return States
->Event
; }
156 /// Add a new event, if necessary.
157 /// Returns OFFLOAD_FAIL if something went wrong, OFFLOAD_SUCCESS otherwise.
158 int addEventIfNecessary(DeviceTy
&Device
, AsyncInfoTy
&AsyncInfo
) const;
160 /// Functions that manages the number of threads referencing the entry in a
162 void incDataEndThreadCount() { ++States
->DataEndThreadCount
; }
164 [[nodiscard
]] int32_t decDataEndThreadCount() {
165 return --States
->DataEndThreadCount
;
168 [[nodiscard
]] int32_t getDataEndThreadCount() const {
169 return States
->DataEndThreadCount
;
172 /// Set the event bound to this data map.
173 void setEvent(void *Event
) const { States
->Event
= Event
; }
175 /// Reset the specified reference count unless it's infinity. Reset to 1
176 /// (even if currently 0) so it can be followed by a decrement.
177 void resetRefCount(bool UseHoldRefCount
) const {
178 uint64_t &ThisRefCount
=
179 UseHoldRefCount
? States
->HoldRefCount
: States
->DynRefCount
;
180 if (ThisRefCount
!= INFRefCount
)
184 /// Increment the specified reference count unless it's infinity.
185 void incRefCount(bool UseHoldRefCount
) const {
186 uint64_t &ThisRefCount
=
187 UseHoldRefCount
? States
->HoldRefCount
: States
->DynRefCount
;
188 if (ThisRefCount
!= INFRefCount
) {
190 assert(ThisRefCount
< INFRefCount
&& "refcount overflow");
194 /// Decrement the specified reference count unless it's infinity or zero, and
195 /// return the total reference count.
196 uint64_t decRefCount(bool UseHoldRefCount
) const {
197 uint64_t &ThisRefCount
=
198 UseHoldRefCount
? States
->HoldRefCount
: States
->DynRefCount
;
199 uint64_t OtherRefCount
=
200 UseHoldRefCount
? States
->DynRefCount
: States
->HoldRefCount
;
202 if (ThisRefCount
!= INFRefCount
) {
203 if (ThisRefCount
> 0)
206 assert(OtherRefCount
>= 0 && "total refcount underflow");
208 return getTotalRefCount();
211 /// Is the dynamic (and thus the total) reference count infinite?
212 bool isDynRefCountInf() const { return States
->DynRefCount
== INFRefCount
; }
214 /// Convert the dynamic reference count to a debug string.
215 std::string
dynRefCountToStr() const {
216 return refCountToStr(States
->DynRefCount
);
219 /// Convert the hold reference count to a debug string.
220 std::string
holdRefCountToStr() const {
221 return refCountToStr(States
->HoldRefCount
);
224 /// Should one decrement of the specified reference count (after resetting it
225 /// if \c AfterReset) remove this mapping?
226 bool decShouldRemove(bool UseHoldRefCount
, bool AfterReset
= false) const {
227 uint64_t ThisRefCount
=
228 UseHoldRefCount
? States
->HoldRefCount
: States
->DynRefCount
;
229 uint64_t OtherRefCount
=
230 UseHoldRefCount
? States
->DynRefCount
: States
->HoldRefCount
;
231 if (OtherRefCount
> 0)
234 return ThisRefCount
!= INFRefCount
;
235 return ThisRefCount
== 1;
238 /// Add the shadow pointer info \p ShadowPtrInfo to this entry but only if the
239 /// the target ptr value was not already present in the existing set of shadow
240 /// pointers. Return true if something was added.
241 bool addShadowPointer(const ShadowPtrInfoTy
&ShadowPtrInfo
) const {
242 auto Pair
= States
->ShadowPtrInfos
.insert(ShadowPtrInfo
);
245 // Check for a stale entry, if found, replace the old one.
246 if ((*Pair
.first
).TgtPtrVal
== ShadowPtrInfo
.TgtPtrVal
)
248 States
->ShadowPtrInfos
.erase(ShadowPtrInfo
);
249 return addShadowPointer(ShadowPtrInfo
);
252 /// Apply \p CB to all shadow pointers of this entry. Returns OFFLOAD_FAIL if
253 /// \p CB returned OFFLOAD_FAIL for any of them, otherwise this returns
254 /// OFFLOAD_SUCCESS. The entry is locked for this operation.
255 template <typename CBTy
> int foreachShadowPointerInfo(CBTy CB
) const {
256 for (auto &It
: States
->ShadowPtrInfos
)
257 if (CB(const_cast<ShadowPtrInfoTy
&>(It
)) == OFFLOAD_FAIL
)
259 return OFFLOAD_SUCCESS
;
262 /// Lock this entry for exclusive access. Ensure to get exclusive access to
264 void lock() const { Mtx
.lock(); }
266 /// Unlock this entry to allow other threads inspecting it.
267 void unlock() const { Mtx
.unlock(); }
270 // Mutex that needs to be held before the entry is inspected or modified. The
271 // HDTTMap mutex needs to be held before trying to lock any HDTT Entry.
272 mutable std::mutex Mtx
;
275 /// Wrapper around the HostDataToTargetTy to be used in the HDTT map. In
276 /// addition to the HDTT pointer we store the key value explicitly. This
277 /// allows the set to inspect (sort/search/...) this entry without an additional
278 /// load of HDTT. HDTT is a pointer to allow the modification of the set without
279 /// invalidating HDTT entries which can now be inspected at the same time.
280 struct HostDataToTargetMapKeyTy
{
283 HostDataToTargetMapKeyTy(void *Key
) : KeyValue(uintptr_t(Key
)) {}
284 HostDataToTargetMapKeyTy(uintptr_t Key
) : KeyValue(Key
) {}
285 HostDataToTargetMapKeyTy(HostDataToTargetTy
*HDTT
)
286 : KeyValue(HDTT
->HstPtrBegin
), HDTT(HDTT
) {}
287 HostDataToTargetTy
*HDTT
;
289 inline bool operator<(const HostDataToTargetMapKeyTy
&LHS
,
290 const uintptr_t &RHS
) {
291 return LHS
.KeyValue
< RHS
;
293 inline bool operator<(const uintptr_t &LHS
,
294 const HostDataToTargetMapKeyTy
&RHS
) {
295 return LHS
< RHS
.KeyValue
;
297 inline bool operator<(const HostDataToTargetMapKeyTy
&LHS
,
298 const HostDataToTargetMapKeyTy
&RHS
) {
299 return LHS
.KeyValue
< RHS
.KeyValue
;
302 /// This struct will be returned by \p DeviceTy::getTargetPointer which provides
303 /// more data than just a target pointer. A TargetPointerResultTy that has a non
304 /// null Entry owns the entry. As long as the TargetPointerResultTy (TPR) exists
305 /// the entry is locked. To give up ownership without destroying the TPR use the
306 /// reset() function.
307 struct TargetPointerResultTy
{
309 /// If the map table entry is just created
310 unsigned IsNewEntry
: 1;
311 /// If the pointer is actually a host pointer (when unified memory enabled)
312 unsigned IsHostPointer
: 1;
313 /// If the pointer is present in the mapping table.
314 unsigned IsPresent
: 1;
315 /// Flag indicating that this was the last user of the entry and the ref
318 /// If the pointer is contained.
319 unsigned IsContained
: 1;
320 } Flags
= {0, 0, 0, 0, 0};
322 TargetPointerResultTy(const TargetPointerResultTy
&) = delete;
323 TargetPointerResultTy
&operator=(const TargetPointerResultTy
&TPR
) = delete;
324 TargetPointerResultTy() {}
326 TargetPointerResultTy(FlagTy Flags
, HostDataToTargetTy
*Entry
,
328 : Flags(Flags
), TargetPointer(TargetPointer
), Entry(Entry
) {
333 TargetPointerResultTy(TargetPointerResultTy
&&TPR
)
334 : Flags(TPR
.Flags
), TargetPointer(TPR
.TargetPointer
), Entry(TPR
.Entry
) {
338 TargetPointerResultTy
&operator=(TargetPointerResultTy
&&TPR
) {
340 std::swap(Flags
, TPR
.Flags
);
341 std::swap(Entry
, TPR
.Entry
);
342 std::swap(TargetPointer
, TPR
.TargetPointer
);
347 ~TargetPointerResultTy() {
352 bool isPresent() const { return Flags
.IsPresent
; }
354 bool isHostPointer() const { return Flags
.IsHostPointer
; }
356 bool isContained() const { return Flags
.IsContained
; }
358 /// The corresponding target pointer
359 void *TargetPointer
= nullptr;
361 HostDataToTargetTy
*getEntry() const { return Entry
; }
362 void setEntry(HostDataToTargetTy
*HDTTT
,
363 HostDataToTargetTy
*OwnedTPR
= nullptr) {
367 if (Entry
&& Entry
!= OwnedTPR
)
371 void reset() { *this = TargetPointerResultTy(); }
374 /// The corresponding map table entry which is stable.
375 HostDataToTargetTy
*Entry
= nullptr;
378 struct LookupResult
{
380 unsigned IsContained
: 1;
381 unsigned ExtendsBefore
: 1;
382 unsigned ExtendsAfter
: 1;
385 LookupResult() : Flags({0, 0, 0}), TPR() {}
387 TargetPointerResultTy TPR
;
391 struct PendingCtorDtorListsTy
{
392 std::list
<void *> PendingCtors
;
393 std::list
<void *> PendingDtors
;
395 typedef std::map
<__tgt_bin_desc
*, PendingCtorDtorListsTy
>
396 PendingCtorsDtorsPerLibrary
;
404 std::once_flag InitFlag
;
405 bool HasPendingGlobals
;
407 /// Host data to device map type with a wrapper key indirection that allows
408 /// concurrent modification of the entries without invalidating the underlying
410 using HostDataToTargetListTy
=
411 std::set
<HostDataToTargetMapKeyTy
, std::less
<>>;
413 /// The HDTTMap is a protected object that can only be accessed by one thread
415 ProtectedObj
<HostDataToTargetListTy
> HostDataToTargetMap
;
417 /// The type used to access the HDTT map.
418 using HDTTMapAccessorTy
= decltype(HostDataToTargetMap
)::AccessorTy
;
420 PendingCtorsDtorsPerLibrary PendingCtorsDtors
;
422 std::mutex PendingGlobalsMtx
;
424 DeviceTy(RTLInfoTy
*RTL
);
425 // DeviceTy is not copyable
426 DeviceTy(const DeviceTy
&D
) = delete;
427 DeviceTy
&operator=(const DeviceTy
&D
) = delete;
431 // Return true if data can be copied to DstDevice directly
432 bool isDataExchangable(const DeviceTy
&DstDevice
);
434 /// Lookup the mapping of \p HstPtrBegin in \p HDTTMap. The accessor ensures
435 /// exclusive access to the HDTT map.
436 LookupResult
lookupMapping(HDTTMapAccessorTy
&HDTTMap
, void *HstPtrBegin
,
438 HostDataToTargetTy
*OwnedTPR
= nullptr);
440 /// Get the target pointer based on host pointer begin and base. If the
441 /// mapping already exists, the target pointer will be returned directly. In
442 /// addition, if required, the memory region pointed by \p HstPtrBegin of size
443 /// \p Size will also be transferred to the device. If the mapping doesn't
444 /// exist, and if unified shared memory is not enabled, a new mapping will be
445 /// created and the data will also be transferred accordingly. nullptr will be
446 /// returned because of any of following reasons:
447 /// - Data allocation failed;
448 /// - The user tried to do an illegal mapping;
449 /// - Data transfer issue fails.
450 TargetPointerResultTy
getTargetPointer(
451 HDTTMapAccessorTy
&HDTTMap
, void *HstPtrBegin
, void *HstPtrBase
,
452 int64_t TgtPadding
, int64_t Size
, map_var_info_t HstPtrName
,
453 bool HasFlagTo
, bool HasFlagAlways
, bool IsImplicit
, bool UpdateRefCount
,
454 bool HasCloseModifier
, bool HasPresentModifier
, bool HasHoldModifier
,
455 AsyncInfoTy
&AsyncInfo
, HostDataToTargetTy
*OwnedTPR
= nullptr,
456 bool ReleaseHDTTMap
= true);
458 /// Return the target pointer for \p HstPtrBegin in \p HDTTMap. The accessor
459 /// ensures exclusive access to the HDTT map.
460 void *getTgtPtrBegin(HDTTMapAccessorTy
&HDTTMap
, void *HstPtrBegin
,
463 /// Return the target pointer begin (where the data will be moved).
464 /// Used by targetDataBegin, targetDataEnd, targetDataUpdate and target.
465 /// - \p UpdateRefCount and \p UseHoldRefCount controls which and if the entry
466 /// reference counters will be decremented.
467 /// - \p MustContain enforces that the query must not extend beyond an already
468 /// mapped entry to be valid.
469 /// - \p ForceDelete deletes the entry regardless of its reference counting
470 /// (unless it is infinite).
471 /// - \p FromDataEnd tracks the number of threads referencing the entry at
472 /// targetDataEnd for delayed deletion purpose.
473 [[nodiscard
]] TargetPointerResultTy
474 getTgtPtrBegin(void *HstPtrBegin
, int64_t Size
, bool UpdateRefCount
,
475 bool UseHoldRefCount
, bool MustContain
= false,
476 bool ForceDelete
= false, bool FromDataEnd
= false);
478 /// Remove the \p Entry from the data map. Expect the entry's total reference
479 /// count to be zero and the caller thread to be the last one using it. \p
480 /// HDTTMap ensure the caller holds exclusive access and can modify the map.
481 /// Return \c OFFLOAD_SUCCESS if the map entry existed, and return \c
482 /// OFFLOAD_FAIL if not. It is the caller's responsibility to skip calling
483 /// this function if the map entry is not expected to exist because \p
484 /// HstPtrBegin uses shared memory.
485 [[nodiscard
]] int eraseMapEntry(HDTTMapAccessorTy
&HDTTMap
,
486 HostDataToTargetTy
*Entry
, int64_t Size
);
488 /// Deallocate the \p Entry from the device memory and delete it. Return \c
489 /// OFFLOAD_SUCCESS if the deallocation operations executed successfully, and
490 /// return \c OFFLOAD_FAIL otherwise.
491 [[nodiscard
]] int deallocTgtPtrAndEntry(HostDataToTargetTy
*Entry
,
494 int associatePtr(void *HstPtrBegin
, void *TgtPtrBegin
, int64_t Size
);
495 int disassociatePtr(void *HstPtrBegin
);
499 __tgt_target_table
*loadBinary(void *Img
);
501 // device memory allocation/deallocation routines
502 /// Allocates \p Size bytes on the device, host or shared memory space
503 /// (depending on \p Kind) and returns the address/nullptr when
504 /// succeeds/fails. \p HstPtr is an address of the host data which the
505 /// allocated target data will be associated with. If it is unknown, the
506 /// default value of \p HstPtr is nullptr. Note: this function doesn't do
507 /// pointer association. Actually, all the __tgt_rtl_data_alloc
508 /// implementations ignore \p HstPtr. \p Kind dictates what allocator should
509 /// be used (host, shared, device).
510 void *allocData(int64_t Size
, void *HstPtr
= nullptr,
511 int32_t Kind
= TARGET_ALLOC_DEFAULT
);
512 /// Deallocates memory which \p TgtPtrBegin points at and returns
513 /// OFFLOAD_SUCCESS/OFFLOAD_FAIL when succeeds/fails. p Kind dictates what
514 /// allocator should be used (host, shared, device).
515 int32_t deleteData(void *TgtPtrBegin
, int32_t Kind
= TARGET_ALLOC_DEFAULT
);
517 // Data transfer. When AsyncInfo is nullptr, the transfer will be
519 // Copy data from host to device
520 int32_t submitData(void *TgtPtrBegin
, void *HstPtrBegin
, int64_t Size
,
521 AsyncInfoTy
&AsyncInfo
,
522 HostDataToTargetTy
*Entry
= nullptr);
523 // Copy data from device back to host
524 int32_t retrieveData(void *HstPtrBegin
, void *TgtPtrBegin
, int64_t Size
,
525 AsyncInfoTy
&AsyncInfo
,
526 HostDataToTargetTy
*Entry
= nullptr);
527 // Copy data from current device to destination device directly
528 int32_t dataExchange(void *SrcPtr
, DeviceTy
&DstDev
, void *DstPtr
,
529 int64_t Size
, AsyncInfoTy
&AsyncInfo
);
531 /// Notify the plugin about a new mapping starting at the host address
532 /// \p HstPtr and \p Size bytes.
533 int32_t notifyDataMapped(void *HstPtr
, int64_t Size
);
535 /// Notify the plugin about an existing mapping being unmapped starting at
536 /// the host address \p HstPtr.
537 int32_t notifyDataUnmapped(void *HstPtr
);
539 // Launch the kernel identified by \p TgtEntryPtr with the given arguments.
540 int32_t launchKernel(void *TgtEntryPtr
, void **TgtVarsPtr
,
541 ptrdiff_t *TgtOffsets
, const KernelArgsTy
&KernelArgs
,
542 AsyncInfoTy
&AsyncInfo
);
544 /// Synchronize device/queue/event based on \p AsyncInfo and return
545 /// OFFLOAD_SUCCESS/OFFLOAD_FAIL when succeeds/fails.
546 int32_t synchronize(AsyncInfoTy
&AsyncInfo
);
548 /// Query for device/queue/event based completion on \p AsyncInfo in a
549 /// non-blocking manner and return OFFLOAD_SUCCESS/OFFLOAD_FAIL when
550 /// succeeds/fails. Must be called multiple times until AsyncInfo is
551 /// completed and AsyncInfo.isDone() returns true.
552 int32_t queryAsync(AsyncInfoTy
&AsyncInfo
);
554 /// Calls the corresponding print in the \p RTLDEVID
555 /// device RTL to obtain the information of the specific device.
556 bool printDeviceInfo(int32_t RTLDevID
);
558 /// Event related interfaces.
561 int32_t createEvent(void **Event
);
563 /// Record the event based on status in AsyncInfo->Queue at the moment the
564 /// function is called.
565 int32_t recordEvent(void *Event
, AsyncInfoTy
&AsyncInfo
);
567 /// Wait for an event. This function can be blocking or non-blocking,
568 /// depending on the implmentation. It is expected to set a dependence on the
569 /// event such that corresponding operations shall only start once the event
571 int32_t waitEvent(void *Event
, AsyncInfoTy
&AsyncInfo
);
573 /// Synchronize the event. It is expected to block the thread.
574 int32_t syncEvent(void *Event
);
576 /// Destroy the event.
577 int32_t destroyEvent(void *Event
);
582 void init(); // To be called only via DeviceTy::initOnce()
584 /// Deinitialize the device (and plugin).
588 extern bool deviceIsReady(int DeviceNum
);
590 /// Struct for the data required to handle plugins
591 struct PluginManager
{
592 PluginManager(bool UseEventsForAtomicTransfers
)
593 : UseEventsForAtomicTransfers(UseEventsForAtomicTransfers
) {}
595 /// RTLs identified on the host
598 /// Executable images and information extracted from the input images passed
600 std::list
<std::pair
<__tgt_device_image
, __tgt_image_info
>> Images
;
602 /// Devices associated with RTLs
603 llvm::SmallVector
<std::unique_ptr
<DeviceTy
>> Devices
;
604 std::mutex RTLsMtx
; ///< For RTLs and Devices
606 /// Translation table retreived from the binary
607 HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable
;
608 std::mutex TrlTblMtx
; ///< For Translation Table
609 /// Host offload entries in order of image registration
610 llvm::SmallVector
<__tgt_offload_entry
*> HostEntriesBeginRegistrationOrder
;
612 /// Map from ptrs on the host to an entry in the Translation Table
613 HostPtrToTableMapTy HostPtrToTableMap
;
614 std::mutex TblMapMtx
; ///< For HostPtrToTableMap
616 // Store target policy (disabled, mandatory, default)
617 kmp_target_offload_kind_t TargetOffloadPolicy
= tgt_default
;
618 std::mutex TargetOffloadMtx
; ///< For TargetOffloadPolicy
620 /// Flag to indicate if we use events to ensure the atomicity of
621 /// map clauses or not. Can be modified with an environment variable.
622 const bool UseEventsForAtomicTransfers
;
624 // Work around for plugins that call dlopen on shared libraries that call
625 // tgt_register_lib during their initialisation. Stash the pointers in a
626 // vector until the plugins are all initialised and then register them.
627 bool maybeDelayRegisterLib(__tgt_bin_desc
*Desc
) {
629 // Only reachable from libomptarget constructor
630 DelayedBinDesc
.push_back(Desc
);
637 void registerDelayedLibraries() {
638 // Only called by libomptarget constructor
640 for (auto *Desc
: DelayedBinDesc
)
641 __tgt_register_lib(Desc
);
642 DelayedBinDesc
.clear();
646 bool RTLsLoaded
= false;
647 llvm::SmallVector
<__tgt_bin_desc
*> DelayedBinDesc
;
650 extern PluginManager
*PM
;