Skip to content

Commit 5f7eaa4

Browse files
committed
Enable IPC cache for Open/Close functions
1 parent 86b1522 commit 5f7eaa4

File tree

8 files changed

+360
-52
lines changed

8 files changed

+360
-52
lines changed

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
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_mmaped_handle_cache_key_t key;
23+
uint64_t ref_count;
24+
uint64_t handle_id;
25+
ipc_mmaped_handle_cache_value_t value;
26+
} ipc_handle_cache_entry_t;
27+
28+
typedef struct ipc_handle_mmaped_cache_t {
29+
utils_mutex_t cache_lock;
30+
umf_ba_pool_t *cache_allocator;
31+
size_t max_size;
32+
size_t cur_size;
33+
ipc_handle_cache_entry_t *hash_table;
34+
ipc_handle_cache_entry_t *frequency_list;
35+
} ipc_handle_mmaped_cache_t;
36+
37+
ipc_handle_mmaped_cache_handle_t IPC_MMAPED_CACHE = NULL;
38+
39+
void umfIpcCacheInit(void) {
40+
ipc_handle_mmaped_cache_t *cache = umf_ba_global_alloc(sizeof(*cache));
41+
if (!cache) {
42+
return;
43+
}
44+
45+
if (NULL == utils_mutex_init(&(cache->cache_lock))) {
46+
LOG_ERR("Failed to initialize mutex for the IPC cache");
47+
umf_ba_global_free(cache);
48+
return;
49+
}
50+
51+
cache->cache_allocator = umf_ba_create(sizeof(ipc_handle_cache_entry_t));
52+
if (!cache->cache_allocator) {
53+
LOG_ERR("Failed to create IPC cache allocator");
54+
umf_ba_global_free(cache);
55+
return;
56+
}
57+
58+
cache->max_size = 0;
59+
cache->cur_size = 0;
60+
cache->hash_table = NULL;
61+
cache->frequency_list = NULL;
62+
63+
IPC_MMAPED_CACHE = cache;
64+
}
65+
66+
void umfIpcCacheTearDown(void) {
67+
ipc_handle_mmaped_cache_handle_t cache = IPC_MMAPED_CACHE;
68+
IPC_MMAPED_CACHE = NULL;
69+
70+
if (!cache) {
71+
return;
72+
}
73+
74+
ipc_handle_cache_entry_t *entry, *tmp;
75+
HASH_ITER(hh, cache->hash_table, entry, tmp) {
76+
DL_DELETE(cache->frequency_list, entry);
77+
HASH_DEL(cache->hash_table, entry);
78+
cache->cur_size -= 1;
79+
umf_ba_free(cache->cache_allocator, entry);
80+
}
81+
HASH_CLEAR(hh, cache->hash_table);
82+
83+
umf_ba_destroy(cache->cache_allocator);
84+
umf_ba_global_free(cache);
85+
}
86+
87+
ipc_handle_mmaped_cache_handle_t umfIpcHandleMmapedCacheCreate(void) {
88+
return IPC_MMAPED_CACHE;
89+
}
90+
91+
void umfIpcHandleMmapedCacheDestroy(ipc_handle_mmaped_cache_handle_t cache) {
92+
(void)cache;
93+
}
94+
95+
umf_result_t
96+
umfIpcHandleMmapedCacheGet(ipc_handle_mmaped_cache_handle_t cache,
97+
const ipc_mmaped_handle_cache_key_t *key,
98+
uint64_t handle_id,
99+
ipc_handle_mmaped_cache_eviction_cb_t eviction_cb,
100+
ipc_mmaped_handle_cache_value_t **retEntry) {
101+
ipc_handle_cache_entry_t *entry = NULL;
102+
umf_result_t ret = UMF_RESULT_SUCCESS;
103+
bool evicted = false;
104+
ipc_mmaped_handle_cache_value_t evicted_value;
105+
106+
if (!cache) {
107+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
108+
}
109+
110+
utils_mutex_lock(&(cache->cache_lock));
111+
112+
HASH_FIND(hh, cache->hash_table, key, sizeof(*key), entry);
113+
if (entry && entry->handle_id == handle_id) { // cache hit
114+
// update frequency list
115+
DL_DELETE(cache->frequency_list, entry);
116+
DL_PREPEND(cache->frequency_list, entry);
117+
} else { //cache miss
118+
// Look for eviction candidate
119+
if (entry == NULL && cache->max_size != 0 &&
120+
cache->cur_size >= cache->max_size) {
121+
entry = cache->frequency_list->prev;
122+
}
123+
124+
if (entry) { // we have eviction candidate
125+
DL_DELETE(cache->frequency_list, entry);
126+
HASH_DEL(cache->hash_table, entry);
127+
cache->cur_size -= 1;
128+
evicted_value.mmaped_base_ptr = entry->value.mmaped_base_ptr;
129+
evicted_value.mmaped_size = entry->value.mmaped_size;
130+
evicted = true;
131+
} else {
132+
entry = umf_ba_alloc(cache->cache_allocator);
133+
if (!entry) {
134+
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
135+
goto exit;
136+
}
137+
if (NULL == utils_mutex_init(&(entry->value.mmap_lock))) {
138+
LOG_ERR("Failed to initialize mutex for the IPC cache entry");
139+
umf_ba_global_free(entry);
140+
ret = UMF_RESULT_ERROR_UNKNOWN;
141+
goto exit;
142+
}
143+
}
144+
145+
entry->key = *key;
146+
entry->ref_count = 0;
147+
entry->handle_id = handle_id;
148+
entry->value.mmaped_size = 0;
149+
entry->value.mmaped_base_ptr = NULL;
150+
151+
HASH_ADD(hh, cache->hash_table, key, sizeof(entry->key), entry);
152+
DL_PREPEND(cache->frequency_list, entry);
153+
cache->cur_size += 1;
154+
}
155+
156+
exit:
157+
if (ret == UMF_RESULT_SUCCESS) {
158+
utils_atomic_increment(&entry->ref_count);
159+
*retEntry = &entry->value;
160+
}
161+
162+
utils_mutex_unlock(&(cache->cache_lock));
163+
164+
if (evicted) {
165+
eviction_cb(key, &evicted_value);
166+
}
167+
168+
return ret;
169+
}

