1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/common/lib/memory_manager.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

246 lines
7.2 KiB
C++
Raw Normal View History

2018-08-21 00:25:44 +02:00
/** Memory managment.
*
* @author Daniel Krebs <github@daniel-krebs.net>
2022-03-15 09:05:42 -04:00
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
2022-05-19 17:40:10 +02:00
* @license Apache License 2.0
2018-08-21 00:25:44 +02:00
*********************************************************************************/
#include <memory>
#include <limits>
#include <cstdint>
#include <villas/exceptions.hpp>
2018-08-21 00:25:44 +02:00
#include <villas/utils.hpp>
#include <villas/memory_manager.hpp>
using namespace villas;
2018-08-21 00:25:44 +02:00
using namespace villas::utils;
namespace villas {
MemoryManager*
MemoryManager::instance = nullptr;
MemoryManager&
MemoryManager::get()
{
2020-06-11 18:33:34 +02:00
if (instance == nullptr) {
2018-08-21 00:25:44 +02:00
instance = new MemoryManager;
if (!instance)
throw MemoryAllocationError();
2018-08-21 00:25:44 +02:00
}
return *instance;
}
MemoryManager::AddressSpaceId
MemoryManager::getOrCreateAddressSpace(std::string name)
{
try {
// Try fast lookup
2018-08-21 00:25:44 +02:00
return addrSpaceLookup.at(name);
} catch (const std::out_of_range&) {
// Does not yet exist, create
2018-08-21 00:25:44 +02:00
std::shared_ptr<AddressSpace> addrSpace(new AddressSpace);
addrSpace->name = name;
// Cache it for the next access
2018-08-21 00:25:44 +02:00
addrSpaceLookup[name] = memoryGraph.addVertex(addrSpace);
return addrSpaceLookup[name];
}
}
MemoryManager::MappingId
MemoryManager::createMapping(uintptr_t src, uintptr_t dest, size_t size,
2020-06-14 21:53:18 +02:00
const std::string &name,
2018-08-21 00:25:44 +02:00
MemoryManager::AddressSpaceId fromAddrSpace,
MemoryManager::AddressSpaceId toAddrSpace)
{
std::shared_ptr<Mapping> mapping(new Mapping);
mapping->name = name;
mapping->src = src;
mapping->dest = dest;
mapping->size = size;
return addMapping(mapping, fromAddrSpace, toAddrSpace);
}
MemoryManager::MappingId
MemoryManager::addMapping(std::shared_ptr<Mapping> mapping,
MemoryManager::AddressSpaceId fromAddrSpace,
MemoryManager::AddressSpaceId toAddrSpace)
{
return memoryGraph.addEdge(mapping, fromAddrSpace, toAddrSpace);
}
MemoryManager::AddressSpaceId
2020-06-14 21:53:18 +02:00
MemoryManager::findAddressSpace(const std::string &name)
2018-08-21 00:25:44 +02:00
{
return memoryGraph.findVertex(
[&](const std::shared_ptr<AddressSpace>& v) {
return v->name == name;
});
}
std::list<MemoryManager::AddressSpaceId>
2022-10-21 09:09:39 +00:00
MemoryManager::findPath(const MemoryManager::AddressSpaceId &fromAddrSpaceId,
const MemoryManager::AddressSpaceId &toAddrSpaceId)
2018-08-21 00:25:44 +02:00
{
std::list<AddressSpaceId> path;
auto fromAddrSpace = memoryGraph.getVertex(fromAddrSpaceId);
auto toAddrSpace = memoryGraph.getVertex(toAddrSpaceId);
// Find a path through the memory graph
2018-08-21 00:25:44 +02:00
MemoryGraph::Path pathGraph;
2020-06-11 18:33:34 +02:00
if (not memoryGraph.getPath(fromAddrSpaceId, toAddrSpaceId, pathGraph, pathCheckFunc)) {
2018-08-21 00:25:44 +02:00
logger->debug("No translation found from ({}) to ({})",
*fromAddrSpace, *toAddrSpace);
throw std::out_of_range("no translation found");
}
2020-06-14 21:53:18 +02:00
for (auto &mappingId : pathGraph) {
2018-08-21 00:25:44 +02:00
auto mapping = memoryGraph.getEdge(mappingId);
path.push_back(mapping->getVertexTo());
}
return path;
}
MemoryTranslation
2022-10-21 09:09:39 +00:00
MemoryManager::getTranslation(const MemoryManager::AddressSpaceId &fromAddrSpaceId,
const MemoryManager::AddressSpaceId &toAddrSpaceId)
2018-08-21 00:25:44 +02:00
{
2022-08-30 12:17:39 -04:00
// Find a path through the memory graph
2018-08-21 00:25:44 +02:00
MemoryGraph::Path path;
2020-06-11 18:33:34 +02:00
if (not memoryGraph.getPath(fromAddrSpaceId, toAddrSpaceId, path, pathCheckFunc)) {
2018-08-21 00:25:44 +02:00
auto fromAddrSpace = memoryGraph.getVertex(fromAddrSpaceId);
auto toAddrSpace = memoryGraph.getVertex(toAddrSpaceId);
logger->debug("No translation found from ({}) to ({})",
*fromAddrSpace, *toAddrSpace);
throw std::out_of_range("no translation found");
}
2022-08-30 12:17:39 -04:00
// Start with an identity mapping
2018-08-21 00:25:44 +02:00
MemoryTranslation translation(0, 0, SIZE_MAX);
2022-08-30 12:17:39 -04:00
// Iterate through path and merge all mappings into a single translation
2020-06-14 21:53:18 +02:00
for (auto &mappingId : path) {
2018-08-21 00:25:44 +02:00
auto mapping = memoryGraph.getEdge(mappingId);
translation += getTranslationFromMapping(*mapping);
}
return translation;
}
bool
2020-06-14 21:53:18 +02:00
MemoryManager::pathCheck(const MemoryGraph::Path &path)
2018-08-21 00:25:44 +02:00
{
2022-08-30 12:17:39 -04:00
// Start with an identity mapping
2018-08-21 00:25:44 +02:00
MemoryTranslation translation(0, 0, SIZE_MAX);
// Try to add all mappings together to a common translation. If this fails
// there is a non-overlapping window.
2020-06-14 21:53:18 +02:00
for (auto &mappingId : path) {
2018-08-21 00:25:44 +02:00
auto mapping = memoryGraph.getEdge(mappingId);
try {
translation += getTranslationFromMapping(*mapping);
2020-07-27 16:40:48 +02:00
} catch (const InvalidTranslation&) {
2018-08-21 00:25:44 +02:00
return false;
}
}
return true;
}
uintptr_t
MemoryTranslation::getLocalAddr(uintptr_t addrInForeignAddrSpace) const
{
assert(addrInForeignAddrSpace >= dst);
assert(addrInForeignAddrSpace < (dst + size));
return src + addrInForeignAddrSpace - dst;
}
uintptr_t
MemoryTranslation::getForeignAddr(uintptr_t addrInLocalAddrSpace) const
{
assert(addrInLocalAddrSpace >= src);
assert(addrInLocalAddrSpace < (src + size));
return dst + addrInLocalAddrSpace - src;
}
MemoryTranslation&
2020-06-14 21:53:18 +02:00
MemoryTranslation::operator+=(const MemoryTranslation &other)
2018-08-21 00:25:44 +02:00
{
2018-11-30 21:43:37 +01:00
Logger logger = logging.get("MemoryTranslation");
2019-01-21 16:32:42 +01:00
// Set level to debug to enable debug output
2018-08-21 00:25:44 +02:00
logger->set_level(spdlog::level::info);
const uintptr_t this_dst_high = this->dst + this->size;
const uintptr_t other_src_high = other.src + other.size;
logger->debug("this->src: {:#x}", this->src);
logger->debug("this->dst: {:#x}", this->dst);
logger->debug("this->size: {:#x}", this->size);
logger->debug("other.src: {:#x}", other.src);
logger->debug("other.dst: {:#x}", other.dst);
logger->debug("other.size: {:#x}", other.size);
logger->debug("this_dst_high: {:#x}", this_dst_high);
logger->debug("other_src_high: {:#x}", other_src_high);
// Make sure there is a common memory area
2018-08-21 00:25:44 +02:00
assertExcept(other.src < this_dst_high, MemoryManager::InvalidTranslation());
assertExcept(this->dst < other_src_high, MemoryManager::InvalidTranslation());
const uintptr_t hi = std::max(this_dst_high, other_src_high);
const uintptr_t lo = std::min(this->dst, other.src);
const uintptr_t diff_hi = (this_dst_high > other_src_high)
? (this_dst_high - other_src_high)
: (other_src_high - this_dst_high);
const bool otherSrcIsSmaller = this->dst > other.src;
const uintptr_t diff_lo = (otherSrcIsSmaller)
? (this->dst - other.src)
: (other.src - this->dst);
logger->debug("hi: {:#x}", hi);
logger->debug("lo: {:#x}", lo);
logger->debug("diff_hi: {:#x}", diff_hi);
logger->debug("diff_lo: {:#x}", diff_lo);
// New size of aperture, can only stay or shrink
2018-08-21 00:25:44 +02:00
this->size = (hi - lo) - diff_hi - diff_lo;
// New translation will come out other's destination (by default)
2018-08-21 00:25:44 +02:00
this->dst = other.dst;
// The source stays the same and can only increase with merged translations
2018-10-19 16:32:44 +02:00
//this->src = this->src;
2018-08-21 00:25:44 +02:00
2020-06-15 21:05:51 +02:00
if (otherSrcIsSmaller)
// Other mapping starts at lower addresses, so we actually arrive at
// higher addresses
2018-08-21 00:25:44 +02:00
this->dst += diff_lo;
2020-06-15 21:05:51 +02:00
else
// Other mapping starts at higher addresses than this, so we have to
// increase the start
// NOTE: for addresses equality, this just adds 0
2018-08-21 00:25:44 +02:00
this->src += diff_lo;
logger->debug("result src: {:#x}", this->src);
logger->debug("result dst: {:#x}", this->dst);
logger->debug("result size: {:#x}", this->size);
return *this;
}
} // namespace villas