forked from OSchip/llvm-project
[LIBOMPTARGET]Fix PR44933: fix crash because of the too early deinitialization of libomptarget.
Summary: Instead of using global variables with unpredicted time of deinitialization, use dynamically allocated variables with functions explicitly marked as global constructor/destructor and priority. This allows to prevent the crash because of the incorrect order of dynamic libraries deinitialization. Reviewers: grokos, hfinkel Subscribers: caomhin, kkwli0, openmp-commits Tags: #openmp Differential Revision: https://reviews.llvm.org/D74837
This commit is contained in:
parent
c5ce6d8b56
commit
63cef621f9
|
@ -21,9 +21,9 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
EXTERN int omp_get_num_devices(void) {
|
EXTERN int omp_get_num_devices(void) {
|
||||||
RTLsMtx.lock();
|
RTLsMtx->lock();
|
||||||
size_t Devices_size = Devices.size();
|
size_t Devices_size = Devices.size();
|
||||||
RTLsMtx.unlock();
|
RTLsMtx->unlock();
|
||||||
|
|
||||||
DP("Call to omp_get_num_devices returning %zd\n", Devices_size);
|
DP("Call to omp_get_num_devices returning %zd\n", Devices_size);
|
||||||
|
|
||||||
|
@ -102,9 +102,9 @@ EXTERN int omp_target_is_present(void *ptr, int device_num) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLsMtx.lock();
|
RTLsMtx->lock();
|
||||||
size_t Devices_size = Devices.size();
|
size_t Devices_size = Devices.size();
|
||||||
RTLsMtx.unlock();
|
RTLsMtx->unlock();
|
||||||
if (Devices_size <= (size_t)device_num) {
|
if (Devices_size <= (size_t)device_num) {
|
||||||
DP("Call to omp_target_is_present with invalid device ID, returning "
|
DP("Call to omp_target_is_present with invalid device ID, returning "
|
||||||
"false\n");
|
"false\n");
|
||||||
|
@ -120,7 +120,7 @@ EXTERN int omp_target_is_present(void *ptr, int device_num) {
|
||||||
// getTgtPtrBegin() function which means that there is no device
|
// getTgtPtrBegin() function which means that there is no device
|
||||||
// corresponding point for ptr. This function should return false
|
// corresponding point for ptr. This function should return false
|
||||||
// in that situation.
|
// in that situation.
|
||||||
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY)
|
if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY)
|
||||||
rc = !IsHostPtr;
|
rc = !IsHostPtr;
|
||||||
DP("Call to omp_target_is_present returns %d\n", rc);
|
DP("Call to omp_target_is_present returns %d\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -189,7 +189,8 @@ void *DeviceTy::getOrAllocTgtPtr(void *HstPtrBegin, void *HstPtrBase,
|
||||||
// maps are respected.
|
// maps are respected.
|
||||||
// In addition to the mapping rules above, the close map
|
// In addition to the mapping rules above, the close map
|
||||||
// modifier forces the mapping of the variable to the device.
|
// modifier forces the mapping of the variable to the device.
|
||||||
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && !HasCloseModifier) {
|
if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
||||||
|
!HasCloseModifier) {
|
||||||
DP("Return HstPtrBegin " DPxMOD " Size=%ld RefCount=%s\n",
|
DP("Return HstPtrBegin " DPxMOD " Size=%ld RefCount=%s\n",
|
||||||
DPxPTR((uintptr_t)HstPtrBegin), Size, (UpdateRefCount ? " updated" : ""));
|
DPxPTR((uintptr_t)HstPtrBegin), Size, (UpdateRefCount ? " updated" : ""));
|
||||||
IsHostPtr = true;
|
IsHostPtr = true;
|
||||||
|
@ -235,7 +236,7 @@ void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size, bool &IsLast,
|
||||||
(UpdateRefCount ? " updated" : ""),
|
(UpdateRefCount ? " updated" : ""),
|
||||||
HT.isRefCountInf() ? "INF" : std::to_string(HT.getRefCount()).c_str());
|
HT.isRefCountInf() ? "INF" : std::to_string(HT.getRefCount()).c_str());
|
||||||
rc = (void *)tp;
|
rc = (void *)tp;
|
||||||
} else if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) {
|
} else if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) {
|
||||||
// If the value isn't found in the mapping and unified shared memory
|
// If the value isn't found in the mapping and unified shared memory
|
||||||
// is on then it means we have stumbled upon a value which we need to
|
// is on then it means we have stumbled upon a value which we need to
|
||||||
// use directly from the host.
|
// use directly from the host.
|
||||||
|
@ -265,7 +266,7 @@ void *DeviceTy::getTgtPtrBegin(void *HstPtrBegin, int64_t Size) {
|
||||||
|
|
||||||
int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete,
|
int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete,
|
||||||
bool HasCloseModifier) {
|
bool HasCloseModifier) {
|
||||||
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && !HasCloseModifier)
|
if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && !HasCloseModifier)
|
||||||
return OFFLOAD_SUCCESS;
|
return OFFLOAD_SUCCESS;
|
||||||
// Check if the pointer is contained in any sub-nodes.
|
// Check if the pointer is contained in any sub-nodes.
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -299,7 +300,7 @@ int DeviceTy::deallocTgtPtr(void *HstPtrBegin, int64_t Size, bool ForceDelete,
|
||||||
void DeviceTy::init() {
|
void DeviceTy::init() {
|
||||||
// Make call to init_requires if it exists for this plugin.
|
// Make call to init_requires if it exists for this plugin.
|
||||||
if (RTL->init_requires)
|
if (RTL->init_requires)
|
||||||
RTL->init_requires(RTLs.RequiresFlags);
|
RTL->init_requires(RTLs->RequiresFlags);
|
||||||
int32_t rc = RTL->init_device(RTLDeviceID);
|
int32_t rc = RTL->init_device(RTLDeviceID);
|
||||||
if (rc == OFFLOAD_SUCCESS) {
|
if (rc == OFFLOAD_SUCCESS) {
|
||||||
IsInit = true;
|
IsInit = true;
|
||||||
|
@ -363,9 +364,9 @@ bool device_is_ready(int device_num) {
|
||||||
DP("Checking whether device %d is ready.\n", device_num);
|
DP("Checking whether device %d is ready.\n", device_num);
|
||||||
// Devices.size() can only change while registering a new
|
// Devices.size() can only change while registering a new
|
||||||
// library, so try to acquire the lock of RTLs' mutex.
|
// library, so try to acquire the lock of RTLs' mutex.
|
||||||
RTLsMtx.lock();
|
RTLsMtx->lock();
|
||||||
size_t Devices_size = Devices.size();
|
size_t Devices_size = Devices.size();
|
||||||
RTLsMtx.unlock();
|
RTLsMtx->unlock();
|
||||||
if (Devices_size <= (size_t)device_num) {
|
if (Devices_size <= (size_t)device_num) {
|
||||||
DP("Device ID %d does not have a matching RTL\n", device_num);
|
DP("Device ID %d does not have a matching RTL\n", device_num);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -71,19 +71,19 @@ static void HandleTargetOutcome(bool success) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// adds requires flags
|
/// adds requires flags
|
||||||
EXTERN void __tgt_register_requires(int64_t flags) {
|
EXTERN void __tgt_register_requires(int64_t flags) {
|
||||||
RTLs.RegisterRequires(flags);
|
RTLs->RegisterRequires(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// adds a target shared library to the target execution image
|
/// adds a target shared library to the target execution image
|
||||||
EXTERN void __tgt_register_lib(__tgt_bin_desc *desc) {
|
EXTERN void __tgt_register_lib(__tgt_bin_desc *desc) {
|
||||||
RTLs.RegisterLib(desc);
|
RTLs->RegisterLib(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// unloads a target shared library
|
/// unloads a target shared library
|
||||||
EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) {
|
EXTERN void __tgt_unregister_lib(__tgt_bin_desc *desc) {
|
||||||
RTLs.UnregisterLib(desc);
|
RTLs->UnregisterLib(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// creates host-to-target data mapping, stores it in the
|
/// creates host-to-target data mapping, stores it in the
|
||||||
|
@ -147,9 +147,9 @@ EXTERN void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
|
||||||
device_id = omp_get_default_device();
|
device_id = omp_get_default_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
RTLsMtx.lock();
|
RTLsMtx->lock();
|
||||||
size_t Devices_size = Devices.size();
|
size_t Devices_size = Devices.size();
|
||||||
RTLsMtx.unlock();
|
RTLsMtx->unlock();
|
||||||
if (Devices_size <= (size_t)device_id) {
|
if (Devices_size <= (size_t)device_id) {
|
||||||
DP("Device ID %" PRId64 " does not have a matching RTL.\n", device_id);
|
DP("Device ID %" PRId64 " does not have a matching RTL.\n", device_id);
|
||||||
HandleTargetOutcome(false);
|
HandleTargetOutcome(false);
|
||||||
|
@ -343,8 +343,8 @@ EXTERN void __kmpc_push_target_tripcount(int64_t device_id,
|
||||||
|
|
||||||
DP("__kmpc_push_target_tripcount(%" PRId64 ", %" PRIu64 ")\n", device_id,
|
DP("__kmpc_push_target_tripcount(%" PRId64 ", %" PRIu64 ")\n", device_id,
|
||||||
loop_tripcount);
|
loop_tripcount);
|
||||||
TblMapMtx.lock();
|
TblMapMtx->lock();
|
||||||
Devices[device_id].LoopTripCnt.emplace(__kmpc_global_thread_num(NULL),
|
Devices[device_id].LoopTripCnt.emplace(__kmpc_global_thread_num(NULL),
|
||||||
loop_tripcount);
|
loop_tripcount);
|
||||||
TblMapMtx.unlock();
|
TblMapMtx->unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,10 +67,10 @@ static int InitLibrary(DeviceTy& Device) {
|
||||||
int rc = OFFLOAD_SUCCESS;
|
int rc = OFFLOAD_SUCCESS;
|
||||||
|
|
||||||
Device.PendingGlobalsMtx.lock();
|
Device.PendingGlobalsMtx.lock();
|
||||||
TrlTblMtx.lock();
|
TrlTblMtx->lock();
|
||||||
for (HostEntriesBeginToTransTableTy::iterator
|
for (HostEntriesBeginToTransTableTy::iterator
|
||||||
ii = HostEntriesBeginToTransTable.begin();
|
ii = HostEntriesBeginToTransTable->begin();
|
||||||
ii != HostEntriesBeginToTransTable.end(); ++ii) {
|
ii != HostEntriesBeginToTransTable->end(); ++ii) {
|
||||||
TranslationTable *TransTable = &ii->second;
|
TranslationTable *TransTable = &ii->second;
|
||||||
if (TransTable->HostTable.EntriesBegin ==
|
if (TransTable->HostTable.EntriesBegin ==
|
||||||
TransTable->HostTable.EntriesEnd) {
|
TransTable->HostTable.EntriesEnd) {
|
||||||
|
@ -149,7 +149,7 @@ static int InitLibrary(DeviceTy& Device) {
|
||||||
}
|
}
|
||||||
Device.DataMapMtx.unlock();
|
Device.DataMapMtx.unlock();
|
||||||
}
|
}
|
||||||
TrlTblMtx.unlock();
|
TrlTblMtx->unlock();
|
||||||
|
|
||||||
if (rc != OFFLOAD_SUCCESS) {
|
if (rc != OFFLOAD_SUCCESS) {
|
||||||
Device.PendingGlobalsMtx.unlock();
|
Device.PendingGlobalsMtx.unlock();
|
||||||
|
@ -299,7 +299,7 @@ int target_data_begin(DeviceTy &Device, int32_t arg_num,
|
||||||
|
|
||||||
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
|
if (arg_types[i] & OMP_TGT_MAPTYPE_TO) {
|
||||||
bool copy = false;
|
bool copy = false;
|
||||||
if (!(RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
|
if (!(RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
|
||||||
HasCloseModifier) {
|
HasCloseModifier) {
|
||||||
if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS)) {
|
if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS)) {
|
||||||
copy = true;
|
copy = true;
|
||||||
|
@ -401,7 +401,7 @@ int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
|
||||||
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
|
if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) {
|
||||||
bool Always = arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS;
|
bool Always = arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS;
|
||||||
bool CopyMember = false;
|
bool CopyMember = false;
|
||||||
if (!(RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
|
if (!(RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
|
||||||
HasCloseModifier) {
|
HasCloseModifier) {
|
||||||
if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
|
if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) &&
|
||||||
!(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) {
|
!(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) {
|
||||||
|
@ -416,7 +416,7 @@ int target_data_end(DeviceTy &Device, int32_t arg_num, void **args_base,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((DelEntry || Always || CopyMember) &&
|
if ((DelEntry || Always || CopyMember) &&
|
||||||
!(RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
!(RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
||||||
TgtPtrBegin == HstPtrBegin)) {
|
TgtPtrBegin == HstPtrBegin)) {
|
||||||
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
|
DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n",
|
||||||
data_size, DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
|
data_size, DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin));
|
||||||
|
@ -499,7 +499,7 @@ int target_data_update(DeviceTy &Device, int32_t arg_num,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
||||||
TgtPtrBegin == HstPtrBegin) {
|
TgtPtrBegin == HstPtrBegin) {
|
||||||
DP("hst data:" DPxMOD " unified and shared, becomes a noop\n",
|
DP("hst data:" DPxMOD " unified and shared, becomes a noop\n",
|
||||||
DPxPTR(HstPtrBegin));
|
DPxPTR(HstPtrBegin));
|
||||||
|
@ -590,14 +590,14 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
|
||||||
// Find the table information in the map or look it up in the translation
|
// Find the table information in the map or look it up in the translation
|
||||||
// tables.
|
// tables.
|
||||||
TableMap *TM = 0;
|
TableMap *TM = 0;
|
||||||
TblMapMtx.lock();
|
TblMapMtx->lock();
|
||||||
HostPtrToTableMapTy::iterator TableMapIt = HostPtrToTableMap.find(host_ptr);
|
HostPtrToTableMapTy::iterator TableMapIt = HostPtrToTableMap->find(host_ptr);
|
||||||
if (TableMapIt == HostPtrToTableMap.end()) {
|
if (TableMapIt == HostPtrToTableMap->end()) {
|
||||||
// We don't have a map. So search all the registered libraries.
|
// We don't have a map. So search all the registered libraries.
|
||||||
TrlTblMtx.lock();
|
TrlTblMtx->lock();
|
||||||
for (HostEntriesBeginToTransTableTy::iterator
|
for (HostEntriesBeginToTransTableTy::iterator
|
||||||
ii = HostEntriesBeginToTransTable.begin(),
|
ii = HostEntriesBeginToTransTable->begin(),
|
||||||
ie = HostEntriesBeginToTransTable.end();
|
ie = HostEntriesBeginToTransTable->end();
|
||||||
!TM && ii != ie; ++ii) {
|
!TM && ii != ie; ++ii) {
|
||||||
// get the translation table (which contains all the good info).
|
// get the translation table (which contains all the good info).
|
||||||
TranslationTable *TransTable = &ii->second;
|
TranslationTable *TransTable = &ii->second;
|
||||||
|
@ -611,17 +611,17 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
|
||||||
continue;
|
continue;
|
||||||
// we got a match, now fill the HostPtrToTableMap so that we
|
// we got a match, now fill the HostPtrToTableMap so that we
|
||||||
// may avoid this search next time.
|
// may avoid this search next time.
|
||||||
TM = &HostPtrToTableMap[host_ptr];
|
TM = &(*HostPtrToTableMap)[host_ptr];
|
||||||
TM->Table = TransTable;
|
TM->Table = TransTable;
|
||||||
TM->Index = i;
|
TM->Index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TrlTblMtx.unlock();
|
TrlTblMtx->unlock();
|
||||||
} else {
|
} else {
|
||||||
TM = &TableMapIt->second;
|
TM = &TableMapIt->second;
|
||||||
}
|
}
|
||||||
TblMapMtx.unlock();
|
TblMapMtx->unlock();
|
||||||
|
|
||||||
// No map for this host pointer found!
|
// No map for this host pointer found!
|
||||||
if (!TM) {
|
if (!TM) {
|
||||||
|
@ -631,11 +631,11 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
|
||||||
}
|
}
|
||||||
|
|
||||||
// get target table.
|
// get target table.
|
||||||
TrlTblMtx.lock();
|
TrlTblMtx->lock();
|
||||||
assert(TM->Table->TargetsTable.size() > (size_t)device_id &&
|
assert(TM->Table->TargetsTable.size() > (size_t)device_id &&
|
||||||
"Not expecting a device ID outside the table's bounds!");
|
"Not expecting a device ID outside the table's bounds!");
|
||||||
__tgt_target_table *TargetTable = TM->Table->TargetsTable[device_id];
|
__tgt_target_table *TargetTable = TM->Table->TargetsTable[device_id];
|
||||||
TrlTblMtx.unlock();
|
TrlTblMtx->unlock();
|
||||||
assert(TargetTable && "Global data has not been mapped\n");
|
assert(TargetTable && "Global data has not been mapped\n");
|
||||||
|
|
||||||
// Move data to device.
|
// Move data to device.
|
||||||
|
@ -682,7 +682,7 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
|
||||||
DPxPTR(HstPtrVal));
|
DPxPTR(HstPtrVal));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
if (RTLs->RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY &&
|
||||||
TgtPtrBegin == HstPtrBegin) {
|
TgtPtrBegin == HstPtrBegin) {
|
||||||
DP("Unified memory is active, no need to map lambda captured"
|
DP("Unified memory is active, no need to map lambda captured"
|
||||||
"variable (" DPxMOD ")\n", DPxPTR(HstPtrVal));
|
"variable (" DPxMOD ")\n", DPxPTR(HstPtrVal));
|
||||||
|
@ -765,14 +765,14 @@ int target(int64_t device_id, void *host_ptr, int32_t arg_num,
|
||||||
|
|
||||||
// Pop loop trip count
|
// Pop loop trip count
|
||||||
uint64_t ltc = 0;
|
uint64_t ltc = 0;
|
||||||
TblMapMtx.lock();
|
TblMapMtx->lock();
|
||||||
auto I = Device.LoopTripCnt.find(__kmpc_global_thread_num(NULL));
|
auto I = Device.LoopTripCnt.find(__kmpc_global_thread_num(NULL));
|
||||||
if (I != Device.LoopTripCnt.end()) {
|
if (I != Device.LoopTripCnt.end()) {
|
||||||
ltc = I->second;
|
ltc = I->second;
|
||||||
Device.LoopTripCnt.erase(I);
|
Device.LoopTripCnt.erase(I);
|
||||||
DP("loop trip count is %lu.\n", ltc);
|
DP("loop trip count is %lu.\n", ltc);
|
||||||
}
|
}
|
||||||
TblMapMtx.unlock();
|
TblMapMtx->unlock();
|
||||||
|
|
||||||
// Launch device execution.
|
// Launch device execution.
|
||||||
DP("Launching target execution %s with pointer " DPxMOD " (index=%d).\n",
|
DP("Launching target execution %s with pointer " DPxMOD " (index=%d).\n",
|
||||||
|
|
|
@ -28,14 +28,34 @@ static const char *RTLNames[] = {
|
||||||
/* CUDA target */ "libomptarget.rtl.cuda.so",
|
/* CUDA target */ "libomptarget.rtl.cuda.so",
|
||||||
/* AArch64 target */ "libomptarget.rtl.aarch64.so"};
|
/* AArch64 target */ "libomptarget.rtl.aarch64.so"};
|
||||||
|
|
||||||
RTLsTy RTLs;
|
RTLsTy *RTLs;
|
||||||
std::mutex RTLsMtx;
|
std::mutex *RTLsMtx;
|
||||||
|
|
||||||
HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
|
HostEntriesBeginToTransTableTy *HostEntriesBeginToTransTable;
|
||||||
std::mutex TrlTblMtx;
|
std::mutex *TrlTblMtx;
|
||||||
|
|
||||||
HostPtrToTableMapTy HostPtrToTableMap;
|
HostPtrToTableMapTy *HostPtrToTableMap;
|
||||||
std::mutex TblMapMtx;
|
std::mutex *TblMapMtx;
|
||||||
|
|
||||||
|
__attribute__((constructor(0))) void init() {
|
||||||
|
DP("Init target library!\n");
|
||||||
|
RTLs = new RTLsTy();
|
||||||
|
RTLsMtx = new std::mutex();
|
||||||
|
HostEntriesBeginToTransTable = new HostEntriesBeginToTransTableTy();
|
||||||
|
TrlTblMtx = new std::mutex();
|
||||||
|
HostPtrToTableMap = new HostPtrToTableMapTy();
|
||||||
|
TblMapMtx = new std::mutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((destructor(0))) void deinit() {
|
||||||
|
DP("Deinit target library!\n");
|
||||||
|
delete RTLs;
|
||||||
|
delete RTLsMtx;
|
||||||
|
delete HostEntriesBeginToTransTable;
|
||||||
|
delete TrlTblMtx;
|
||||||
|
delete HostPtrToTableMap;
|
||||||
|
delete TblMapMtx;
|
||||||
|
}
|
||||||
|
|
||||||
void RTLsTy::LoadRTLs() {
|
void RTLsTy::LoadRTLs() {
|
||||||
#ifdef OMPTARGET_DEBUG
|
#ifdef OMPTARGET_DEBUG
|
||||||
|
@ -234,7 +254,7 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
|
||||||
// Attempt to load all plugins available in the system.
|
// Attempt to load all plugins available in the system.
|
||||||
std::call_once(initFlag, &RTLsTy::LoadRTLs, this);
|
std::call_once(initFlag, &RTLsTy::LoadRTLs, this);
|
||||||
|
|
||||||
RTLsMtx.lock();
|
RTLsMtx->lock();
|
||||||
// Register the images with the RTLs that understand them, if any.
|
// Register the images with the RTLs that understand them, if any.
|
||||||
for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
|
for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
|
||||||
// Obtain the image.
|
// Obtain the image.
|
||||||
|
@ -244,7 +264,7 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
|
||||||
|
|
||||||
// Scan the RTLs that have associated images until we find one that supports
|
// Scan the RTLs that have associated images until we find one that supports
|
||||||
// the current image.
|
// the current image.
|
||||||
for (auto &R : RTLs.AllRTLs) {
|
for (auto &R : AllRTLs) {
|
||||||
if (!R.is_valid_binary(img)) {
|
if (!R.is_valid_binary(img)) {
|
||||||
DP("Image " DPxMOD " is NOT compatible with RTL %s!\n",
|
DP("Image " DPxMOD " is NOT compatible with RTL %s!\n",
|
||||||
DPxPTR(img->ImageStart), R.RTLName.c_str());
|
DPxPTR(img->ImageStart), R.RTLName.c_str());
|
||||||
|
@ -269,35 +289,34 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the index of this RTL and save it in the used RTLs.
|
// Initialize the index of this RTL and save it in the used RTLs.
|
||||||
R.Idx = (RTLs.UsedRTLs.empty())
|
R.Idx = (UsedRTLs.empty())
|
||||||
? 0
|
? 0
|
||||||
: RTLs.UsedRTLs.back()->Idx +
|
: UsedRTLs.back()->Idx + UsedRTLs.back()->NumberOfDevices;
|
||||||
RTLs.UsedRTLs.back()->NumberOfDevices;
|
|
||||||
assert((size_t) R.Idx == start &&
|
assert((size_t) R.Idx == start &&
|
||||||
"RTL index should equal the number of devices used so far.");
|
"RTL index should equal the number of devices used so far.");
|
||||||
R.isUsed = true;
|
R.isUsed = true;
|
||||||
RTLs.UsedRTLs.push_back(&R);
|
UsedRTLs.push_back(&R);
|
||||||
|
|
||||||
DP("RTL " DPxMOD " has index %d!\n", DPxPTR(R.LibraryHandler), R.Idx);
|
DP("RTL " DPxMOD " has index %d!\n", DPxPTR(R.LibraryHandler), R.Idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize (if necessary) translation table for this library.
|
// Initialize (if necessary) translation table for this library.
|
||||||
TrlTblMtx.lock();
|
TrlTblMtx->lock();
|
||||||
if(!HostEntriesBeginToTransTable.count(desc->HostEntriesBegin)){
|
if(!HostEntriesBeginToTransTable->count(desc->HostEntriesBegin)){
|
||||||
TranslationTable &tt =
|
TranslationTable &tt =
|
||||||
HostEntriesBeginToTransTable[desc->HostEntriesBegin];
|
(*HostEntriesBeginToTransTable)[desc->HostEntriesBegin];
|
||||||
tt.HostTable.EntriesBegin = desc->HostEntriesBegin;
|
tt.HostTable.EntriesBegin = desc->HostEntriesBegin;
|
||||||
tt.HostTable.EntriesEnd = desc->HostEntriesEnd;
|
tt.HostTable.EntriesEnd = desc->HostEntriesEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve translation table for this library.
|
// Retrieve translation table for this library.
|
||||||
TranslationTable &TransTable =
|
TranslationTable &TransTable =
|
||||||
HostEntriesBeginToTransTable[desc->HostEntriesBegin];
|
(*HostEntriesBeginToTransTable)[desc->HostEntriesBegin];
|
||||||
|
|
||||||
DP("Registering image " DPxMOD " with RTL %s!\n",
|
DP("Registering image " DPxMOD " with RTL %s!\n",
|
||||||
DPxPTR(img->ImageStart), R.RTLName.c_str());
|
DPxPTR(img->ImageStart), R.RTLName.c_str());
|
||||||
RegisterImageIntoTranslationTable(TransTable, R, img);
|
RegisterImageIntoTranslationTable(TransTable, R, img);
|
||||||
TrlTblMtx.unlock();
|
TrlTblMtx->unlock();
|
||||||
FoundRTL = &R;
|
FoundRTL = &R;
|
||||||
|
|
||||||
// Load ctors/dtors for static objects
|
// Load ctors/dtors for static objects
|
||||||
|
@ -311,7 +330,7 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
|
||||||
DP("No RTL found for image " DPxMOD "!\n", DPxPTR(img->ImageStart));
|
DP("No RTL found for image " DPxMOD "!\n", DPxPTR(img->ImageStart));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RTLsMtx.unlock();
|
RTLsMtx->unlock();
|
||||||
|
|
||||||
|
|
||||||
DP("Done registering entries!\n");
|
DP("Done registering entries!\n");
|
||||||
|
@ -320,7 +339,7 @@ void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
|
||||||
void RTLsTy::UnregisterLib(__tgt_bin_desc *desc) {
|
void RTLsTy::UnregisterLib(__tgt_bin_desc *desc) {
|
||||||
DP("Unloading target library!\n");
|
DP("Unloading target library!\n");
|
||||||
|
|
||||||
RTLsMtx.lock();
|
RTLsMtx->lock();
|
||||||
// Find which RTL understands each image, if any.
|
// Find which RTL understands each image, if any.
|
||||||
for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
|
for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
|
||||||
// Obtain the image.
|
// Obtain the image.
|
||||||
|
@ -330,7 +349,7 @@ void RTLsTy::UnregisterLib(__tgt_bin_desc *desc) {
|
||||||
|
|
||||||
// Scan the RTLs that have associated images until we find one that supports
|
// Scan the RTLs that have associated images until we find one that supports
|
||||||
// the current image. We only need to scan RTLs that are already being used.
|
// the current image. We only need to scan RTLs that are already being used.
|
||||||
for (auto *R : RTLs.UsedRTLs) {
|
for (auto *R : UsedRTLs) {
|
||||||
|
|
||||||
assert(R->isUsed && "Expecting used RTLs.");
|
assert(R->isUsed && "Expecting used RTLs.");
|
||||||
|
|
||||||
|
@ -376,28 +395,28 @@ void RTLsTy::UnregisterLib(__tgt_bin_desc *desc) {
|
||||||
DPxPTR(img->ImageStart));
|
DPxPTR(img->ImageStart));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RTLsMtx.unlock();
|
RTLsMtx->unlock();
|
||||||
DP("Done unregistering images!\n");
|
DP("Done unregistering images!\n");
|
||||||
|
|
||||||
// Remove entries from HostPtrToTableMap
|
// Remove entries from HostPtrToTableMap
|
||||||
TblMapMtx.lock();
|
TblMapMtx->lock();
|
||||||
for (__tgt_offload_entry *cur = desc->HostEntriesBegin;
|
for (__tgt_offload_entry *cur = desc->HostEntriesBegin;
|
||||||
cur < desc->HostEntriesEnd; ++cur) {
|
cur < desc->HostEntriesEnd; ++cur) {
|
||||||
HostPtrToTableMap.erase(cur->addr);
|
HostPtrToTableMap->erase(cur->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove translation table for this descriptor.
|
// Remove translation table for this descriptor.
|
||||||
auto tt = HostEntriesBeginToTransTable.find(desc->HostEntriesBegin);
|
auto tt = HostEntriesBeginToTransTable->find(desc->HostEntriesBegin);
|
||||||
if (tt != HostEntriesBeginToTransTable.end()) {
|
if (tt != HostEntriesBeginToTransTable->end()) {
|
||||||
DP("Removing translation table for descriptor " DPxMOD "\n",
|
DP("Removing translation table for descriptor " DPxMOD "\n",
|
||||||
DPxPTR(desc->HostEntriesBegin));
|
DPxPTR(desc->HostEntriesBegin));
|
||||||
HostEntriesBeginToTransTable.erase(tt);
|
HostEntriesBeginToTransTable->erase(tt);
|
||||||
} else {
|
} else {
|
||||||
DP("Translation table for descriptor " DPxMOD " cannot be found, probably "
|
DP("Translation table for descriptor " DPxMOD " cannot be found, probably "
|
||||||
"it has been already removed.\n", DPxPTR(desc->HostEntriesBegin));
|
"it has been already removed.\n", DPxPTR(desc->HostEntriesBegin));
|
||||||
}
|
}
|
||||||
|
|
||||||
TblMapMtx.unlock();
|
TblMapMtx->unlock();
|
||||||
|
|
||||||
// TODO: Remove RTL and the devices it manages if it's not used anymore?
|
// TODO: Remove RTL and the devices it manages if it's not used anymore?
|
||||||
// TODO: Write some RTL->unload_image(...) function?
|
// TODO: Write some RTL->unload_image(...) function?
|
||||||
|
|
|
@ -134,8 +134,8 @@ public:
|
||||||
// Unregister a shared library from all RTLs.
|
// Unregister a shared library from all RTLs.
|
||||||
void UnregisterLib(__tgt_bin_desc *desc);
|
void UnregisterLib(__tgt_bin_desc *desc);
|
||||||
};
|
};
|
||||||
extern RTLsTy RTLs;
|
extern RTLsTy *RTLs;
|
||||||
extern std::mutex RTLsMtx;
|
extern std::mutex *RTLsMtx;
|
||||||
|
|
||||||
|
|
||||||
/// Map between the host entry begin and the translation table. Each
|
/// Map between the host entry begin and the translation table. Each
|
||||||
|
@ -153,8 +153,8 @@ struct TranslationTable {
|
||||||
};
|
};
|
||||||
typedef std::map<__tgt_offload_entry *, TranslationTable>
|
typedef std::map<__tgt_offload_entry *, TranslationTable>
|
||||||
HostEntriesBeginToTransTableTy;
|
HostEntriesBeginToTransTableTy;
|
||||||
extern HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
|
extern HostEntriesBeginToTransTableTy *HostEntriesBeginToTransTable;
|
||||||
extern std::mutex TrlTblMtx;
|
extern std::mutex *TrlTblMtx;
|
||||||
|
|
||||||
/// Map between the host ptr and a table index
|
/// Map between the host ptr and a table index
|
||||||
struct TableMap {
|
struct TableMap {
|
||||||
|
@ -165,7 +165,7 @@ struct TableMap {
|
||||||
: Table(table), Index(index) {}
|
: Table(table), Index(index) {}
|
||||||
};
|
};
|
||||||
typedef std::map<void *, TableMap> HostPtrToTableMapTy;
|
typedef std::map<void *, TableMap> HostPtrToTableMapTy;
|
||||||
extern HostPtrToTableMapTy HostPtrToTableMap;
|
extern HostPtrToTableMapTy *HostPtrToTableMap;
|
||||||
extern std::mutex TblMapMtx;
|
extern std::mutex *TblMapMtx;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// RUN: %libomptarget-compile-aarch64-unknown-linux-gnu -DSHARED -shared -o %t.so && %clang %flags %s -o %t-aarch64-unknown-linux-gnu -ldl && %libomptarget-run-aarch64-unknown-linux-gnu %t.so 2>&1 | %fcheck-aarch64-unknown-linux-gnu
|
||||||
|
// RUN: %libomptarget-compile-powerpc64-ibm-linux-gnu -DSHARED -shared -o %t.so && %clang %flags %s -o %t-powerpc64-ibm-linux-gnu -ldl && %libomptarget-run-powerpc64-ibm-linux-gnu %t.so 2>&1 | %fcheck-powerpc64-ibm-linux-gnu
|
||||||
|
// RUN: %libomptarget-compile-powerpc64le-ibm-linux-gnu -DSHARED -shared -o %t.so && %clang %flags %s -o %t-powerpc64le-ibm-linux-gnu -ldl && %libomptarget-run-powerpc64le-ibm-linux-gnu %t.so 2>&1 | %fcheck-powerpc64le-ibm-linux-gnu
|
||||||
|
// RUN: %libomptarget-compile-x86_64-pc-linux-gnu -DSHARED -shared -o %t.so && %clang %flags %s -o %t-x86_64-pc-linux-gnu -ldl && %libomptarget-run-x86_64-pc-linux-gnu %t.so 2>&1 | %fcheck-x86_64-pc-linux-gnu
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
#include <stdio.h>
|
||||||
|
int foo() {
|
||||||
|
#pragma omp target
|
||||||
|
;
|
||||||
|
printf("%s\n", "DONE.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
void *Handle = dlopen(argv[1], RTLD_NOW);
|
||||||
|
int (*Foo)(void);
|
||||||
|
|
||||||
|
if (Handle == NULL) {
|
||||||
|
printf("dlopen() failed: %s\n", dlerror());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Foo = (int (*)(void)) dlsym(Handle, "foo");
|
||||||
|
if (Handle == NULL) {
|
||||||
|
printf("dlsym() failed: %s\n", dlerror());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// CHECK: DONE.
|
||||||
|
// CHECK-NOT: {{abort|fault}}
|
||||||
|
return Foo();
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue