Skip to content

Commit 874d784

Browse files
committed
add examples
1 parent 245d916 commit 874d784

File tree

5 files changed

+613
-0
lines changed

5 files changed

+613
-0
lines changed

examples/CMakeLists.txt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,50 @@ else()
165165
"IPC examples with UMF pool API are supported on Linux only - skipping"
166166
)
167167
endif()
168+
169+
if(LINUX)
170+
set(EXAMPLE_NAME umf_example_memspace_numa)
171+
172+
add_umf_executable(
173+
NAME ${EXAMPLE_NAME}
174+
SRCS memspace/memspace_numa.c
175+
LIBS umf hwloc numa)
176+
177+
target_include_directories(
178+
${EXAMPLE_NAME} PRIVATE ${UMF_CMAKE_SOURCE_DIR}/src/utils
179+
${UMF_CMAKE_SOURCE_DIR}/include)
180+
181+
target_link_directories(${EXAMPLE_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS})
182+
183+
set(EXAMPLE_NAME umf_example_memspace_hmat)
184+
185+
add_umf_executable(
186+
NAME ${EXAMPLE_NAME}
187+
SRCS memspace/memspace_hmat.c
188+
LIBS umf hwloc numa)
189+
190+
target_include_directories(
191+
${EXAMPLE_NAME} PRIVATE ${UMF_CMAKE_SOURCE_DIR}/src/utils
192+
${UMF_CMAKE_SOURCE_DIR}/include)
193+
194+
target_link_directories(${EXAMPLE_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS})
195+
196+
set(EXAMPLE_NAME umf_example_file_provider)
197+
198+
add_umf_executable(
199+
NAME ${EXAMPLE_NAME}
200+
SRCS custom_provider/file_provider.c
201+
LIBS umf hwloc)
202+
203+
target_include_directories(
204+
${EXAMPLE_NAME} PRIVATE ${UMF_CMAKE_SOURCE_DIR}/src/utils
205+
${UMF_CMAKE_SOURCE_DIR}/include)
206+
207+
target_link_directories(${EXAMPLE_NAME} PRIVATE ${LIBHWLOC_LIBRARY_DIRS})
208+
209+
else()
210+
message(
211+
STATUS "Memspace examples API are supported on Linux only - skipping")
212+
message(
213+
STATUS "File provider example is supported on Linux only - skipping")
214+
endif()
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
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+
#define _GNU_SOURCE 1
10+
11+
#include "umf/base.h"
12+
#include "umf/pools/pool_scalable.h"
13+
#include "umf/providers/provider_os_memory.h"
14+
15+
#include <fcntl.h>
16+
#include <linux/falloc.h>
17+
#include <stdio.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
#include <sys/mman.h>
21+
#include <unistd.h>
22+
23+
#define ADRESS_RESERVATION ((size_t)16 * 1024 * 1024 * 1024)
24+
#define ALIGN_UP(value, align) (((value) + (align) - 1) & ~((align) - 1))
25+
26+
typedef struct file_provider_t {
27+
void *ptr;
28+
size_t offset;
29+
30+
int fd;
31+
size_t foffset;
32+
33+
size_t page_size;
34+
} file_provider_t;
35+
36+
typedef struct file_params_t {
37+
const char *filename;
38+
} file_params_t;
39+
40+
static umf_result_t file_init(void *params, void **provider) {
41+
(void)params; // unused
42+
file_provider_t *file_provider = NULL;
43+
file_params_t *file_params = (file_params_t *)params;
44+
int page_size = 0;
45+
umf_result_t ret = UMF_RESULT_SUCCESS;
46+
47+
file_provider = malloc(sizeof(*file_provider));
48+
if (!file_provider) {
49+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
50+
}
51+
52+
file_provider->fd = open(file_params->filename, O_RDWR | O_CREAT, 0666);
53+
if (file_provider->fd < 0) {
54+
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
55+
goto cleanup_malloc;
56+
}
57+
58+
file_provider->ptr = mmap(NULL, ADRESS_RESERVATION, PROT_READ | PROT_WRITE,
59+
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
60+
61+
if (file_provider->ptr == MAP_FAILED) {
62+
63+
ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
64+
goto cleanup_fd;
65+
}
66+
67+
page_size = sysconf(_SC_PAGESIZE);
68+
if (page_size < 0) {
69+
ret = UMF_RESULT_ERROR_UNKNOWN;
70+
goto cleanup_mmap;
71+
}
72+
73+
file_provider->offset = 0;
74+
file_provider->foffset = 0;
75+
file_provider->page_size = (size_t)page_size;
76+
*provider = file_provider;
77+
78+
return UMF_RESULT_SUCCESS;
79+
80+
cleanup_mmap:
81+
munmap(file_provider->ptr, ADRESS_RESERVATION);
82+
cleanup_fd:
83+
close(file_provider->fd);
84+
cleanup_malloc:
85+
free(file_provider);
86+
return ret;
87+
}
88+
89+
static void file_deinit(void *provider) {
90+
file_provider_t *file_provider = (file_provider_t *)provider;
91+
munmap(file_provider->ptr, ADRESS_RESERVATION);
92+
close(file_provider->fd);
93+
free(file_provider);
94+
}
95+
96+
static umf_result_t file_alloc(void *provider, size_t size, size_t alignment,
97+
void **ptr) {
98+
if (provider == NULL || ptr == NULL) {
99+
fprintf(stderr, "provider or ptr cannot be null\n");
100+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
101+
}
102+
file_provider_t *file_provider = (file_provider_t *)provider;
103+
size_t page_size = file_provider->page_size;
104+
105+
if (alignment && (alignment % page_size) && (page_size % alignment)) {
106+
fprintf(stderr,
107+
"wrong alignment: %zu (not a multiple or a divider of the "
108+
"minimum page size (%zu))",
109+
alignment, page_size);
110+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
111+
}
112+
113+
size = ALIGN_UP(size, page_size);
114+
115+
uintptr_t aligned_ptr =
116+
alignment > page_size
117+
? ALIGN_UP((uintptr_t)file_provider->ptr + file_provider->offset,
118+
alignment)
119+
: (uintptr_t)file_provider->ptr + file_provider->offset;
120+
121+
size_t new_offset = aligned_ptr + size - (uintptr_t)file_provider->ptr;
122+
if (new_offset + size > ADRESS_RESERVATION) {
123+
fprintf(stderr, "This example limits allocation up to 10GB\n");
124+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
125+
}
126+
127+
if (fallocate(file_provider->fd, 0, file_provider->foffset, size)) {
128+
perror("fallocate");
129+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
130+
}
131+
132+
void *ret = mmap((void *)aligned_ptr, size, PROT_READ | PROT_WRITE,
133+
MAP_FIXED | MAP_PRIVATE, file_provider->fd,
134+
file_provider->foffset);
135+
136+
if (ret == MAP_FAILED) {
137+
perror("mmap");
138+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
139+
}
140+
141+
file_provider->offset = new_offset;
142+
file_provider->foffset += size;
143+
*ptr = ret;
144+
return UMF_RESULT_SUCCESS;
145+
}
146+
147+
static umf_result_t file_free(void *provider, void *ptr, size_t size) {
148+
if (provider == NULL || ptr == NULL) {
149+
fprintf(stderr, "provider or ptr cannot be null\n");
150+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
151+
}
152+
file_provider_t *file_provider = (file_provider_t *)provider;
153+
if (size == 0) {
154+
fprintf(stderr, "size cannot be 0\n");
155+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
156+
}
157+
if (ptr < file_provider->ptr ||
158+
(uintptr_t)ptr >=
159+
(uintptr_t)file_provider->ptr + file_provider->offset) {
160+
fprintf(stderr, "ptr is not within the provider's memory\n");
161+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
162+
}
163+
164+
if (munmap(ptr, size)) {
165+
fprintf(stderr, "munmap failed\n");
166+
return UMF_RESULT_ERROR_UNKNOWN;
167+
}
168+
169+
if (fallocate(file_provider->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
170+
(uintptr_t)ptr - (uintptr_t)file_provider->ptr, size)) {
171+
perror("fallocate");
172+
return UMF_RESULT_ERROR_UNKNOWN;
173+
}
174+
175+
return UMF_RESULT_SUCCESS;
176+
}
177+
178+
static const char *file_get_name(void *provider) {
179+
(void)provider; // unused
180+
return "File Provider";
181+
}
182+
183+
static void file_get_last_native_error(void *provider, const char **ppMessage,
184+
int32_t *pError) {
185+
(void)provider; // unused
186+
*ppMessage = "";
187+
*pError = 0;
188+
}
189+
190+
static umf_result_t file_get_recommended_page_size(void *provider, size_t size,
191+
size_t *pageSize) {
192+
(void)size; // unused
193+
if (provider == NULL || pageSize == NULL) {
194+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
195+
}
196+
197+
file_provider_t *file_provider = (file_provider_t *)provider;
198+
*pageSize = file_provider->page_size;
199+
return UMF_RESULT_SUCCESS;
200+
}
201+
202+
static umf_result_t file_get_min_page_size(void *provider, void *ptr,
203+
size_t *pageSize) {
204+
(void)ptr; // unused
205+
if (provider == NULL || pageSize == NULL) {
206+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
207+
}
208+
209+
file_provider_t *file_provider = (file_provider_t *)provider;
210+
*pageSize = file_provider->page_size;
211+
return UMF_RESULT_SUCCESS;
212+
}
213+
214+
static umf_memory_provider_ops_t file_ops = {
215+
.version = UMF_VERSION_CURRENT,
216+
.initialize = file_init,
217+
.finalize = file_deinit,
218+
.alloc = file_alloc,
219+
.free = file_free,
220+
.get_name = file_get_name,
221+
.get_last_native_error = file_get_last_native_error,
222+
.get_recommended_page_size = file_get_recommended_page_size,
223+
.get_min_page_size = file_get_min_page_size,
224+
};
225+
226+
int main(void) {
227+
// A result object for storing UMF API result status
228+
umf_result_t res;
229+
umf_memory_provider_handle_t provider;
230+
file_params_t params;
231+
params.filename = "/tmp/file_provider_example";
232+
233+
res = umfMemoryProviderCreate(&file_ops, &params, &provider);
234+
if (res != UMF_RESULT_SUCCESS) {
235+
printf("Failed to create a memory provider!\n");
236+
return -1;
237+
}
238+
printf("OS memory provider created at %p\n", (void *)provider);
239+
240+
// Allocate memory from memory provider
241+
size_t alloc_size = 5000;
242+
size_t alignment = 0;
243+
void *ptr_provider = NULL;
244+
245+
res =
246+
umfMemoryProviderAlloc(provider, alloc_size, alignment, &ptr_provider);
247+
if (res != UMF_RESULT_SUCCESS) {
248+
printf("Failed to allocate memory from the memory provider!\n");
249+
goto memory_provider_destroy;
250+
}
251+
252+
const char *strSource = "Allocated memory at";
253+
254+
// Write to the allocated memory
255+
memset(ptr_provider, '\0', alloc_size);
256+
strncpy(ptr_provider, strSource, alloc_size);
257+
printf("%s %p with the memory provider at %p\n", (char *)ptr_provider,
258+
(void *)ptr_provider, (void *)provider);
259+
260+
// Free allocated memory
261+
res = umfMemoryProviderFree(provider, ptr_provider, alloc_size);
262+
if (res != UMF_RESULT_SUCCESS) {
263+
printf("Failed to free memory to the provider!\n");
264+
goto memory_provider_destroy;
265+
}
266+
printf("Freed memory at %p\n", ptr_provider);
267+
268+
// Create a memory pool
269+
umf_memory_pool_ops_t *pool_ops = umfScalablePoolOps();
270+
void *pool_params = NULL;
271+
umf_pool_create_flags_t flags = 0;
272+
umf_memory_pool_handle_t pool;
273+
274+
res = umfPoolCreate(pool_ops, provider, pool_params, flags, &pool);
275+
if (res != UMF_RESULT_SUCCESS) {
276+
printf("Failed to create a pool!\n");
277+
goto memory_provider_destroy;
278+
}
279+
printf("Scalable memory pool created at %p\n", (void *)pool);
280+
281+
// Allocate some memory in the pool
282+
size_t num = 1;
283+
alloc_size = 128;
284+
285+
char *ptr = umfPoolCalloc(pool, num, alloc_size);
286+
if (!ptr) {
287+
printf("Failed to allocate memory in the pool!\n");
288+
goto memory_pool_destroy;
289+
}
290+
291+
// Write a string to allocated memory
292+
strncpy(ptr, strSource, alloc_size);
293+
printf("%s %p\n", ptr, (void *)ptr);
294+
295+
// Retrieve a memory pool from a pointer, available with memory tracking
296+
umf_memory_pool_handle_t check_pool = umfPoolByPtr(ptr);
297+
printf("Memory at %p has been allocated from the pool at %p\n", (void *)ptr,
298+
(void *)check_pool);
299+
300+
// Retrieve a memory provider from a pool
301+
umf_memory_provider_handle_t check_provider;
302+
res = umfPoolGetMemoryProvider(pool, &check_provider);
303+
if (res != UMF_RESULT_SUCCESS) {
304+
printf("Failed to retrieve a memory provider for the pool!\n");
305+
goto memory_pool_destroy;
306+
}
307+
printf("Pool at %p has been allocated from the provider at %p\n",
308+
(void *)pool, (void *)check_provider);
309+
310+
// Clean up.
311+
umfFree(ptr);
312+
umfPoolDestroy(pool);
313+
umfMemoryProviderDestroy(provider);
314+
return 0;
315+
316+
memory_pool_destroy:
317+
umfPoolDestroy(pool);
318+
memory_provider_destroy:
319+
umfMemoryProviderDestroy(provider);
320+
return -1;
321+
}

0 commit comments

Comments
 (0)