-
Notifications
You must be signed in to change notification settings - Fork 35
Implement IPC cache for umfOpenIPCHandle function #736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
43c9cd7
Fix utils_atomic_load_acquire on Windows
vinser52 5364731
Add utils_atomic_decrement function
vinser52 0f72af2
Add uthash and utlist implemenation
vinser52 7278552
Use the UMF base allocator in UThash
vinser52 e574428
Enable IPC cache for Open/Close functions
vinser52 d46530a
Fix umfIpcTest.AllocFreeAllocTest test
vinser52 546632c
Enable umfIpcTest for OS provider with jemalloc
vinser52 d776bea
Suppress drd and helgrind false-positive in trackingOpenIpcHandle fun…
vinser52 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
/* | ||
* | ||
* Copyright (C) 2024 Intel Corporation | ||
* | ||
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. | ||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
* | ||
*/ | ||
|
||
#include <stdbool.h> | ||
|
||
#include "base_alloc_global.h" | ||
#include "ipc_cache.h" | ||
#include "uthash.h" | ||
#include "utils_common.h" | ||
#include "utils_concurrency.h" | ||
#include "utils_log.h" | ||
#include "utlist.h" | ||
|
||
struct ipc_handle_cache_entry_t; | ||
|
||
typedef struct ipc_handle_cache_entry_t *hash_map_t; | ||
typedef struct ipc_handle_cache_entry_t *lru_list_t; | ||
|
||
typedef struct ipc_handle_cache_entry_t { | ||
UT_hash_handle hh; | ||
struct ipc_handle_cache_entry_t *next, *prev; | ||
ipc_mapped_handle_cache_key_t key; | ||
uint64_t ref_count; | ||
lplewa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
uint64_t handle_id; | ||
hash_map_t | ||
*hash_table; // pointer to the hash table to which the entry belongs | ||
ipc_mapped_handle_cache_value_t value; | ||
} ipc_handle_cache_entry_t; | ||
|
||
typedef struct ipc_mapped_handle_cache_global_t { | ||
utils_mutex_t cache_lock; | ||
umf_ba_pool_t *cache_allocator; | ||
size_t max_size; | ||
size_t cur_size; | ||
lru_list_t lru_list; | ||
} ipc_mapped_handle_cache_global_t; | ||
|
||
typedef struct ipc_mapped_handle_cache_t { | ||
ipc_mapped_handle_cache_global_t *global; | ||
hash_map_t hash_table; | ||
ipc_mapped_handle_cache_eviction_cb_t eviction_cb; | ||
} ipc_mapped_handle_cache_t; | ||
|
||
ipc_mapped_handle_cache_global_t *IPC_MAPPED_CACHE_GLOBAL = NULL; | ||
|
||
umf_result_t umfIpcCacheGlobalInit(void) { | ||
umf_result_t ret = UMF_RESULT_SUCCESS; | ||
ipc_mapped_handle_cache_global_t *cache_global = | ||
umf_ba_global_alloc(sizeof(*cache_global)); | ||
if (!cache_global) { | ||
LOG_ERR("Failed to allocate memory for the IPC cache global data"); | ||
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; | ||
goto err_exit; | ||
} | ||
|
||
if (NULL == utils_mutex_init(&(cache_global->cache_lock))) { | ||
LOG_ERR("Failed to initialize mutex for the IPC global cache"); | ||
ret = UMF_RESULT_ERROR_UNKNOWN; | ||
goto err_cache_global_free; | ||
} | ||
|
||
cache_global->cache_allocator = | ||
umf_ba_create(sizeof(ipc_handle_cache_entry_t)); | ||
lplewa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!cache_global->cache_allocator) { | ||
LOG_ERR("Failed to create IPC cache allocator"); | ||
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; | ||
goto err_mutex_destroy; | ||
} | ||
|
||
// TODO: make max_size configurable via environment variable | ||
cache_global->max_size = 0; | ||
lplewa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
cache_global->cur_size = 0; | ||
cache_global->lru_list = NULL; | ||
|
||
IPC_MAPPED_CACHE_GLOBAL = cache_global; | ||
goto err_exit; | ||
|
||
err_mutex_destroy: | ||
utils_mutex_destroy_not_free(&(cache_global->cache_lock)); | ||
err_cache_global_free: | ||
umf_ba_global_free(cache_global); | ||
err_exit: | ||
return ret; | ||
} | ||
|
||
static size_t getGlobalLruListSize(lru_list_t lru_list) { | ||
size_t size = 0; | ||
ipc_handle_cache_entry_t *tmp; | ||
DL_COUNT(lru_list, tmp, size); | ||
return size; | ||
} | ||
|
||
void umfIpcCacheGlobalTearDown(void) { | ||
ipc_mapped_handle_cache_global_t *cache_global = IPC_MAPPED_CACHE_GLOBAL; | ||
IPC_MAPPED_CACHE_GLOBAL = NULL; | ||
|
||
if (!cache_global) { | ||
return; | ||
} | ||
|
||
assert(cache_global->cur_size == 0); | ||
assert(getGlobalLruListSize(cache_global->lru_list) == 0); | ||
|
||
umf_ba_destroy(cache_global->cache_allocator); | ||
utils_mutex_destroy_not_free(&(cache_global->cache_lock)); | ||
umf_ba_global_free(cache_global); | ||
} | ||
|
||
ipc_mapped_handle_cache_handle_t umfIpcHandleMappedCacheCreate( | ||
ipc_mapped_handle_cache_eviction_cb_t eviction_cb) { | ||
if (eviction_cb == NULL) { | ||
LOG_ERR("Eviction callback is NULL"); | ||
return NULL; | ||
} | ||
|
||
ipc_mapped_handle_cache_t *cache = umf_ba_global_alloc(sizeof(*cache)); | ||
|
||
if (!cache) { | ||
LOG_ERR("Failed to allocate memory for the IPC cache"); | ||
return NULL; | ||
bratpiorka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
assert(IPC_MAPPED_CACHE_GLOBAL != NULL); | ||
|
||
cache->global = IPC_MAPPED_CACHE_GLOBAL; | ||
cache->hash_table = NULL; | ||
cache->eviction_cb = eviction_cb; | ||
|
||
return cache; | ||
} | ||
|
||
void umfIpcHandleMappedCacheDestroy(ipc_mapped_handle_cache_handle_t cache) { | ||
ipc_handle_cache_entry_t *entry, *tmp; | ||
HASH_ITER(hh, cache->hash_table, entry, tmp) { | ||
DL_DELETE(cache->global->lru_list, entry); | ||
HASH_DEL(cache->hash_table, entry); | ||
cache->global->cur_size -= 1; | ||
cache->eviction_cb(&entry->key, &entry->value); | ||
utils_mutex_destroy_not_free(&(entry->value.mmap_lock)); | ||
umf_ba_free(cache->global->cache_allocator, entry); | ||
} | ||
HASH_CLEAR(hh, cache->hash_table); | ||
|
||
umf_ba_global_free(cache); | ||
} | ||
|
||
umf_result_t | ||
umfIpcHandleMappedCacheGet(ipc_mapped_handle_cache_handle_t cache, | ||
const ipc_mapped_handle_cache_key_t *key, | ||
uint64_t handle_id, | ||
ipc_mapped_handle_cache_value_t **retEntry) { | ||
ipc_handle_cache_entry_t *entry = NULL; | ||
umf_result_t ret = UMF_RESULT_SUCCESS; | ||
bool evicted = false; | ||
ipc_mapped_handle_cache_value_t evicted_value; | ||
|
||
if (!cache || !key || !retEntry) { | ||
LOG_ERR("Some arguments are NULL, cache=%p, key=%p, retEntry=%p", | ||
(void *)cache, (const void *)key, (void *)retEntry); | ||
lplewa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return UMF_RESULT_ERROR_INVALID_ARGUMENT; | ||
bratpiorka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
assert(cache->global != NULL); | ||
|
||
utils_mutex_lock(&(cache->global->cache_lock)); | ||
|
||
HASH_FIND(hh, cache->hash_table, key, sizeof(*key), entry); | ||
if (entry && entry->handle_id == handle_id) { // cache hit | ||
// update frequency list | ||
// remove the entry from the current position | ||
DL_DELETE(cache->global->lru_list, entry); | ||
bratpiorka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// add the entry to the head of the list | ||
DL_PREPEND(cache->global->lru_list, entry); | ||
} else { //cache miss | ||
// Look for eviction candidate | ||
if (entry == NULL && cache->global->max_size != 0 && | ||
cache->global->cur_size >= cache->global->max_size) { | ||
// If max_size is set and the cache is full, evict the least recently used entry. | ||
entry = cache->global->lru_list->prev; | ||
bratpiorka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
if (entry) { // we have eviction candidate | ||
// remove the entry from the frequency list | ||
DL_DELETE(cache->global->lru_list, entry); | ||
// remove the entry from the hash table it belongs to | ||
HASH_DEL(*(entry->hash_table), entry); | ||
cache->global->cur_size -= 1; | ||
evicted_value.mapped_base_ptr = entry->value.mapped_base_ptr; | ||
evicted_value.mapped_size = entry->value.mapped_size; | ||
evicted = true; | ||
} else { // allocate the new entry | ||
entry = umf_ba_alloc(cache->global->cache_allocator); | ||
if (!entry) { | ||
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; | ||
bratpiorka marked this conversation as resolved.
Show resolved
Hide resolved
|
||
LOG_ERR("Failed to allocate memory for a new IPC cache entry"); | ||
goto exit; | ||
} | ||
if (NULL == utils_mutex_init(&(entry->value.mmap_lock))) { | ||
LOG_ERR("Failed to initialize mutex for the IPC cache entry"); | ||
umf_ba_global_free(entry); | ||
ret = UMF_RESULT_ERROR_UNKNOWN; | ||
goto exit; | ||
} | ||
} | ||
|
||
entry->key = *key; | ||
entry->ref_count = 0; | ||
entry->handle_id = handle_id; | ||
entry->hash_table = &cache->hash_table; | ||
entry->value.mapped_size = 0; | ||
entry->value.mapped_base_ptr = NULL; | ||
|
||
HASH_ADD(hh, cache->hash_table, key, sizeof(entry->key), entry); | ||
Check warning on line 219 in src/ipc_cache.c
|
||
DL_PREPEND(cache->global->lru_list, entry); | ||
cache->global->cur_size += 1; | ||
} | ||
|
||
exit: | ||
if (ret == UMF_RESULT_SUCCESS) { | ||
utils_atomic_increment(&entry->ref_count); | ||
*retEntry = &entry->value; | ||
} | ||
|
||
utils_mutex_unlock(&(cache->global->cache_lock)); | ||
|
||
if (evicted) { | ||
cache->eviction_cb(key, &evicted_value); | ||
} | ||
|
||
return ret; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* | ||
* Copyright (C) 2024 Intel Corporation | ||
* | ||
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. | ||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
* | ||
*/ | ||
|
||
#ifndef UMF_IPC_CACHE_H | ||
#define UMF_IPC_CACHE_H 1 | ||
|
||
#include <umf/memory_provider.h> | ||
|
||
#include "utils_concurrency.h" | ||
|
||
typedef struct ipc_mapped_handle_cache_key_t { | ||
void *remote_base_ptr; | ||
umf_memory_provider_handle_t local_provider; | ||
int remote_pid; | ||
} ipc_mapped_handle_cache_key_t; | ||
|
||
typedef struct ipc_mapped_handle_cache_value_t { | ||
void *mapped_base_ptr; | ||
size_t mapped_size; | ||
utils_mutex_t mmap_lock; | ||
} ipc_mapped_handle_cache_value_t; | ||
|
||
struct ipc_mapped_handle_cache_t; | ||
|
||
typedef struct ipc_mapped_handle_cache_t *ipc_mapped_handle_cache_handle_t; | ||
|
||
umf_result_t umfIpcCacheGlobalInit(void); | ||
void umfIpcCacheGlobalTearDown(void); | ||
|
||
// define pointer to the eviction callback function | ||
typedef void (*ipc_mapped_handle_cache_eviction_cb_t)( | ||
const ipc_mapped_handle_cache_key_t *key, | ||
const ipc_mapped_handle_cache_value_t *value); | ||
|
||
ipc_mapped_handle_cache_handle_t umfIpcHandleMappedCacheCreate( | ||
ipc_mapped_handle_cache_eviction_cb_t eviction_cb); | ||
|
||
void umfIpcHandleMappedCacheDestroy(ipc_mapped_handle_cache_handle_t cache); | ||
|
||
umf_result_t | ||
umfIpcHandleMappedCacheGet(ipc_mapped_handle_cache_handle_t cache, | ||
const ipc_mapped_handle_cache_key_t *key, | ||
uint64_t handle_id, | ||
ipc_mapped_handle_cache_value_t **retEntry); | ||
|
||
#endif /* UMF_IPC_CACHE_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.