Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/plugin_v2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ The plugin implements these required hook functions:
- `cache_miss_hook()` - Handle cache misses (insert new object)
- `cache_eviction_hook()` - Evict least recently used object and return its ID
- `cache_remove_hook()` - Remove specific object from cache
- `cache_free_hook()` - Clean up and free the LRU cache data structure

## Usage

Expand Down
9 changes: 8 additions & 1 deletion example/plugin_v2/plugin_lru.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,11 @@ void cache_remove_hook(void *data, const obj_id_t obj_id) {
lru_cache->cache_remove(obj_id);
}

} // extern "C"
// implement the cache free hook
void cache_free_hook(void *data) {
// free the LRU cache (destructor handles all cleanup)
StandaloneLRU *lru_cache = (StandaloneLRU *)data;
delete lru_cache;
}

} // extern "C"
23 changes: 23 additions & 0 deletions libCacheSim/cache/eviction/plugin_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* - cache_miss_hook: Handle cache miss events
* - cache_eviction_hook: Determine which object to evict
* - cache_remove_hook: Clean up when objects are removed
* - cache_free_hook: Free plugin resources
*
* The plugin cache delegates core cache operations to these hooks, enabling
* flexible and extensible cache policies.
Expand Down Expand Up @@ -46,12 +47,14 @@ extern "C" {
*/
typedef struct pluginCache_params {
char *plugin_path; ///< Path to the plugin shared library
void *plugin_handle; ///< Handle to the loaded plugin library
void *data; ///< Plugin's internal data structure
cache_init_hook_t cache_init_hook; ///< Plugin initialization function
cache_hit_hook_t cache_hit_hook; ///< Cache hit handler function
cache_miss_hook_t cache_miss_hook; ///< Cache miss handler function
cache_eviction_hook_t cache_eviction_hook; ///< Eviction decision function
cache_remove_hook_t cache_remove_hook; ///< Object removal handler function
cache_free_hook_t cache_free_hook; ///< Cache cleanup function
char *cache_name;
} pluginCache_params_t;

Expand Down Expand Up @@ -137,6 +140,7 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
ERROR("Failed to load plugin %s: %s\n", params->plugin_path, dlerror());
exit(1);
}
params->plugin_handle = handle;

// Load hook functions from the plugin using unions to avoid pedantic warnings
union {
Expand All @@ -159,6 +163,10 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
void *obj;
cache_remove_hook_t func;
} cache_remove_u;
union {
void *obj;
cache_free_hook_t func;
} cache_free_u;

cache_init_u.obj = dlsym(handle, "cache_init_hook");
params->cache_init_hook = cache_init_u.func;
Expand All @@ -175,6 +183,9 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
cache_remove_u.obj = dlsym(handle, "cache_remove_hook");
params->cache_remove_hook = cache_remove_u.func;

cache_free_u.obj = dlsym(handle, "cache_free_hook");
Copy link

Copilot AI Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result of dlsym for cache_free_hook isn't checked; if the symbol load fails unexpectedly, you may call a garbage pointer. Add a NULL check or error log similar to other hooks.

Suggested change
cache_free_u.obj = dlsym(handle, "cache_free_hook");
cache_free_u.obj = dlsym(handle, "cache_free_hook");
if (cache_free_u.obj == NULL) {
fprintf(stderr, "Error: Failed to load symbol 'cache_free_hook'.\n");
return -1; // or appropriate error handling
}

Copilot uses AI. Check for mistakes.
params->cache_free_hook = cache_free_u.func;

// Initialize the plugin with cache parameters
params->data = params->cache_init_hook(ccache_params);

Expand Down Expand Up @@ -205,6 +216,10 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
*/
static void pluginCache_free(cache_t *cache) {
pluginCache_params_t *params = (pluginCache_params_t *)cache->eviction_params;

if (params->cache_free_hook != NULL) params->cache_free_hook(params->data);
if (params->plugin_handle != NULL)
dlclose(params->plugin_handle); // Close the plugin shared library handle
if (params->plugin_path != NULL) free(params->plugin_path);
if (params->cache_name != NULL) free(params->cache_name);
free(cache->eviction_params);
Expand Down Expand Up @@ -398,8 +413,16 @@ static void pluginCache_parse_params(cache_t *cache,

// Process recognized parameters
if (strcasecmp(key, "plugin") == 0 || strcasecmp(key, "plugin_path") == 0) {
// Validate plugin path is not empty
if (strlen(value) == 0) {
ERROR("Parameter 'plugin_path' cannot be empty in cache '%s'\n",
cache->cache_name);
exit(1);
}
if (params->plugin_path != NULL) free(params->plugin_path);
params->plugin_path = strdup(value);
} else if (strcasecmp(key, "cache_name") == 0) {
if (params->cache_name != NULL) free(params->cache_name);
params->cache_name = strdup(value);
} else if (strcasecmp(key, "print") == 0) {
printf("current parameters: plugin_path=%s\n", params->plugin_path);
Expand Down
11 changes: 11 additions & 0 deletions libCacheSim/include/libCacheSim/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ cache_t *create_cache_external(const char *const cache_alg_name,
* - cache_miss_hook: Handle cache miss events
* - cache_eviction_hook: Determine which object to evict
* - cache_remove_hook: Clean up when objects are removed
* - cache_free_hook: Free plugin resources
*
* @see example/plugin_v2/plugin_lru.c for a complete implementation example
* @{
Expand Down Expand Up @@ -186,6 +187,16 @@ typedef obj_id_t (*cache_eviction_hook_t)(void *data, const request_t *req);
*/
typedef void (*cache_remove_hook_t)(void *data, const obj_id_t obj_id);

/**
* @brief Cache free hook function type
*
* Cleanup function called when the cache is being destroyed.
* The plugin should free any resources allocated in cache_init_hook.
*
* @param data Pointer to plugin's internal data (from cache_init_hook)
*/
typedef void (*cache_free_hook_t)(void *data);

/** @} */ // end of v2_plugin_api group

#ifdef __cplusplus
Expand Down
Loading