Skip to content

Commit 5bd462c

Browse files
committed
add memspace filter functions
1 parent e9b0630 commit 5bd462c

File tree

14 files changed

+388
-25
lines changed

14 files changed

+388
-25
lines changed

include/umf/base.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright (C) 2023 Intel Corporation
3+
* Copyright (C) 2023-2024 Intel Corporation
44
*
55
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
66
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
@@ -43,7 +43,8 @@ typedef enum umf_result_t {
4343
UMF_RESULT_ERROR_INVALID_ALIGNMENT =
4444
4, ///< Invalid alignment of an argument
4545
UMF_RESULT_ERROR_NOT_SUPPORTED = 5, ///< Operation not supported
46-
46+
UMF_RESULT_ERROR_USER_SPECIFIC =
47+
6, ///< Failure in user provider code (i.e in user provided callback)
4748
UMF_RESULT_ERROR_UNKNOWN = 0x7ffffffe ///< Unknown or internal error
4849
} umf_result_t;
4950

include/umf/memspace.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,58 @@ umf_result_t
131131
umfMemspaceMemtargetRemove(umf_memspace_handle_t hMemspace,
132132
umf_const_memtarget_handle_t hMemtarget);
133133

134+
/// \brief Clones memspace.
135+
///
136+
/// \param hMemspace handle to memspace
137+
/// \param hNewMemspace [out] handle to the newly created memspace
138+
/// \return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
139+
///
140+
umf_result_t umfMemspaceClone(umf_const_memspace_handle_t hMemspace,
141+
umf_memspace_handle_t *hNewMemspace);
142+
143+
/// \brief custom filter function for umfMemspaceUserFilter
144+
///
145+
/// \param hMemspace handle to memspace
146+
/// \param hMemtarget handle to memory target
147+
/// \param args - user provided arguments
148+
/// \return zero if hMemtarget should be removed from memspace, positive otherwise, and negative on error
149+
///
150+
typedef int (*umf_memspace_filter_func_t)(
151+
umf_const_memspace_handle_t memspace,
152+
umf_const_memtarget_handle_t memtarget, void *args);
153+
154+
/// \brief Removes all memory targets with not matching numa node ids.
155+
///
156+
/// \param hMemspace handle to memspace
157+
/// \param ids - array of numa node ids
158+
/// \param size - size of the array
159+
/// \return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
160+
/// If the error code is UMF_RESULT_UNKNOWN the memspace is corrupted, otherwise the memspace is not modified.
161+
///
162+
umf_result_t umfMemspaceFilterById(umf_memspace_handle_t memspace,
163+
unsigned *ids, size_t size);
164+
165+
/// \brief Filters out memory targets that capacity is less than specified size.
166+
///
167+
/// \param memspace handle to memspace
168+
/// \param size - minimum capacity of memory target
169+
/// \return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
170+
/// If the error code is UMF_RESULT_UNKNOWN the memspace is corrupted, otherwise the memspace is not modified.
171+
///
172+
umf_result_t umfMemspaceFilterByCapacity(umf_memspace_handle_t memspace,
173+
size_t size);
174+
175+
/// \brief Filters out memory targets based on user provided function
176+
///
177+
/// \param memspace handle to memspace
178+
/// \param filter - user provided function
179+
/// \param args - user provided arguments
180+
/// \return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
181+
/// If the error code is UMF_RESULT_UNKNOWN the memspace is corrupted, otherwise the memspace is not modified.
182+
///
183+
umf_result_t umfMemspaceUserFilter(umf_memspace_handle_t memspace,
184+
umf_memspace_filter_func_t filter,
185+
void *args);
134186
#ifdef __cplusplus
135187
}
136188
#endif

include/umf/memtarget.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ umf_result_t umfMemtargetGetType(umf_const_memtarget_handle_t hMemtarget,
3939
umf_result_t umfMemtargetGetCapacity(umf_const_memtarget_handle_t hMemtarget,
4040
size_t *capacity);
4141

42+
/// \brief Get ID of the memory target in bytes.
43+
/// \param hMemtarget handle to the memory target
44+
/// \param id [out] id of the memory target
45+
/// \return UMF_RESULT_SUCCESS on success or appropriate error code on failure.
46+
umf_result_t umfMemtargetGetId(umf_const_memtarget_handle_t hMemtarget,
47+
unsigned *id);
48+
4249
#ifdef __cplusplus
4350
}
4451
#endif

src/libumf.def.in

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,18 @@ EXPORTS
4040
umfMempolicyDestroy
4141
umfMempolicySetCustomSplitPartitions
4242
umfMempolicySetInterleavePartSize
43-
umfMemspaceNew
43+
umfMemspaceClone
4444
umfMemspaceDestroy
45-
umfMemspaceMemtargetNum
46-
umfMemspaceMemtargetGet
47-
umfMemtargetGetCapacity
45+
umfMemspaceFilterByCapacity
46+
umfMemspaceFilterById
47+
umfMemspaceNew
4848
umfMemspaceMemtargetAdd
49+
umfMemspaceMemtargetGet
50+
umfMemspaceMemtargetNum
4951
umfMemspaceMemtargetRemove
52+
umfMemspaceUserFilter
53+
umfMemtargetGetCapacity
54+
umfMemtargetGetId
5055
umfMemtargetGetType
5156
umfOpenIPCHandle
5257
umfPoolAlignedMalloc