src/ipc_cache.h

Lines changed: 54 additions & 0 deletions
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_mmaped_handle_cache_key_t {
20+
void *remote_base_ptr;
21+
umf_memory_provider_handle_t local_provider;
22+
int remote_pid;
23+
} ipc_mmaped_handle_cache_key_t;
24+
25+
typedef struct ipc_mmaped_handle_cache_value_t {
26+
void *mmaped_base_ptr;
27+
size_t mmaped_size;
28+
utils_mutex_t mmap_lock;
29+
} ipc_mmaped_handle_cache_value_t;
30+
31+
struct ipc_handle_mmaped_cache_t;
32+
33+
typedef struct ipc_handle_mmaped_cache_t *ipc_handle_mmaped_cache_handle_t;
34+
35+
void umfIpcCacheInit(void);
36+
void umfIpcCacheTearDown(void);
37+
38+
ipc_handle_mmaped_cache_handle_t umfIpcHandleMmapedCacheCreate(void);
39+
40+
void umfIpcHandleMmapedCacheDestroy(ipc_handle_mmaped_cache_handle_t cache);
41+
42+
// define pointer to the eviction callback function
43+
typedef void (*ipc_handle_mmaped_cache_eviction_cb_t)(
44+
const ipc_mmaped_handle_cache_key_t *key,
45+
const ipc_mmaped_handle_cache_value_t *value);
46+
47+
umf_result_t
48+
umfIpcHandleMmapedCacheGet(ipc_handle_mmaped_cache_handle_t cache,
49+
const ipc_mmaped_handle_cache_key_t *key,
50+
uint64_t handle_id,
51+
ipc_handle_mmaped_cache_eviction_cb_t eviction_cb,
52+
ipc_mmaped_handle_cache_value_t **retEntry);
53+
54+
#endif /* UMF_IPC_CACHE_H */

src/ipc_internal.h

Lines changed: 4 additions & 2 deletions
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

Lines changed: 3 additions & 0 deletions
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)