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
Αυτή η υποβολή περιλαμβάνεται σε:
υποβλήθηκε από
Rakesh Roy
γονέας
0fa632c52c
υποβολή
e4d29e228d
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Αναφορά σε νέο ζήτημα
Block a user