summaryrefslogtreecommitdiff
path: root/view/sharedcache/core
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-04-14 17:17:42 -0400
committerMason Reed <mason@vector35.com>2025-04-14 20:45:14 -0400
commit8c3bd6e14eafe4b1d0af509c7abc7e6bd9a97c15 (patch)
treef977f4191e9ef94e02c809f52734940da32da247 /view/sharedcache/core
parent9b7b429106f16b5704cf27baf9f3d69ff4a0857a (diff)
[SharedCache] Evict file accessors from the global file accessor cache on file metadata destruction
Previously we would just let them continue to exist after view destruction, this is fine assuming we expect the user to be re-opening the same cache over and over, but if a user wants to load a bunch of different caches they might want to evict the old file accessors so that COW pages are known to be evicted, along with other paged in memory.
Diffstat (limited to 'view/sharedcache/core')
-rw-r--r--view/sharedcache/core/FileAccessorCache.cpp8
-rw-r--r--view/sharedcache/core/FileAccessorCache.h4
-rw-r--r--view/sharedcache/core/SharedCacheController.cpp46
-rw-r--r--view/sharedcache/core/SharedCacheController.h2
-rw-r--r--view/sharedcache/core/SharedCacheView.cpp3
5 files changed, 41 insertions, 22 deletions
diff --git a/view/sharedcache/core/FileAccessorCache.cpp b/view/sharedcache/core/FileAccessorCache.cpp
index 5fa965b3..28aab15d 100644
--- a/view/sharedcache/core/FileAccessorCache.cpp
+++ b/view/sharedcache/core/FileAccessorCache.cpp
@@ -68,6 +68,12 @@ WeakFileAccessor FileAccessorCache::Open(const std::string& filePath)
return WeakFileAccessor(sharedAccessor, filePath);
}
+void FileAccessorCache::RemoveAccessor(const CacheAccessorID id)
+{
+ std::unique_lock lock(m_mutex);
+ m_accessors.erase(id);
+}
+
std::shared_ptr<MappedFileAccessor> WeakFileAccessor::lock()
{
auto sharedPtr = m_weakPtr.lock();
@@ -86,4 +92,4 @@ std::shared_ptr<MappedFileAccessor> WeakFileAccessor::lock()
}
return sharedPtr;
-} \ No newline at end of file
+}
diff --git a/view/sharedcache/core/FileAccessorCache.h b/view/sharedcache/core/FileAccessorCache.h
index 811aea78..46de6fcc 100644
--- a/view/sharedcache/core/FileAccessorCache.h
+++ b/view/sharedcache/core/FileAccessorCache.h
@@ -34,12 +34,16 @@ public:
// accessor and inserting itself back into its related cache.
WeakFileAccessor Open(const std::string& filePath);
+ void RemoveAccessor(CacheAccessorID id);
+
// Adjust the cache size limit.
// This will NOT evict current cache entries, as they are already available.
// Any subsequent call to `Open` will assume this cache size, evicting until the size is equal to the cache size.
void SetCacheSize(const uint64_t size) { m_cacheSize = size; };
size_t GetCacheSize() const { return m_cacheSize; }
+
+ size_t GetCacheCount() const { return m_accessors.size(); }
};
class WeakFileAccessor
diff --git a/view/sharedcache/core/SharedCacheController.cpp b/view/sharedcache/core/SharedCacheController.cpp
index e0cd036f..6e275b4b 100644
--- a/view/sharedcache/core/SharedCacheController.cpp
+++ b/view/sharedcache/core/SharedCacheController.cpp
@@ -13,39 +13,49 @@ std::shared_mutex GlobalControllersMutex;
std::map<ViewId, DSCRef<SharedCacheController>>& GlobalControllers()
{
// To make initialization order consistent we place the static in a function.
- static std::map<ViewId, DSCRef<SharedCacheController>> g_dscViews = {};
- return g_dscViews;
+ static std::map<ViewId, DSCRef<SharedCacheController>> g_controllers = {};
+ return g_controllers;
}
-ViewId GetViewIdFromView(BinaryView& view)
+ViewId GetViewIdFromFileMetadata(const FileMetadata& file)
{
// Currently the view id is just the views session id.
// NOTE: If we want more than one shared cache controller per view we would need to make this more unique.
- return view.GetFile()->GetSessionId();
+ return file.GetSessionId();
}
-void DeleteController(BinaryView& view)
+void DeleteController(const FileMetadata& file)
{
- const auto id = GetViewIdFromView(view);
+ const auto id = GetViewIdFromFileMetadata(file);
std::unique_lock<std::shared_mutex> lock(GlobalControllersMutex);
- auto& dscViews = GlobalControllers();
- if (auto it = dscViews.find(id); it != dscViews.end())
+ auto& controllers = GlobalControllers();
+ if (auto it = controllers.find(id); it != controllers.end())
{
+ auto controller = it->second;
// Someone is still holding the controller, lets warn about this.
- if (it->second->m_refs > 1)
+ if (controller->m_refs > 1)
LogWarn("Deleting SharedCacheController for view %llx, but there are still %d references", id,
- it->second->m_refs.load());
- dscViews.erase(it);
- LogDebug("Deleted SharedCacheController for view %s", view.GetFile()->GetFilename().c_str());
+ controller->m_refs.load());
+
+ // Go through the file accessor cache and remove the entries we reference.
+ auto& fileAccessorCache = FileAccessorCache::Global();
+ for (const auto& entry : controller->GetCache().GetEntries())
+ {
+ auto accessorId = GetCacheAccessorID(entry.GetFilePath());
+ fileAccessorCache.RemoveAccessor(accessorId);
+ }
+
+ controllers.erase(it);
+ LogDebug("Deleted SharedCacheController for view %s", file.GetFilename().c_str());
}
}
void RegisterSharedCacheControllerDestructor()
{
BNObjectDestructionCallbacks callbacks = {};
- callbacks.destructBinaryView = [](void* ctx, BNBinaryView* obj) -> void {
- auto view = BinaryView(obj);
- DeleteController(view);
+ callbacks.destructFileMetadata = [](void* ctx, BNFileMetadata* obj) -> void {
+ const auto file = FileMetadata(obj);
+ DeleteController(file);
};
BNRegisterObjectDestructionCallbacks(&callbacks);
}
@@ -63,7 +73,7 @@ SharedCacheController::SharedCacheController(SharedCache&& cache, Ref<Logger> lo
DSCRef<SharedCacheController> SharedCacheController::Initialize(BinaryView& view, SharedCache&& cache)
{
- auto id = GetViewIdFromView(view);
+ auto id = GetViewIdFromFileMetadata(*view.GetFile());
std::unique_lock<std::shared_mutex> lock(GlobalControllersMutex);
auto logger = new Logger("SharedCache.Controller", view.GetFile()->GetSessionId());
DSCRef<SharedCacheController> controller = new SharedCacheController(std::move(cache), logger);
@@ -94,9 +104,9 @@ DSCRef<SharedCacheController> SharedCacheController::Initialize(BinaryView& view
return controller;
}
-DSCRef<SharedCacheController> SharedCacheController::FromView(BinaryView& view)
+DSCRef<SharedCacheController> SharedCacheController::FromView(const BinaryView& view)
{
- auto id = GetViewIdFromView(view);
+ auto id = GetViewIdFromFileMetadata(*view.GetFile());
std::shared_lock<std::shared_mutex> lock(GlobalControllersMutex);
auto& dscViews = GlobalControllers();
auto dscView = dscViews.find(id);
diff --git a/view/sharedcache/core/SharedCacheController.h b/view/sharedcache/core/SharedCacheController.h
index 3a6c76dc..cda3653c 100644
--- a/view/sharedcache/core/SharedCacheController.h
+++ b/view/sharedcache/core/SharedCacheController.h
@@ -42,7 +42,7 @@ namespace BinaryNinja::DSC {
static DSCRef<SharedCacheController> Initialize(BinaryView& view, SharedCache&& cache);
// NOTE: This will not create one if it does not exist. To create one for the view call `Initialize`.
- static DSCRef<SharedCacheController> FromView(BinaryView& view);
+ static DSCRef<SharedCacheController> FromView(const BinaryView& view);
SharedCache& GetCache() { return m_cache; };
const std::unordered_set<uint64_t>& GetLoadedRegions() { return m_loadedRegions; };
diff --git a/view/sharedcache/core/SharedCacheView.cpp b/view/sharedcache/core/SharedCacheView.cpp
index 4218a2fe..0cd4d82e 100644
--- a/view/sharedcache/core/SharedCacheView.cpp
+++ b/view/sharedcache/core/SharedCacheView.cpp
@@ -20,8 +20,7 @@ void SharedCacheViewType::Register()
// Adjust the global accessor cache to the fdlimit.
FileAccessorCache::Global().SetCacheSize(fdLimit);
-
- // TODO: Register object destructor to clear accessor cache
+
RegisterSharedCacheControllerDestructor();
static SharedCacheViewType type;