src/libumf.map.in

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,19 @@ UMF_1.0 {
3434
umfMempolicyDestroy;
3535
umfMempolicySetCustomSplitPartitions;
3636
umfMempolicySetInterleavePartSize;
37-
umfMemspaceNew;
37+
umfMemspaceClone;
3838
umfMemspaceCreateFromNumaArray;
3939
umfMemspaceDestroy;
40+
umfMemspaceFilterByCapacity;
41+
umfMemspaceFilterById;
42+
umfMemspaceNew;
4043
umfMemspaceMemtargetAdd;
41-
umfMemspaceMemtargetRemove;
42-
umfMemspaceMemtargetNum;
4344
umfMemspaceMemtargetGet;
45+
umfMemspaceMemtargetNum;
46+
umfMemspaceMemtargetRemove;
47+
umfMemspaceUserFilter;
4448
umfMemtargetGetCapacity;
49+
umfMemtargetGetId;
4550
umfMemtargetGetType;
4651
umfOpenIPCHandle;
4752
umfPoolAlignedMalloc;

src/memspace.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,134 @@ umfMemspaceMemtargetRemove(umf_memspace_handle_t hMemspace,
426426
hMemspace->size--;
427427
return UMF_RESULT_SUCCESS;
428428
}
429+
430+
static umf_result_t MemspaceFilter(umf_memspace_handle_t memspace,
431+
umf_memspace_filter_func_t filter,
432+
void *args) {
433+
434+
if (!memspace || !filter) {
435+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
436+
}
437+
size_t idx = 0;
438+
umf_result_t ret;
439+
umf_memtarget_handle_t *nodesToRemove =
440+
umf_ba_global_alloc(sizeof(*nodesToRemove) * memspace->size);
441+
442+
if (!nodesToRemove) {
443+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
444+
}
445+
446+
for (size_t i = 0; i < memspace->size; i++) {
447+
int r = filter(memspace, memspace->nodes[i], args);
448+
if (r < 0) {
449+
return (umf_result_t)r;
450+
} else if (r == 0) {
451+
nodesToRemove[idx++] = memspace->nodes[i];
452+
}
453+
}
454+
455+
size_t i = 0;
456+
for (; i < idx; i++) {
457+
ret = umfMemspaceMemtargetRemove(memspace, nodesToRemove[i]);
458+
if (ret != UMF_RESULT_SUCCESS) {
459+
goto re_add;
460+
}
461+
}
462+
463+
umf_ba_global_free(nodesToRemove);
464+
return UMF_RESULT_SUCCESS;
465+
466+
re_add:
467+
for (size_t j = 0; j < i; j++) {
468+
umf_result_t ret2 = umfMemspaceMemtargetAdd(memspace, nodesToRemove[j]);
469+
if (ret2 != UMF_RESULT_SUCCESS) {
470+
ret =
471+
UMF_RESULT_ERROR_UNKNOWN; // indicate that memspace is corrupted
472+
break;
473+
}
474+
}
475+
476+
umf_ba_global_free(nodesToRemove);
477+
return ret;
478+
}
479+
480+
umf_result_t umfMemspaceUserFilter(umf_memspace_handle_t memspace,
481+
umf_memspace_filter_func_t filter,
482+
void *args) {
483+
484+
if (!memspace || !filter) {
485+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
486+
}
487+
umf_result_t ret = MemspaceFilter(memspace, filter, args);
488+
489+
if (ret < 0) {
490+
return UMF_RESULT_ERROR_USER_SPECIFIC;
491+
}
492+
493+
return ret;
494+
}
495+
496+
struct filter_by_id_args {
497+
unsigned *ids;
498+
size_t size;
499+
};
500+
501+
int filterById(umf_const_memspace_handle_t memspace,
502+
umf_const_memtarget_handle_t target, void *args) {
503+
if (!memspace && !target && !args) {
504+
return -UMF_RESULT_ERROR_INVALID_ARGUMENT;
505+
}
506+
507+
struct filter_by_id_args *filterArgs = args;
508+
for (size_t i = 0; i < filterArgs->size; i++) {
509+
unsigned id;
510+
umf_result_t ret = umfMemtargetGetId(target, &id);
511+
if (ret != UMF_RESULT_SUCCESS) {
512+
return -ret;
513+
}
514+
515+
if (id == filterArgs->ids[i]) {
516+
return 1;
517+
}
518+
}
519+
return 0;
520+
}
521+
522+
int filterByCapacity(umf_const_memspace_handle_t memspace,
523+
umf_const_memtarget_handle_t target, void *args) {
524+
if (!memspace && !target && !args) {
525+
return -UMF_RESULT_ERROR_INVALID_ARGUMENT;
526+
}
527+
528+
size_t capacity;
529+
umf_result_t ret = umfMemtargetGetCapacity(target, &capacity);
530+
if (ret != UMF_RESULT_SUCCESS) {
531+
return -ret;
532+
}
533+
534+
size_t *targetCapacity = args;
535+
return capacity >= *targetCapacity ? 1 : 0;
536+
}
537+
538+
umf_result_t umfMemspaceFilterById(umf_memspace_handle_t memspace,
539+
unsigned *ids, size_t size) {
540+
if (!memspace || !ids || size == 0) {
541+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
542+
}
543+
544+
struct filter_by_id_args args = {ids, size};
545+
int ret = MemspaceFilter(memspace, &filterById, &args);
546+
547+
return ret < 0 ? -ret : ret;
548+
}
549+
550+
umf_result_t umfMemspaceFilterByCapacity(umf_memspace_handle_t memspace,
551+
size_t capacity) {
552+
if (!memspace) {
553+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
554+
}
555+
556+
int ret = MemspaceFilter(memspace, &filterByCapacity, &capacity);
557+
558+
return ret < 0 ? -ret : ret;
559+
}

src/memspace_internal.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ struct umf_memspace_t {
2424
umf_memtarget_handle_t *nodes;
2525
};
2626

27-
///
28-
/// \brief Clones memspace
29-
///
30-
umf_result_t umfMemspaceClone(umf_const_memspace_handle_t hMemspace,
31-
umf_memspace_handle_t *outHandle);
32-
3327
typedef umf_result_t (*umfGetPropertyFn)(umf_const_memtarget_handle_t,
3428
uint64_t *);
3529

src/memtarget.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ umf_result_t umfMemtargetGetLatency(umf_memtarget_handle_t srcMemoryTarget,
107107
dstMemoryTarget->priv, latency);
108108
}
109109

