diff --git a/offloading-cacher/cache.hpp b/offloading-cacher/cache.hpp index c96c468..2980a28 100644 --- a/offloading-cacher/cache.hpp +++ b/offloading-cacher/cache.hpp @@ -51,6 +51,8 @@ namespace dsacache { constexpr uint64_t FLAG_WAIT_WEAK = 0b1ULL << 63; constexpr uint64_t FLAG_HANDLE_PF = 0b1ULL << 62; + constexpr uint64_t FLAG_ACCESS_WEAK = 0b1ULL << 61; + constexpr uint64_t FLAG_DEFAULT = 0ULL; class Cache; @@ -121,6 +123,7 @@ namespace dsacache { uint8_t* GetSource() const { return src_; } int32_t GetRefCount() const { return active_->load(); } void SetTaskHandlerAndCache(uint8_t* cache, dml_handler* handler); + void SetCacheToSource() { cache_->store(src_); delete_ = false; } // initializes the class after which it is thread safe // but may only be destroyed safely after setting handlers @@ -277,8 +280,13 @@ namespace dsacache { // only after this is it safe to use in a threaded environment void Init(CachePolicy* cache_policy_function, CopyPolicy* copy_policy_function); - // function to perform data access through the cache - std::unique_ptr Access(uint8_t* data, const size_t size); + // function to perform data access through the cache, behaviour depends + // on flags, by default will also perform prefetch, otherwise with + // FLAG_ACCESS_WEAK set will not perform prefetch and instead return + // a cache entry with the data source as cache location on cache miss, + // this flag must be set for each invocation, the flags set for the + // entire cache will not be evaluated for this + std::unique_ptr Access(uint8_t* data, const size_t size, const uint64_t flags = FLAG_DEFAULT); // flushes the cache of inactive entries // if node is -1 then the whole cache is @@ -334,7 +342,7 @@ inline void dsacache::Cache::Init(CachePolicy* cache_policy_function, CopyPolicy } } -inline std::unique_ptr dsacache::Cache::Access(uint8_t* data, const size_t size) { +inline std::unique_ptr dsacache::Cache::Access(uint8_t* data, const size_t size, const uint64_t flags) { // get destination numa node for the cache int dst_node = -1; @@ -342,10 +350,6 @@ inline std::unique_ptr dsacache::Cache::Access(uint8_t* dat GetCacheNode(data, size, &dst_node, &src_node); - // TODO: at this point it could be beneficial to check whether - // TODO: the given destination node is present as an entry - // TODO: in the cache state to see if it is valid - // check whether the data is already cached std::unique_ptr task = GetFromCache(data, size, dst_node); @@ -360,6 +364,22 @@ inline std::unique_ptr dsacache::Cache::Access(uint8_t* dat task = std::make_unique(data, size); task->SetFlags(flags_); + // when the ACCESS_WEAK flag is set for the flags parameter (!) + // and we have reached this point, there was no cache entry + // present for the requested data and therefore we abort + // but to keep validity, we return the previously created + // CacheData struct, setting the cache variable to the + // data source location + + if (CheckFlag(flags, FLAG_ACCESS_WEAK)) { + std::cerr << "[!] CacheAccess with WEAK set encountered miss!" << std::endl; + task->SetCacheToSource(); + return std::move(task); + } + + // the following operation adds the task to the cache state + // which requires unique locking of the current nodes entry + { LockedNodeCacheState* local_cache_state = cache_state_[dst_node];