mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
common/memory: add check-callback to getPath() to select desired path
This is a workaround until we have a better heuristic (maybe shortest path?) to choose between multiple paths in the graph. Since the (abstract) graph has no idea about memory translations, getPath() may even yield paths that are no valid translation because a pair of inbound/outbound edges must not neccessarily share a common address window, but from the perspective of the abstract graph present a valid path. The callback function is used by the MemoryManager to verify if a path candidate represents a valid translation.
This commit is contained in:
parent
29709aed7a
commit
105f47d2d0
4 changed files with 60 additions and 6 deletions
|
@ -212,9 +212,17 @@ public:
|
|||
vertexGetEdges(VertexIdentifier vertexId) const
|
||||
{ return getVertex(vertexId)->edges; }
|
||||
|
||||
|
||||
using check_path_fn = std::function<bool(const Path&)>;
|
||||
|
||||
static bool
|
||||
checkPath(const Path&)
|
||||
{ return true; }
|
||||
|
||||
bool getPath(VertexIdentifier fromVertexId,
|
||||
VertexIdentifier toVertexId,
|
||||
Path& path)
|
||||
Path& path,
|
||||
check_path_fn pathCheckFunc = checkPath)
|
||||
{
|
||||
if(fromVertexId == toVertexId) {
|
||||
// arrived at the destination
|
||||
|
@ -244,7 +252,8 @@ public:
|
|||
path.push_back(edgeId);
|
||||
|
||||
// recursive, depth-first search
|
||||
if(getPath(edgeOfFromVertex->to, toVertexId, path)) {
|
||||
if(getPath(edgeOfFromVertex->to, toVertexId, path, pathCheckFunc) and
|
||||
pathCheckFunc(path)) {
|
||||
// path found, we're done
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log.hpp"
|
||||
|
@ -73,7 +74,12 @@ private:
|
|||
// This is a singleton, so private constructor ...
|
||||
MemoryManager() :
|
||||
memoryGraph("MemoryGraph"),
|
||||
logger(loggerGetOrCreate("MemoryManager")) {}
|
||||
logger(loggerGetOrCreate("MemoryManager"))
|
||||
{
|
||||
pathCheckFunc = [&](const MemoryGraph::Path& path) {
|
||||
return this->pathCheck(path);
|
||||
};
|
||||
}
|
||||
|
||||
// ... and no copying or assigning
|
||||
MemoryManager(const MemoryManager&) = delete;
|
||||
|
@ -144,6 +150,8 @@ public:
|
|||
using AddressSpaceId = MemoryGraph::VertexIdentifier;
|
||||
using MappingId = MemoryGraph::EdgeIdentifier;
|
||||
|
||||
struct InvalidTranslation : public std::exception {};
|
||||
|
||||
/// Get singleton instance
|
||||
static MemoryManager&
|
||||
get();
|
||||
|
@ -210,6 +218,8 @@ private:
|
|||
getTranslationFromMapping(const Mapping& mapping)
|
||||
{ return MemoryTranslation(mapping.src, mapping.dest, mapping.size); }
|
||||
|
||||
bool
|
||||
pathCheck(const MemoryGraph::Path& path);
|
||||
|
||||
private:
|
||||
/// Directed graph that stores address spaces and memory mappings
|
||||
|
@ -221,6 +231,8 @@ private:
|
|||
/// Logger for universal access in this class
|
||||
SpdLogger logger;
|
||||
|
||||
MemoryGraph::check_path_fn pathCheckFunc;
|
||||
|
||||
/// Static pointer to global instance, because this is a singleton
|
||||
static MemoryManager* instance;
|
||||
};
|
||||
|
|
|
@ -10,6 +10,15 @@ namespace utils {
|
|||
std::vector<std::string>
|
||||
tokenize(std::string s, std::string delimiter);
|
||||
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
assertExcept(bool condition, const T& exception)
|
||||
{
|
||||
if(not condition)
|
||||
throw exception;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace villas
|
||||
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
#include <limits>
|
||||
#include <cstdint>
|
||||
|
||||
#include <villas/utils.hpp>
|
||||
#include "memory_manager.hpp"
|
||||
|
||||
using namespace villas::utils;
|
||||
|
||||
namespace villas {
|
||||
|
||||
MemoryManager*
|
||||
|
@ -76,7 +79,8 @@ MemoryManager::getTranslation(MemoryManager::AddressSpaceId fromAddrSpaceId,
|
|||
{
|
||||
// find a path through the memory graph
|
||||
MemoryGraph::Path path;
|
||||
if(not memoryGraph.getPath(fromAddrSpaceId, toAddrSpaceId, path)) {
|
||||
if(not memoryGraph.getPath(fromAddrSpaceId, toAddrSpaceId, path, pathCheckFunc)) {
|
||||
|
||||
auto fromAddrSpace = memoryGraph.getVertex(fromAddrSpaceId);
|
||||
auto toAddrSpace = memoryGraph.getVertex(toAddrSpaceId);
|
||||
|
||||
|
@ -98,6 +102,26 @@ MemoryManager::getTranslation(MemoryManager::AddressSpaceId fromAddrSpaceId,
|
|||
return translation;
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryManager::pathCheck(const MemoryGraph::Path& path)
|
||||
{
|
||||
// start with an identity mapping
|
||||
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
|
||||
for(auto& mappingId : path) {
|
||||
auto mapping = memoryGraph.getEdge(mappingId);
|
||||
try {
|
||||
translation += getTranslationFromMapping(*mapping);
|
||||
} catch(const InvalidTranslation&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
MemoryTranslation::getLocalAddr(uintptr_t addrInForeignAddrSpace) const
|
||||
{
|
||||
|
@ -125,8 +149,8 @@ MemoryTranslation::operator+=(const MemoryTranslation& other)
|
|||
const uintptr_t other_src_high = other.src + other.size;
|
||||
|
||||
// make sure there is a common memory area
|
||||
assert(other.src < this_dst_high);
|
||||
assert(this->dst < other_src_high);
|
||||
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);
|
||||
|
|
Loading…
Add table
Reference in a new issue