110+
umf_result_t umfMemtargetGetId(umf_const_memtarget_handle_t hMemtarget,
111+
unsigned *id) {
112+
if (!hMemtarget || !id) {
113+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
114+
}
115+
116+
return hMemtarget->ops->get_id(hMemtarget->priv, id);
117+
}
110118
umf_result_t umfMemtargetGetType(umf_const_memtarget_handle_t memoryTarget,
111119
umf_memtarget_type_t *type) {
112120
if (!memoryTarget || !type) {

src/memtarget_ops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typedef struct umf_memtarget_ops_t {
4545
size_t *latency);
4646

4747
umf_result_t (*get_type)(void *memoryTarget, umf_memtarget_type_t *type);
48+
umf_result_t (*get_id)(void *memoryTarget, unsigned *type);
4849
umf_result_t (*compare)(void *memTarget, void *otherMemTarget, int *result);
4950

5051
} umf_memtarget_ops_t;

src/memtargets/memtarget_numa.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,15 @@ static umf_result_t numa_get_type(void *memTarget, umf_memtarget_type_t *type) {
326326
return UMF_RESULT_SUCCESS;
327327
}
328328

329+
static umf_result_t numa_get_id(void *memTarget, unsigned *id) {
330+
if (!memTarget || !id) {
331+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
332+
}
333+
334+
*id = ((struct numa_memtarget_t *)memTarget)->physical_id;
335+
return UMF_RESULT_SUCCESS;
336+
}
337+
329338
static umf_result_t numa_compare(void *memTarget, void *otherMemTarget,
330339
int *result) {
331340
if (!memTarget || !otherMemTarget || !result) {
@@ -350,6 +359,7 @@ struct umf_memtarget_ops_t UMF_MEMTARGET_NUMA_OPS = {
350359
.get_bandwidth = numa_get_bandwidth,
351360
.get_latency = numa_get_latency,
352361
.get_type = numa_get_type,
362+
.get_id = numa_get_id,
353363
.compare = numa_compare,
354364
.memory_provider_create_from_memspace =
355365
numa_memory_provider_create_from_memspace};

src/provider/provider_level_zero.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,7 @@ static void ze_memory_provider_finalize(void *provider) {
188188
return;
189189
}
190190

191-
util_init_once(&ze_is_initialized, init_ze_global_state);
192191
umf_ba_global_free(provider);
193-
194-
// portable version of "ze_is_initialized = UTIL_ONCE_FLAG_INIT;"
195-
static UTIL_ONCE_FLAG is_initialized = UTIL_ONCE_FLAG_INIT;
196-
memcpy(&ze_is_initialized, &is_initialized, sizeof(ze_is_initialized));
197192
}
198193

199194
static bool use_relaxed_allocation(ze_memory_provider_t *ze_provider,

test/memspaces/memspace_fixtures.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ struct memspaceProviderTest : ::memspaceGetTest {
102102
umf_memory_provider_handle_t hProvider = nullptr;
103103
};
104104

105+
struct numaNodesCapacityTest : numaNodesTest {
106+
void SetUp() override {
107+
numaNodesTest::SetUp();
108+
109+
for (auto nodeId : nodeIds) {
110+
capacities.push_back(numa_node_size64(nodeId, nullptr));
111+
}
112+
}
113+
114+
std::vector<size_t> capacities;
115+
};
116+
105117
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(memspaceGetTest);
106118
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(memspaceProviderTest);
107119

0 commit comments

Comments
 (0)