|
|
@ -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<CacheData> 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<CacheData> 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::CacheData> dsacache::Cache::Access(uint8_t* data, const size_t size) { |
|
|
|
inline std::unique_ptr<dsacache::CacheData> 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::CacheData> 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<CacheData> task = GetFromCache(data, size, dst_node); |
|
|
@ -360,6 +364,22 @@ inline std::unique_ptr<dsacache::CacheData> dsacache::Cache::Access(uint8_t* dat |
|
|
|
task = std::make_unique<CacheData>(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]; |
|
|
|
|
|
|
|