Skip to content

Commit b84c05c

Browse files
committed
Enable IPC cache for Open/Close functions
1 parent 284a43b commit b84c05c

File tree

8 files changed

+382
-52
lines changed

8 files changed

+382
-52
lines changed

src/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ set(UMF_SOURCES
104104
${BA_SOURCES}
105105
libumf.c
106106
ipc.c
107+
ipc_cache.c
107108
memory_pool.c
108109
memory_provider.c
109110
memory_provider_get_last_failed.c
@@ -247,6 +248,7 @@ target_include_directories(
247248
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/provider>
248249
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/memspaces>
249250
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/memtargets>
251+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/uthash>
250252
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
251253

252254
install(TARGETS umf EXPORT ${PROJECT_NAME}-targets)

src/ipc.c

+2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ umf_result_t umfGetIPCHandle(const void *ptr, umf_ipc_handle_t *umfIPCHandle,
9090
return ret;
9191
}
9292

93+
// ipcData->handle_id is filled by tracking provider
94+
ipcData->base = allocInfo.base;
9395
ipcData->pid = utils_getpid();
9496
ipcData->baseSize = allocInfo.baseSize;
9597
ipcData->offset = (uintptr_t)ptr - (uintptr_t)allocInfo.base;

src/ipc_cache.c

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/*
2+
*
3+
* Copyright (C) 2024 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
#include "ipc_cache.h"
10+
11+
#include <stdbool.h>
12+
13+
#include "base_alloc_global.h"
14+
#include "utils_common.h"
15+
#include "utils_concurrency.h"
16+
#include "utils_log.h"
17+
#include "utlist.h"
18+
19+
typedef struct ipc_handle_cache_entry_t {
20+
UT_hash_handle hh;
21+
struct ipc_handle_cache_entry_t *next, *prev;
22+
ipc_mapped_handle_cache_key_t key;
23+
uint64_t ref_count;
24+
uint64_t handle_id;
25+
ipc_mapped_handle_cache_value_t value;
26+
} ipc_handle_cache_entry_t;
27+
28+
typedef ipc_handle_cache_entry_t *hash_map_t;
29+
typedef ipc_handle_cache_entry_t *lru_list_t;
30+
31+
typedef struct ipc_handle_mapped_cache_global_t {
32+
utils_mutex_t cache_lock;
33+
umf_ba_pool_t *cache_allocator;
34+
size_t max_size;
35+
size_t cur_size;
36+
lru_list_t lru_list;
37+
} ipc_handle_mapped_cache_global_t;
38+
39+
typedef struct ipc_handle_mapped_cache_t {
40+
ipc_handle_mapped_cache_global_t *global;
41+
hash_map_t hash_table;
42+
ipc_handle_mapped_cache_eviction_cb_t eviction_cb;
43+
} ipc_handle_mapped_cache_t;
44+
45+
ipc_handle_mapped_cache_global_t *IPC_MAPPED_CACHE_GLOBAL = NULL;
46+
47+
void umfIpcCacheInit(void) {
48+
ipc_handle_mapped_cache_global_t *cache_global =
49+
umf_ba_global_alloc(sizeof(*cache_global));
50+
if (!cache_global) {
51+
return;
52+
}
53+
54+
if (NULL == utils_mutex_init(&(cache_global->cache_lock))) {
55+
LOG_ERR("Failed to initialize mutex for the IPC cache");
56+
umf_ba_global_free(cache_global);
57+
return;
58+
}
59+
60+
cache_global->cache_allocator =
61+
umf_ba_create(sizeof(ipc_handle_cache_entry_t));
62+
if (!cache_global->cache_allocator) {
63+
LOG_ERR("Failed to create IPC cache allocator");
64+
umf_ba_global_free(cache_global);
65+
return;
66+
}
67+
68+
cache_global->max_size = 0;
69+
cache_global->cur_size = 0;
70+
cache_global->lru_list = NULL;
71+
72+
IPC_MAPPED_CACHE_GLOBAL = cache_global;
73+
}
74+
75+
void umfIpcCacheTearDown(void) {
76+
ipc_handle_mapped_cache_global_t *cache = IPC_MAPPED_CACHE_GLOBAL;
77+
IPC_MAPPED_CACHE_GLOBAL = NULL;
78+
79+
if (!cache) {
80+
return;
81+
}
82+
83+
assert(cache->cur_size == 0);
84+
85+
umf_ba_destroy(cache->cache_allocator);
86+
umf_ba_global_free(cache);
87+
}
88+
89+
ipc_handle_mapped_cache_handle_t umfIpcHandleMappedCacheCreate(
90+
ipc_handle_mapped_cache_eviction_cb_t eviction_cb) {
91+
ipc_handle_mapped_cache_t *cache = umf_ba_global_alloc(sizeof(*cache));
92+
93+
if (!cache) {
94+
return NULL;
95+
}
96+
97+
cache->global = IPC_MAPPED_CACHE_GLOBAL;
98+
cache->hash_table = NULL;
99+
cache->eviction_cb = eviction_cb;
100+
101+
return cache;
102+
}
103+
104+
void umfIpcHandleMappedCacheDestroy(ipc_handle_mapped_cache_handle_t cache) {
105+
ipc_handle_cache_entry_t *entry, *tmp;
106+
HASH_ITER(hh, cache->hash_table, entry, tmp) {
107+
DL_DELETE(cache->global->lru_list, entry);
108+
HASH_DEL(cache->hash_table, entry);
109+
cache->global->cur_size -= 1;
110+
cache->eviction_cb(&entry->key, &entry->value);
111+
umf_ba_free(cache->global->cache_allocator, entry);
112+
}
113+
HASH_CLEAR(hh, cache->hash_table);
114+
115+
umf_ba_global_free(cache);
116+
}
117+
118+
umf_result_t
119+
umfIpcHandleMappedCacheGet(ipc_handle_mapped_cache_handle_t cache,
120+
const ipc_mapped_handle_cache_key_t *key,
121+
uint64_t handle_id,
122+
ipc_mapped_handle_cache_value_t **retEntry) {
123+
ipc_handle_cache_entry_t *entry = NULL;
124+
umf_result_t ret = UMF_RESULT_SUCCESS;
125+
bool evicted = false;
126+
ipc_mapped_handle_cache_value_t evicted_value;
127+
128+
if (!cache) {
129+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
130+
}
131+
132+
utils_mutex_lock(&(cache->global->cache_lock));
133+
134+
HASH_FIND(hh, cache->hash_table, key, sizeof(*key), entry);
135+
if (entry && entry->handle_id == handle_id) { // cache hit
136+
// update frequency list
137+
DL_DELETE(cache->global->lru_list, entry);
138+
DL_PREPEND(cache->global->lru_list, entry);
139+
} else { //cache miss
140+
// Look for eviction candidate
141+
if (entry == NULL && cache->global->max_size != 0 &&
142+
cache->global->cur_size >= cache->global->max_size) {
143+
entry = cache->global->lru_list->prev;
144+
}
145+
146+
if (entry) { // we have eviction candidate
147+
DL_DELETE(cache->global->lru_list, entry);
148+
HASH_DEL(cache->hash_table, entry);
149+
cache->global->cur_size -= 1;
150+
evicted_value.mapped_base_ptr = entry->value.mapped_base_ptr;
151+
evicted_value.mapped_size = entry->value.mapped_size;
152+
evicted = true;
153+
} else {
154+
entry = umf_ba_alloc(cache->global->cache_allocator);
155+
if (!entry) {
156+
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
157+
goto exit;
158+
}
159+
if (NULL == utils_mutex_init(&(entry->value.mmap_lock))) {
160+
LOG_ERR("Failed to initialize mutex for the IPC cache entry");
161+
umf_ba_global_free(entry);
162+
ret = UMF_RESULT_ERROR_UNKNOWN;
163+
goto exit;
164+
}
165+
}
166+
167+
entry->key = *key;
168+
entry->ref_count = 0;
169+
entry->handle_id = handle_id;
170+
entry->value.mapped_size = 0;
171+
entry->value.mapped_base_ptr = NULL;
172+
173+
HASH_ADD(hh, cache->hash_table, key, sizeof(entry->key), entry);
174+
DL_PREPEND(cache->global->lru_list, entry);
175+
cache->global->cur_size += 1;
176+
}
177+
178+
exit:
179+
if (ret == UMF_RESULT_SUCCESS) {
180+
utils_atomic_increment(&entry->ref_count);
181+
*retEntry = &entry->value;
182+
}
183+
184+
utils_mutex_unlock(&(cache->global->cache_lock));
185+
186+
if (evicted) {
187+
cache->eviction_cb(key, &evicted_value);
188+
}
189+
190+
return ret;
191+
}

src/ipc_cache.h

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
*
3+
* Copyright (C) 2024 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
#ifndef UMF_IPC_CACHE_H
11+
#define UMF_IPC_CACHE_H 1
12+
13+
#include "umf/memory_provider.h"
14+
15+
#include "base_alloc.h"
16+
#include "uthash.h"
17+
#include "utils_concurrency.h"
18+
19+
typedef struct ipc_mapped_handle_cache_key_t {
20+
void *remote_base_ptr;
21+
umf_memory_provider_handle_t local_provider;
22+
int remote_pid;
23+
} ipc_mapped_handle_cache_key_t;
24+
25+
typedef struct ipc_mapped_handle_cache_value_t {
26+
void *mapped_base_ptr;
27+
size_t mapped_size;
28+
utils_mutex_t mmap_lock;
29+
} ipc_mapped_handle_cache_value_t;
30+
31+
struct ipc_handle_mapped_cache_t;
32+
33+
typedef struct ipc_handle_mapped_cache_t *ipc_handle_mapped_cache_handle_t;
34+
35+
void umfIpcCacheInit(void);
36+
void umfIpcCacheTearDown(void);
37+
38+
// define pointer to the eviction callback function
39+
typedef void (*ipc_handle_mapped_cache_eviction_cb_t)(
40+
const ipc_mapped_handle_cache_key_t *key,
41+
const ipc_mapped_handle_cache_value_t *value);
42+
43+
ipc_handle_mapped_cache_handle_t umfIpcHandleMappedCacheCreate(
44+
ipc_handle_mapped_cache_eviction_cb_t eviction_cb);
45+
46+
void umfIpcHandleMappedCacheDestroy(ipc_handle_mapped_cache_handle_t cache);
47+
48+
umf_result_t
49+
umfIpcHandleMappedCacheGet(ipc_handle_mapped_cache_handle_t cache,
50+
const ipc_mapped_handle_cache_key_t *key,
51+
uint64_t handle_id,
52+
ipc_mapped_handle_cache_value_t **retEntry);
53+
54+
#endif /* UMF_IPC_CACHE_H */

src/ipc_internal.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ extern "C" {
2121
// providerIpcData is a Flexible Array Member because its size varies
2222
// depending on the provider.
2323
typedef struct umf_ipc_data_t {
24-
int pid; // process ID of the process that allocated the memory
25-
size_t baseSize; // size of base (coarse-grain) allocation
24+
uint64_t handle_id; // unique handle ID
25+
void *base; // base address of the memory
26+
int pid; // process ID of the process that allocated the memory
27+
size_t baseSize; // size of base (coarse-grain) allocation
2628
uint64_t offset;
2729
char providerIpcData[];
2830
} umf_ipc_data_t;

src/libumf.c

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stddef.h>
1111

1212
#include "base_alloc_global.h"
13+
#include "ipc_cache.h"
1314
#include "memspace_internal.h"
1415
#include "provider_tracking.h"
1516
#include "utils_log.h"
@@ -25,6 +26,7 @@ int umfInit(void) {
2526
if (utils_fetch_and_add64(&umfRefCount, 1) == 0) {
2627
utils_log_init();
2728
TRACKER = umfMemoryTrackerCreate();
29+
umfIpcCacheInit();
2830
}
2931

3032
return (TRACKER) ? 0 : -1;
@@ -39,6 +41,7 @@ void umfTearDown(void) {
3941
umfMemspaceLowestLatencyDestroy();
4042
umfDestroyTopology();
4143
#endif
44+
umfIpcCacheTearDown();
4245
// make sure TRACKER is not used after being destroyed
4346
umf_memory_tracker_handle_t t = TRACKER;
4447
TRACKER = NULL;

0 commit comments

Comments
 (0)