Skip to content

Commit fd6a18a

Browse files
committed
add memspace filter functions
1 parent ddd572b commit fd6a18a

File tree

14 files changed

+400
-25
lines changed

14 files changed

+400
-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 hMemspace,
152+
umf_const_memtarget_handle_t hMemtarget, 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 hMemspace,
163+
unsigned *ids, size_t size);
164+
165+
/// \brief Filters out memory targets that capacity is less than specified size.
166+
///
167+
/// \param hMemspace 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 hMemspace,
173+
size_t size);
174+
175+
/// \brief Filters out memory targets based on user provided function
176+
///
177+
/// \param hMemspace 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 hMemspace,
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 physical ID of the memory target.
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: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,146 @@ umfMemspaceMemtargetRemove(umf_memspace_handle_t hMemspace,
426426
hMemspace->size--;
427427
return UMF_RESULT_SUCCESS;
428428
}
429+
430+
// Helper function - returns zero on success, negative in case of error in filter function
431+
// and positive error code, in case of other errors.
432+
static int umfMemspaceFilterHelper(umf_memspace_handle_t memspace,
433+
umf_memspace_filter_func_t filter,
434+
void *args) {
435+
436+
if (!memspace || !filter) {
437+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
438+
}
439+
size_t idx = 0;
440+
int ret;
441+
umf_memtarget_handle_t *nodesToRemove =
442+
umf_ba_global_alloc(sizeof(*nodesToRemove) * memspace->size);
443+
444+
if (!nodesToRemove) {
445+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
446+
}
447+
448+
for (size_t i = 0; i < memspace->size; i++) {
449+
ret = filter(memspace, memspace->nodes[i], args);
450+
if (ret < 0) {
451+
LOG_ERR("filter function failed");
452+
goto free_mem;
453+
} else if (ret == 0) {
454+
nodesToRemove[idx++] = memspace->nodes[i];
455+
}
456+
}
457+
458+
size_t i = 0;
459+
for (; i < idx; i++) {
460+
ret = umfMemspaceMemtargetRemove(memspace, nodesToRemove[i]);
461+
if (ret != UMF_RESULT_SUCCESS) {
462+
goto re_add;
463+
}
464+
}
465+
466+
umf_ba_global_free(nodesToRemove);
467+
return UMF_RESULT_SUCCESS;
468+
469+
re_add:
470+
// If target removal failed, add back previously removed targets.
471+
for (size_t j = 0; j < i; j++) {
472+
umf_result_t ret2 = umfMemspaceMemtargetAdd(memspace, nodesToRemove[j]);
473+
if (ret2 != UMF_RESULT_SUCCESS) {
474+
ret =
475+
UMF_RESULT_ERROR_UNKNOWN; // indicate that memspace is corrupted
476+
break;
477+
}
478+
}
479+
free_mem:
480+
umf_ba_global_free(nodesToRemove);
481+
return ret;
482+
}
483+
484+
umf_result_t umfMemspaceUserFilter(umf_memspace_handle_t memspace,
485+
umf_memspace_filter_func_t filter,
486+
void *args) {
487+
488+
if (!memspace || !filter) {
489+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
490+
}
491+
int ret = umfMemspaceFilterHelper(memspace, filter, args);
492+
493+
if (ret < 0) {
494+
return UMF_RESULT_ERROR_USER_SPECIFIC;
495+
}
496+
497+
return ret;
498+
}
499+
500+
/*
501+
* Predefined filter callbacks returns umf_return codes as negative value
502+
* as negative only value are treated as an error. umfMemspaceFilter will passthru this error code
503+
* so and calling filter function has to translate this code to positive umf_return code.
504+
*/
505+
506+
typedef struct filter_by_id_args {
507+
unsigned *ids;
508+
size_t size;
509+
} filter_by_id_args_t;
510+
511+
static int filterById(umf_const_memspace_handle_t memspace,
512+
umf_const_memtarget_handle_t target, void *args) {
513+
if (!memspace && !target && !args) {
514+
return -UMF_RESULT_ERROR_INVALID_ARGUMENT;
515+
}
516+
517+
filter_by_id_args_t *filterArgs = args;
518+
for (size_t i = 0; i < filterArgs->size; i++) {
519+
unsigned id;
520+
umf_result_t ret = umfMemtargetGetId(target, &id);
521+
if (ret != UMF_RESULT_SUCCESS) {
522+
return -ret;
523+
}
524+
525+
if (id == filterArgs->ids[i]) {
526+
return 1;
527+
}
528+
}
529+
return 0;
530+
}
531+
532+
static int filterByCapacity(umf_const_memspace_handle_t memspace,
533+
umf_const_memtarget_handle_t target, void *args) {
534+
if (!memspace && !target && !args) {
535+
return -UMF_RESULT_ERROR_INVALID_ARGUMENT;
536+
}
537+
538+
size_t capacity;
539+
umf_result_t ret = umfMemtargetGetCapacity(target, &capacity);
540+
if (ret != UMF_RESULT_SUCCESS) {
541+
return -ret;
542+
}
543+
544+
size_t *targetCapacity = args;
545+
return capacity >= *targetCapacity ? 1 : 0;
546+
}
547+
548+
umf_result_t umfMemspaceFilterById(umf_memspace_handle_t memspace,
549+
unsigned *ids, size_t size) {
550+
if (!memspace || !ids || size == 0) {
551+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
552+
}
553+
554+
filter_by_id_args_t args = {ids, size};
555+
int ret = umfMemspaceFilterHelper(memspace, &filterById, &args);
556+
557+
// if umfMemspaceFilter() returned negative umf_result change it to positive
558+
return ret < 0 ? -ret : ret;
559+
}
560+
561+
umf_result_t umfMemspaceFilterByCapacity(umf_memspace_handle_t memspace,
562+
size_t capacity) {
563+
if (!memspace) {
564+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
565+
}
566+
567+
int ret = umfMemspaceFilterHelper(memspace, &filterByCapacity, &capacity);
568+
569+
// if umfMemspaceFilter() returned negative umf_result change it to positive
570+
return ret < 0 ? -ret : ret;
571+
}

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-
utils_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)