diff --git a/include/umf/memtarget.h b/include/umf/memtarget.h index 2a7850015..a4902b98d 100644 --- a/include/umf/memtarget.h +++ b/include/umf/memtarget.h @@ -10,6 +10,7 @@ #ifndef UMF_MEMTARGET_H #define UMF_MEMTARGET_H 1 +#include #include #ifdef __cplusplus @@ -31,6 +32,13 @@ typedef enum umf_memtarget_type_t { umf_result_t umfMemtargetGetType(umf_const_memtarget_handle_t hMemtarget, umf_memtarget_type_t *type); +/// \brief Get size of the memory target in bytes. +/// \param hMemtarget handle to the memory target +/// \param capacity [out] capacity of the memory target +/// \return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfMemtargetGetCapacity(umf_const_memtarget_handle_t hMemtarget, + size_t *capacity); + #ifdef __cplusplus } #endif diff --git a/src/libumf.def.in b/src/libumf.def.in index cb8d4d74c..f69d7ac1a 100644 --- a/src/libumf.def.in +++ b/src/libumf.def.in @@ -43,6 +43,7 @@ EXPORTS umfMemspaceDestroy umfMemspaceMemtargetNum umfMemspaceMemtargetGet + umfMemtargetGetCapacity umfMemtargetGetType umfOpenIPCHandle umfPoolAlignedMalloc diff --git a/src/libumf.map.in b/src/libumf.map.in index 7c2002a1f..09be6dfe9 100644 --- a/src/libumf.map.in +++ b/src/libumf.map.in @@ -37,6 +37,7 @@ UMF_1.0 { umfMemspaceDestroy; umfMemspaceMemtargetNum; umfMemspaceMemtargetGet; + umfMemtargetGetCapacity; umfMemtargetGetType; umfOpenIPCHandle; umfPoolAlignedMalloc; diff --git a/src/memspace.c b/src/memspace.c index 01e20e617..bce5fb6ee 100644 --- a/src/memspace.c +++ b/src/memspace.c @@ -173,10 +173,8 @@ static int propertyCmp(const void *a, const void *b) { } } -umf_result_t -umfMemspaceSortDesc(umf_memspace_handle_t hMemspace, - umf_result_t (*getProperty)(umf_memtarget_handle_t node, - uint64_t *property)) { +umf_result_t umfMemspaceSortDesc(umf_memspace_handle_t hMemspace, + umfGetPropertyFn getProperty) { if (!hMemspace || !getProperty) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; } diff --git a/src/memspace_internal.h b/src/memspace_internal.h index 0cb28b92f..8f678ff7d 100644 --- a/src/memspace_internal.h +++ b/src/memspace_internal.h @@ -30,7 +30,8 @@ struct umf_memspace_t { umf_result_t umfMemspaceClone(umf_const_memspace_handle_t hMemspace, umf_memspace_handle_t *outHandle); -typedef umf_result_t (*umfGetPropertyFn)(umf_memtarget_handle_t, uint64_t *); +typedef umf_result_t (*umfGetPropertyFn)(umf_const_memtarget_handle_t, + uint64_t *); /// /// \brief Sorts memspace by getProperty() in descending order diff --git a/src/memtarget.c b/src/memtarget.c index 4c851a772..c85630769 100644 --- a/src/memtarget.c +++ b/src/memtarget.c @@ -76,7 +76,7 @@ umf_result_t umfMemtargetClone(umf_memtarget_handle_t memoryTarget, return UMF_RESULT_SUCCESS; } -umf_result_t umfMemtargetGetCapacity(umf_memtarget_handle_t memoryTarget, +umf_result_t umfMemtargetGetCapacity(umf_const_memtarget_handle_t memoryTarget, size_t *capacity) { if (!memoryTarget || !capacity) { return UMF_RESULT_ERROR_INVALID_ARGUMENT; diff --git a/src/memtarget_internal.h b/src/memtarget_internal.h index bad309723..2e1547e07 100644 --- a/src/memtarget_internal.h +++ b/src/memtarget_internal.h @@ -30,8 +30,7 @@ void umfMemtargetDestroy(umf_memtarget_handle_t memoryTarget); umf_result_t umfMemtargetClone(umf_memtarget_handle_t memoryTarget, umf_memtarget_handle_t *outHandle); -umf_result_t umfMemtargetGetCapacity(umf_memtarget_handle_t memoryTarget, - size_t *capacity); + umf_result_t umfMemtargetGetBandwidth(umf_memtarget_handle_t srcMemoryTarget, umf_memtarget_handle_t dstMemoryTarget, size_t *bandwidth); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 59c76fe31..962d1e126 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -221,7 +221,7 @@ if(LINUX AND (NOT UMF_DISABLE_HWLOC)) # OS-specific functions are implemented add_umf_test( NAME memtarget SRCS memspaces/memtarget.cpp - LIBS ${LIBNUMA_LIBRARIES}) + LIBS ${LIBNUMA_LIBRARIES} ${LIBHWLOC_LIBRARIES}) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND UMF_BUILD_FUZZTESTS) add_subdirectory(fuzz) endif() diff --git a/test/memspaces/memtarget.cpp b/test/memspaces/memtarget.cpp index 84001a705..c4cc80a8f 100644 --- a/test/memspaces/memtarget.cpp +++ b/test/memspaces/memtarget.cpp @@ -2,6 +2,7 @@ // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include "memspace_fixtures.hpp" #include "memspace_helpers.hpp" #include @@ -13,17 +14,53 @@ using umf_test::test; TEST_F(test, memTargetNuma) { auto memspace = umfMemspaceHostAllGet(); ASSERT_NE(memspace, nullptr); - + umf_memtarget_type_t type; for (size_t i = 0; i < umfMemspaceMemtargetNum(memspace); i++) { auto hTarget = umfMemspaceMemtargetGet(memspace, i); ASSERT_NE(hTarget, nullptr); - umf_memtarget_type_t type; auto ret = umfMemtargetGetType(hTarget, &type); EXPECT_EQ(ret, UMF_RESULT_SUCCESS); EXPECT_EQ(type, UMF_MEMTARGET_TYPE_NUMA); } } +TEST_F(numaNodesTest, getCapacity) { + auto memspace = umfMemspaceHostAllGet(); + ASSERT_NE(memspace, nullptr); + std::vector capacities; + for (auto nodeId : nodeIds) { + capacities.push_back(numa_node_size64(nodeId, nullptr)); + } + + for (size_t i = 0; i < umfMemspaceMemtargetNum(memspace); i++) { + auto hTarget = umfMemspaceMemtargetGet(memspace, i); + ASSERT_NE(hTarget, nullptr); + size_t capacity; + auto ret = umfMemtargetGetCapacity(hTarget, &capacity); + EXPECT_EQ(ret, UMF_RESULT_SUCCESS); + auto it = std::find(capacities.begin(), capacities.end(), capacity); + EXPECT_NE(it, capacities.end()); + if (it != capacities.end()) { + capacities.erase(it); + } + } + ASSERT_EQ(capacities.size(), 0); +} + +TEST_F(numaNodesTest, getCapacityInvalid) { + auto memspace = umfMemspaceHostAllGet(); + ASSERT_NE(memspace, nullptr); + size_t capacity; + auto ret = umfMemtargetGetCapacity(NULL, &capacity); + EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + ret = umfMemtargetGetCapacity(NULL, NULL); + EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); + auto hTarget = umfMemspaceMemtargetGet(memspace, 0); + ASSERT_NE(hTarget, nullptr); + ret = umfMemtargetGetCapacity(hTarget, NULL); + EXPECT_EQ(ret, UMF_RESULT_ERROR_INVALID_ARGUMENT); +} + TEST_F(test, memTargetInvalid) { auto memspace = umfMemspaceHostAllGet(); ASSERT_NE(memspace, nullptr);