Skip to content

Commit ab7b9ee

Browse files
committed
Enable IPC cache for Open/Close functions
1 parent 42b438d commit ab7b9ee

11 files changed

+2323
-1846
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
@@ -270,6 +271,7 @@ target_include_directories(
270271
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/provider>
271272
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/memspaces>
272273
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/memtargets>
274+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/uthash>
273275
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
274276

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

src/ipc_cache.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
typedef struct ipc_handle_cache_entry_t {
32+
UT_hash_handle hh;
33+
struct ipc_handle_cache_entry_t *next, *prev;
34+
ipc_mmaped_handle_cache_key_t key;
35+
uint64_t ref_count;
36+
uint64_t handle_id;
37+
ipc_mmaped_handle_cache_value_t value;
38+
} ipc_handle_cache_entry_t;
39+
40+
typedef struct ipc_handle_mmaped_cache_t {
41+
utils_mutex_t cache_lock;
42+
umf_ba_pool_t *cache_allocator;
43+
size_t max_size;
44+
size_t cur_size;
45+
ipc_handle_cache_entry_t *hash_table;
46+
ipc_handle_cache_entry_t *frequency_list;
47+
} ipc_handle_mmaped_cache_t;
48+
49+
typedef ipc_handle_mmaped_cache_t *ipc_handle_mmaped_cache_handle_t;
50+
51+
ipc_handle_mmaped_cache_handle_t umfIpcHandleMmapedCacheCreate(void);
52+
53+
void umfIpcHandleMmapedCacheDestroy(ipc_handle_mmaped_cache_handle_t cache);
54+
55+
// define pointer to the eviction callback function
56+
typedef void (*ipc_handle_mmaped_cache_eviction_cb_t)(
57+
const ipc_mmaped_handle_cache_key_t *key,
58+
const ipc_mmaped_handle_cache_value_t *value);
59+
60+
umf_result_t
61+
umfIpcHandleMmapedCacheGet(ipc_handle_mmaped_cache_handle_t cache,
62+
const ipc_mmaped_handle_cache_key_t *key,
63+
uint64_t handle_id,
64+
ipc_handle_mmaped_cache_eviction_cb_t eviction_cb,
65+
ipc_mmaped_handle_cache_value_t **retEntry);
66+
67+
#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: 6 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"
@@ -18,13 +19,15 @@
1819
#endif
1920

2021
umf_memory_tracker_handle_t TRACKER = NULL;
22+
ipc_handle_mmaped_cache_handle_t IPC_MMAPED_CACHE = NULL;
2123

2224
static unsigned long long umfRefCount = 0;
2325

2426
int umfInit(void) {
2527
if (utils_fetch_and_add64(&umfRefCount, 1) == 0) {
2628
utils_log_init();
2729
TRACKER = umfMemoryTrackerCreate();
30+
IPC_MMAPED_CACHE = umfIpcHandleMmapedCacheCreate();
2831
}
2932

3033
return (TRACKER) ? 0 : -1;
@@ -39,6 +42,9 @@ void umfTearDown(void) {
3942
umfMemspaceLowestLatencyDestroy();
4043
umfDestroyTopology();
4144
#endif
45+
ipc_handle_mmaped_cache_handle_t ipc_mmaped_cache = IPC_MMAPED_CACHE;
46+
IPC_MMAPED_CACHE = NULL;
47+
umfIpcHandleMmapedCacheDestroy(ipc_mmaped_cache);
4248
// make sure TRACKER is not used after being destroyed
4349
umf_memory_tracker_handle_t t = TRACKER;
4450
TRACKER = NULL;

0 commit comments

Comments
 (0)