SWDEV-495987 - Use shared mutex for MemObj maps

- Remove binning logic, although useful it doesnt work in current
  scenario as there is no upper limit on the size of allocation. If an
app or framework uses entire VRAM and then creates suballocs, binning
would result in failure.

Change-Id: Icc27c13e433bb4a1f03e82028d8718488b43bfa5
Αυτή η υποβολή περιλαμβάνεται σε:
Saleel Kudchadker
2024-11-12 17:25:09 +00:00
υποβλήθηκε από Rakesh Roy
γονέας 0fa632c52c
υποβολή e4d29e228d
2 αρχεία άλλαξαν με 40 προσθήκες και 58 διαγραφές
+35 -44
Προβολή Αρχείου
@@ -305,13 +305,13 @@ Context* Device::glb_ctx_ = nullptr;
Monitor Device::p2p_stage_ops_(true);
Memory* Device::p2p_stage_ = nullptr;
std::array<MemObjMap::Bin, MemObjMap::kNumBins> MemObjMap::MemObjBin_ ROCCLR_INIT_PRIORITY(101) = {} ;
std::array<MemObjMap::Bin, MemObjMap::kNumBins> MemObjMap::VirtualMemObjBin_ ROCCLR_INIT_PRIORITY(101) = {} ;
std::shared_mutex MemObjMap::AllocatedLock_ ROCCLR_INIT_PRIORITY(101);
std::map<uintptr_t, amd::Memory*> MemObjMap::MemObjMap_ ROCCLR_INIT_PRIORITY(101);
std::map<uintptr_t, amd::Memory*> MemObjMap::VirtualMemObjMap_ ROCCLR_INIT_PRIORITY(101);
void MemObjMap::AddMemObj(const void* k, amd::Memory* v) {
auto& bin = getMapBin(k, MemObjBin_);
std::unique_lock lock(bin.AllocatedLock_);
auto rval = bin.map_.insert({ reinterpret_cast<uintptr_t>(k), v });
std::unique_lock lock(AllocatedLock_);
auto rval = MemObjMap_.insert({ reinterpret_cast<uintptr_t>(k), v });
if (!rval.second) {
DevLogPrintfError("Memobj map already has an entry for ptr: 0x%x",
reinterpret_cast<uintptr_t>(k));
@@ -319,19 +319,17 @@ void MemObjMap::AddMemObj(const void* k, amd::Memory* v) {
}
void MemObjMap::RemoveMemObj(const void* k) {
auto& bin = getMapBin(k, MemObjBin_);
std::unique_lock lock(bin.AllocatedLock_);
auto rval = bin.map_.erase(reinterpret_cast<uintptr_t>(k));
std::unique_lock lock(AllocatedLock_);
auto rval = MemObjMap_.erase(reinterpret_cast<uintptr_t>(k));
guarantee(rval == 1, "Memobj map does not have ptr: 0x%x",
reinterpret_cast<uintptr_t>(k));
}
amd::Memory* MemObjMap::FindMemObj(const void* k, size_t* offset) {
auto& bin = getMapBin(k, MemObjBin_);
std::shared_lock lock(bin.AllocatedLock_);
std::shared_lock lock(AllocatedLock_);
uintptr_t key = reinterpret_cast<uintptr_t>(k);
auto it = bin.map_.upper_bound(key);
if (it == bin.map_.begin()) {
auto it = MemObjMap_.upper_bound(key);
if (it == MemObjMap_.begin()) {
return nullptr;
}
@@ -354,16 +352,14 @@ void MemObjMap::UpdateAccess(amd::Device *peerDev) {
}
// Provides access to all memory allocated on peerDev but
// hsa_amd_agents_allow_access was not called because there was no peer
for (auto& bin : MemObjBin_) {
std::shared_lock lock(bin.AllocatedLock_);
for (auto it : bin.map_) {
const std::vector<Device*>& devices = it.second->getContext().devices();
if (devices.size() == 1 && devices[0] == peerDev) {
device::Memory* devMem = it.second->getDeviceMemory(*devices[0]);
if (!devMem->getAllowedPeerAccess()) {
peerDev->deviceAllowAccess(reinterpret_cast<void*>(it.first));
devMem->setAllowedPeerAccess(true);
}
std::shared_lock lock(AllocatedLock_);
for (auto it : MemObjMap_) {
const std::vector<Device*>& devices = it.second->getContext().devices();
if (devices.size() == 1 && devices[0] == peerDev) {
device::Memory* devMem = it.second->getDeviceMemory(*devices[0]);
if (!devMem->getAllowedPeerAccess()) {
peerDev->deviceAllowAccess(reinterpret_cast<void*>(it.first));
devMem->setAllowedPeerAccess(true);
}
}
}
@@ -371,26 +367,23 @@ void MemObjMap::UpdateAccess(amd::Device *peerDev) {
void MemObjMap::Purge(amd::Device* dev) {
assert(dev != nullptr);
for (auto& bin : MemObjBin_) {
std::unique_lock lock(bin.AllocatedLock_);
for (auto it = bin.map_.cbegin(); it != bin.map_.cend(); ) {
amd::Memory* memObj = it->second;
unsigned int flags = memObj->getMemFlags();
const std::vector<Device*>& devices = memObj->getContext().devices();
if (devices.size() == 1 && devices[0] == dev && !(flags & ROCCLR_MEM_INTERNAL_MEMORY)) {
memObj->release();
it = bin.map_.erase(it);
} else {
++it;
}
std::unique_lock lock(AllocatedLock_);
for (auto it = MemObjMap_.cbegin(); it != MemObjMap_.cend(); ) {
amd::Memory* memObj = it->second;
unsigned int flags = memObj->getMemFlags();
const std::vector<Device*>& devices = memObj->getContext().devices();
if (devices.size() == 1 && devices[0] == dev && !(flags & ROCCLR_MEM_INTERNAL_MEMORY)) {
memObj->release();
it = MemObjMap_.erase(it);
} else {
++it;
}
}
}
void MemObjMap::AddVirtualMemObj(const void* k, amd::Memory* v) {
auto& bin = getMapBin(k, VirtualMemObjBin_);
std::unique_lock lock(bin.AllocatedLock_);
auto rval = bin.map_.insert({ reinterpret_cast<uintptr_t>(k), v });
std::unique_lock lock(AllocatedLock_);
auto rval = VirtualMemObjMap_.insert({ reinterpret_cast<uintptr_t>(k), v });
if (!rval.second) {
DevLogPrintfError("Virtual Memobj map already has an entry for ptr: 0x%x",
reinterpret_cast<uintptr_t>(k));
@@ -398,19 +391,17 @@ void MemObjMap::AddVirtualMemObj(const void* k, amd::Memory* v) {
}
void MemObjMap::RemoveVirtualMemObj(const void* k) {
auto& bin = getMapBin(k, VirtualMemObjBin_);
std::unique_lock lock(bin.AllocatedLock_);
auto rval = bin.map_.erase(reinterpret_cast<uintptr_t>(k));
std::unique_lock lock(AllocatedLock_);
auto rval = VirtualMemObjMap_.erase(reinterpret_cast<uintptr_t>(k));
guarantee(rval == 1, "Virtual Memobj map does not have ptr: 0x%x",
reinterpret_cast<uintptr_t>(k));
}
amd::Memory* MemObjMap::FindVirtualMemObj(const void* k) {
auto& bin = getMapBin(k, VirtualMemObjBin_);
std::shared_lock lock(bin.AllocatedLock_);
std::shared_lock lock(AllocatedLock_);
uintptr_t key = reinterpret_cast<uintptr_t>(k);
auto it = bin.map_.upper_bound(key);
if (it == bin.map_.begin()) {
auto it = VirtualMemObjMap_.upper_bound(key);
if (it == VirtualMemObjMap_.begin()) {
return nullptr;
}
+5 -14
Προβολή Αρχείου
@@ -58,7 +58,6 @@
#include <unordered_set>
#include <utility>
#include <shared_mutex>
#include <array>
namespace amd {
class Command;
@@ -1380,22 +1379,14 @@ class MemObjMap : public AllStatic {
static void RemoveVirtualMemObj(const void* k);
//!< Same as FindMemObj but for virtual addressing
static amd::Memory* FindVirtualMemObj(const void* k);
struct Bin {
std::shared_mutex AllocatedLock_;
std::map<uintptr_t, amd::Memory*> map_;
};
static constexpr size_t kNumBins = 16;
private:
//!< the mem object<->hostptr information container
static std::array<Bin, kNumBins> MemObjBin_;
static std::map<uintptr_t, amd::Memory*> MemObjMap_;
//!< the virtual mem object<->hostptr information container
static std::array<Bin, kNumBins> VirtualMemObjBin_;
static Bin& getMapBin(const void* k, std::array<Bin, kNumBins>& bin) {
size_t index = std::hash<const void*>{}(k) % kNumBins;
return bin.at(index);
}
static std::map<uintptr_t, amd::Memory*> VirtualMemObjMap_;
//!< Shared read/write lock
static std::shared_mutex AllocatedLock_;
};
/// @brief Instruction Set Architecture properties.