From bc467c7afee9e5d5536f0edbff514a56d2a5b0f0 Mon Sep 17 00:00:00 2001 From: Igor Chorazewicz Date: Tue, 27 Jun 2023 16:24:10 +0000 Subject: [PATCH] [uma] extend error codes with METADATA and DATA provider specific errors. --- .../include/uma/base.h | 13 +- .../include/uma/memoryPoolAPI.cpp | 206 ++++++++++++++++++ .../include/uma/memory_provider.h | 3 +- .../memoryPoolAPI.cpp | 3 +- .../memoryProviderAPI.cpp | 3 +- 5 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 source/common/unified_memory_allocation/include/uma/memoryPoolAPI.cpp diff --git a/source/common/unified_memory_allocation/include/uma/base.h b/source/common/unified_memory_allocation/include/uma/base.h index 7d5d34f987..1e1b6ba634 100644 --- a/source/common/unified_memory_allocation/include/uma/base.h +++ b/source/common/unified_memory_allocation/include/uma/base.h @@ -39,13 +39,16 @@ enum uma_result_t { UMA_RESULT_ERROR_POOL_SPECIFIC = 2, ///< A pool specific warning/error has been reported and can be ///< Retrieved via the umaPoolGetLastResult entry point. - UMA_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC = - 3, ///< A provider specific warning/error has been reported and can be + UMA_RESULT_ERROR_METADATA_MEMORY_PROVIDER_SPECIFIC = + 3, ///< A metadata provider specific warning/error has been reported and can be ///< Retrieved via the umaMemoryProviderGetLastResult entry point. + UMA_RESULT_ERROR_DATA_MEMORY_PROVIDER_SPECIFIC = + 4, ///< A data provider specific warning/error has been reported and can be + ///< Retrieved via the umaMemoryProviderGetLastNativeError entry point. UMA_RESULT_ERROR_INVALID_ARGUMENT = - 4, ///< Generic error code for invalid arguments - UMA_RESULT_ERROR_INVALID_ALIGNMENT = 5, /// Invalid alignment of an argument - UMA_RESULT_ERROR_NOT_SUPPORTED = 6, /// Operation not supported + 5, ///< Generic error code for invalid arguments + UMA_RESULT_ERROR_INVALID_ALIGNMENT = 6, /// Invalid alignment of an argument + UMA_RESULT_ERROR_NOT_SUPPORTED = 7, /// Operation not supported UMA_RESULT_ERROR_UNKNOWN = 0x7ffffffe ///< Unknown or internal error }; diff --git a/source/common/unified_memory_allocation/include/uma/memoryPoolAPI.cpp b/source/common/unified_memory_allocation/include/uma/memoryPoolAPI.cpp new file mode 100644 index 0000000000..b64085825f --- /dev/null +++ b/source/common/unified_memory_allocation/include/uma/memoryPoolAPI.cpp @@ -0,0 +1,206 @@ +// Copyright (C) 2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// This file contains tests for UMA pool API + +#include "pool.h" +#include "pool.hpp" +#include "provider.h" +#include "provider.hpp" + +#include "memoryPool.hpp" +#include "uma/memory_provider.h" + +#include +#include +#include + +using uma_test::test; + +TEST_F(test, memoryPoolTrace) { + static std::unordered_map poolCalls; + static std::unordered_map providerCalls; + auto tracePool = [](const char *name) { poolCalls[name]++; }; + auto traceProvider = [](const char *name) { providerCalls[name]++; }; + + auto nullProvider = uma_test::wrapProviderUnique(nullProviderCreate()); + auto tracingProvider = uma_test::wrapProviderUnique( + traceProviderCreate(nullProvider.get(), traceProvider)); + auto provider = tracingProvider.get(); + + auto [ret, proxyPool] = + uma::poolMakeUnique(provider, nullptr); + ASSERT_EQ(ret, UMA_RESULT_SUCCESS); + + auto tracingPool = + uma_test::wrapPoolUnique(tracePoolCreate(proxyPool.get(), tracePool)); + + size_t pool_call_count = 0; + size_t provider_call_count = 0; + + umaPoolMalloc(tracingPool.get(), 0); + ASSERT_EQ(poolCalls["malloc"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls["alloc"], 1); + ASSERT_EQ(providerCalls.size(), ++provider_call_count); + + umaPoolFree(tracingPool.get(), nullptr); + ASSERT_EQ(poolCalls["free"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls["free"], 1); + ASSERT_EQ(providerCalls.size(), ++provider_call_count); + + umaPoolCalloc(tracingPool.get(), 0, 0); + ASSERT_EQ(poolCalls["calloc"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls["alloc"], 2); + ASSERT_EQ(providerCalls.size(), provider_call_count); + + umaPoolRealloc(tracingPool.get(), nullptr, 0); + ASSERT_EQ(poolCalls["realloc"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls.size(), provider_call_count); + + umaPoolAlignedMalloc(tracingPool.get(), 0, 0); + ASSERT_EQ(poolCalls["aligned_malloc"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls["alloc"], 3); + ASSERT_EQ(providerCalls.size(), provider_call_count); + + umaPoolMallocUsableSize(tracingPool.get(), nullptr); + ASSERT_EQ(poolCalls["malloc_usable_size"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls.size(), provider_call_count); + + ret = umaPoolGetLastResult(tracingPool.get(), nullptr); + ASSERT_EQ(ret, UMA_RESULT_SUCCESS); + + ASSERT_EQ(poolCalls["get_last_result"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + ASSERT_EQ(providerCalls["get_last_result"], 1); + ASSERT_EQ(providerCalls.size(), ++provider_call_count); + + auto p = umaPoolGetDataMemoryProvider(tracingPool.get()); + ASSERT_NE(p, nullptr); + ASSERT_EQ(poolCalls["get_data_memory_provider"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); + + p = umaPoolGetMetadataMemoryProvider(tracingPool.get()); + ASSERT_EQ(poolCalls["get_metadata_memory_provider"], 1); + ASSERT_EQ(poolCalls.size(), ++pool_call_count); +} + +TEST_F(test, retrieveMemoryProviders) { + struct memory_provider : uma_test::provider_base { + const char *name; + uma_result_t initialize(const char *name) { + this->name = name; + return UMA_RESULT_SUCCESS; + } + const char *get_name() noexcept { return name; } + }; + + auto [ret1, data_provider] = + uma::memoryProviderMakeUnique("data_provider"); + auto [ret2, metadata_provider] = + uma::memoryProviderMakeUnique("metadata_provider"); + + ASSERT_EQ(ret1, UMA_RESULT_SUCCESS); + ASSERT_EQ(ret2, UMA_RESULT_SUCCESS); + + auto [ret, pool] = uma::poolMakeUnique( + data_provider.get(), metadata_provider.get()); + + ASSERT_EQ(ret, UMA_RESULT_SUCCESS); + + uma_memory_provider_handle_t ret_data_provider = + umaPoolGetDataMemoryProvider(pool.get()); + uma_memory_provider_handle_t ret_metadata_provider = + umaPoolGetMetadataMemoryProvider(pool.get()); + + // comapre names of the providers: handles might point to a different object if providers are wrapped by memory tracking-provider + ASSERT_EQ(std::string_view(umaMemoryProviderGetName(data_provider.get())), + std::string_view(umaMemoryProviderGetName(ret_data_provider))); + ASSERT_EQ( + std::string_view(umaMemoryProviderGetName(metadata_provider.get())), + std::string_view(umaMemoryProviderGetName(ret_metadata_provider))); +} + +template +static auto +makePool(std::function makeProvider) { + auto providerUnique = makeProvider(); + uma_memory_provider_handle_t provider = providerUnique.get(); + auto pool = uma::poolMakeUnique(provider, nullptr).second; + auto dtor = [provider = + providerUnique.release()](uma_memory_pool_handle_t hPool) { + umaPoolDestroy(hPool); + umaMemoryProviderDestroy(provider); + }; + return uma::pool_unique_handle_t(pool.release(), std::move(dtor)); +} + +INSTANTIATE_TEST_SUITE_P(mallocPoolTest, umaPoolTest, ::testing::Values([] { + return makePool([] { + return uma_test::wrapProviderUnique( + nullProviderCreate()); + }); + })); + +INSTANTIATE_TEST_SUITE_P( + mallocProviderPoolTest, umaPoolTest, ::testing::Values([] { + return makePool([] { + return uma::memoryProviderMakeUnique() + .second; + }); + })); + +INSTANTIATE_TEST_SUITE_P( + mallocMultiPoolTest, umaMultiPoolTest, ::testing::Values([] { + return makePool([] { + return uma::memoryProviderMakeUnique() + .second; + }); + })); + +////////////////// Negative test cases ///////////////// + +TEST_F(test, memoryPoolInvalidProvidersNullptr) { + auto ret = uma::poolMakeUnique(nullptr, nullptr); + ASSERT_EQ(ret.first, UMA_RESULT_ERROR_INVALID_ARGUMENT); +} + +struct poolInitializeTest : uma_test::test, + ::testing::WithParamInterface {}; + +INSTANTIATE_TEST_SUITE_P( + poolInitializeTest, poolInitializeTest, + ::testing::Values(UMA_RESULT_ERROR_OUT_OF_HOST_MEMORY, + UMA_RESULT_ERROR_POOL_SPECIFIC, + UMA_RESULT_ERROR_METADATA_MEMORY_PROVIDER_SPECIFIC, + UMA_RESULT_ERROR_DATA_MEMORY_PROVIDER_SPECIFIC + UMA_RESULT_ERROR_INVALID_ARGUMENT, + UMA_RESULT_ERROR_UNKNOWN)); + +TEST_P(poolInitializeTest, errorPropagation) { + auto nullProvider = uma_test::wrapProviderUnique(nullProviderCreate()); + struct pool : public uma_test::pool_base { + uma_result_t initialize(uma_memory_provider_handle_t data_provider, + uma_memory_provider_handle_t metadata_provider, + uma_result_t errorToReturn) noexcept { + return errorToReturn; + } + }; + auto ret = uma::poolMakeUnique(nullProvider.get(), nullptr, + this->GetParam()); + ASSERT_EQ(ret.first, this->GetParam()); + ASSERT_EQ(ret.second, nullptr); +} diff --git a/source/common/unified_memory_allocation/include/uma/memory_provider.h b/source/common/unified_memory_allocation/include/uma/memory_provider.h index 7f3507289e..7d203b047a 100644 --- a/source/common/unified_memory_allocation/include/uma/memory_provider.h +++ b/source/common/unified_memory_allocation/include/uma/memory_provider.h @@ -63,7 +63,8 @@ enum uma_result_t umaMemoryProviderFree(uma_memory_provider_handle_t hProvider, /// /// \brief Retrieve string representation of the underlying provider specific /// result reported by the last API that returned -/// UMA_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC. Allows for a provider +/// UMA_RESULT_ERROR_METADATA_MEMORY_PROVIDER_SPECIFIC or +/// UMA_RESULT_ERROR_DATA_MEMORY_PROVIDER_SPECIFIC. Allows for a provider /// independent way to return a provider specific result. /// /// \details diff --git a/test/unified_memory_allocation/memoryPoolAPI.cpp b/test/unified_memory_allocation/memoryPoolAPI.cpp index a4dc60277e..1faa8a62c7 100644 --- a/test/unified_memory_allocation/memoryPoolAPI.cpp +++ b/test/unified_memory_allocation/memoryPoolAPI.cpp @@ -185,7 +185,8 @@ INSTANTIATE_TEST_SUITE_P( poolInitializeTest, poolInitializeTest, ::testing::Values(UMA_RESULT_ERROR_OUT_OF_HOST_MEMORY, UMA_RESULT_ERROR_POOL_SPECIFIC, - UMA_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC, + UMA_RESULT_ERROR_METADATA_MEMORY_PROVIDER_SPECIFIC, + UMA_RESULT_ERROR_DATA_MEMORY_PROVIDER_SPECIFIC, UMA_RESULT_ERROR_INVALID_ARGUMENT, UMA_RESULT_ERROR_UNKNOWN)); diff --git a/test/unified_memory_allocation/memoryProviderAPI.cpp b/test/unified_memory_allocation/memoryProviderAPI.cpp index 09a7726250..37ec352062 100644 --- a/test/unified_memory_allocation/memoryProviderAPI.cpp +++ b/test/unified_memory_allocation/memoryProviderAPI.cpp @@ -76,7 +76,8 @@ INSTANTIATE_TEST_SUITE_P( providerInitializeTest, providerInitializeTest, ::testing::Values(UMA_RESULT_ERROR_OUT_OF_HOST_MEMORY, UMA_RESULT_ERROR_POOL_SPECIFIC, - UMA_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC, + UMA_RESULT_ERROR_METADATA_MEMORY_PROVIDER_SPECIFIC, + UMA_RESULT_ERROR_DATA_MEMORY_PROVIDER_SPECIFIC, UMA_RESULT_ERROR_INVALID_ARGUMENT, UMA_RESULT_ERROR_UNKNOWN));