Skip to content

Verify if the provider supports the split operation #1465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions .github/workflows/reusable_compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,21 @@ jobs:
- name: Run "tag" UMF tests with latest UMF libs (warnings enabled)
working-directory: ${{github.workspace}}/tag_version/build
# Exclude the test_jemalloc_pool test -
# TODO: add fix for that in v1.0.1
run: >
UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
LD_LIBRARY_PATH=${{github.workspace}}/latest_version/build/lib/
ctest --verbose
ctest --verbose -E test_jemalloc_pool
- name: Run EXCLUDED tests with filters
working-directory: ${{github.workspace}}/tag_version/build
# Exclude the jemallocPoolName test case of the test_jemalloc_pool test
# TODO: add fix for that in v1.0.1
run: >
UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
LD_LIBRARY_PATH=${{github.workspace}}/latest_version/build/lib/
./test/test_jemalloc_pool --gtest_filter="-*jemallocPoolName*"
# Browse all folders in the examples directory, build them using the
# latest UMF version, and run them, excluding those in the exclude list.
Expand Down Expand Up @@ -220,10 +231,22 @@ jobs:

- name: Run "tag" UMF tests with latest UMF libs (warnings enabled)
working-directory: ${{github.workspace}}/tag_version/build
# Exclude the test_jemalloc_pool test -
# TODO: add fix for that in v1.0.1
run: |
$env:UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
$env:UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
cp ${{github.workspace}}/latest_version/build/bin/Debug/umf.dll ${{github.workspace}}/tag_version/build/bin/Debug/umf.dll
ctest -C Debug --verbose
ctest -C Debug --verbose -E test_jemalloc_pool
- name: Run EXCLUDED tests with filters
working-directory: ${{github.workspace}}/tag_version/build/
# Exclude the jemallocPoolName test case of the test_jemalloc_pool test
# TODO: add fix for that in v1.0.1
run: |
$env:UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
$env:Path = "${{github.workspace}}/tag_version/build/bin/Debug;${{env.VCPKG_BIN_PATH}};$env:Path"
cp ${{github.workspace}}/latest_version/build/bin/Debug/umf.dll ${{github.workspace}}/tag_version/build/bin/Debug/umf.dll
test/Debug/test_jemalloc_pool.exe --gtest_filter="-*jemallocPoolName*"
# Browse all folders in the examples directory, build them using the
# latest UMF version, and run them, excluding those in the exclude list.
Expand Down Expand Up @@ -361,10 +384,21 @@ jobs:
- name: Run "tag" UMF tests with latest UMF libs (warnings enabled)
working-directory: ${{github.workspace}}/tag_version/build
# Exclude the test_jemalloc_pool test -
# TODO: add fix for that in v1.0.1
run: >
UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
LD_LIBRARY_PATH=${{github.workspace}}/latest_version/build/lib/
ctest --verbose -E test_jemalloc_pool
- name: Run EXCLUDED tests with filters
working-directory: ${{github.workspace}}/tag_version/build
# Exclude the jemallocPoolName test case of the test_jemalloc_pool test
# TODO: add fix for that in v1.0.1
run: >
UMF_LOG="level:warning;flush:debug;output:stderr;pid:no"
LD_LIBRARY_PATH=${{github.workspace}}/latest_version/build/lib/
ctest --verbose
./test/test_jemalloc_pool --gtest_filter="-*jemallocPoolName*"
# Browse all folders in the examples directory, build them using the
# latest UMF version, and run them, excluding those in the exclude list.
Expand Down
47 changes: 45 additions & 2 deletions src/pool/pool_jemalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <string.h>

#include "base_alloc_global.h"
#include "memory_provider_internal.h"
#include "provider_tracking.h"
#include "utils_common.h"
#include "utils_concurrency.h"
#include "utils_log.h"
Expand Down Expand Up @@ -272,8 +274,15 @@ static bool arena_extent_split(extent_hooks_t *extent_hooks, void *addr,

jemalloc_memory_pool_t *pool = get_pool_by_arena_index(arena_ind);
assert(pool);
return umfMemoryProviderAllocationSplit(pool->provider, addr, size,
size_a) != UMF_RESULT_SUCCESS;

umf_result_t ret =
umfMemoryProviderAllocationSplit(pool->provider, addr, size, size_a);
if (ret != UMF_RESULT_SUCCESS) {
LOG_ERR("memory provider failed to split a memory region, while "
"jemalloc requires that");
}

return ret != UMF_RESULT_SUCCESS;
}

// arena_extent_merge - an extent merge function conforms to the extent_merge_t type and optionally
Expand Down Expand Up @@ -424,11 +433,45 @@ static void *op_aligned_alloc(void *pool, size_t size, size_t alignment) {
return ptr;
}

// Verify if the memory provider supports the split() operation,
// because jemalloc pool requires that.
static umf_result_t verify_split(umf_memory_provider_handle_t provider) {
// Retrieve the upstream memory provider
umf_memory_provider_handle_t upstream_provider = NULL;
umfTrackingMemoryProviderGetUpstreamProvider(
umfMemoryProviderGetPriv(provider), &upstream_provider);

size_t page_size = 0;
umf_result_t ret =
umfMemoryProviderGetMinPageSize(upstream_provider, NULL, &page_size);
if (ret != UMF_RESULT_SUCCESS) {
return ret;
}

size_t size = 2 * page_size; // use double the page size for the split test
if (UMF_RESULT_ERROR_NOT_SUPPORTED ==
umfMemoryProviderAllocationSplit(upstream_provider, (void *)size, size,
page_size)) {
LOG_ERR("memory provider does not support the split operation, while "
"jemalloc pool requires that");
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

return UMF_RESULT_SUCCESS;
}

static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
const void *params, void **out_pool) {
assert(provider);
assert(out_pool);

// Verify if the memory provider supports the split() operation,
// because jemalloc pool requires that.
umf_result_t ret = verify_split(provider);
if (ret != UMF_RESULT_SUCCESS) {
return ret;
}

extent_hooks_t *pHooks = &arena_extent_hooks;
size_t unsigned_size = sizeof(unsigned);
int n_arenas_set_from_params = 0;
Expand Down
28 changes: 14 additions & 14 deletions test/common/provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,69 +36,69 @@ auto wrapProviderUnique(umf_memory_provider_handle_t hProvider) {
typedef struct provider_base_t {
umf_result_t initialize() noexcept { return UMF_RESULT_SUCCESS; };
umf_result_t alloc(size_t, size_t, void **) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t free([[maybe_unused]] void *ptr,
[[maybe_unused]] size_t size) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t get_last_native_error(const char **, int32_t *) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t
get_recommended_page_size([[maybe_unused]] size_t size,
[[maybe_unused]] size_t *pageSize) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t get_min_page_size([[maybe_unused]] const void *ptr,
[[maybe_unused]] size_t *pageSize) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t get_name(const char **name) noexcept {
*name = "base";
return UMF_RESULT_SUCCESS;
}
umf_result_t ext_purge_lazy([[maybe_unused]] void *ptr,
[[maybe_unused]] size_t size) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t ext_purge_force([[maybe_unused]] void *ptr,
[[maybe_unused]] size_t size) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

umf_result_t ext_allocation_merge([[maybe_unused]] void *lowPtr,
[[maybe_unused]] void *highPtr,
[[maybe_unused]] size_t totalSize) {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}

umf_result_t ext_allocation_split([[maybe_unused]] void *ptr,
[[maybe_unused]] size_t totalSize,
[[maybe_unused]] size_t firstSize) {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t
ext_get_ipc_handle_size([[maybe_unused]] size_t *size) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t
ext_get_ipc_handle([[maybe_unused]] const void *ptr,
[[maybe_unused]] size_t size,
[[maybe_unused]] void *providerIpcData) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t
ext_put_ipc_handle([[maybe_unused]] void *providerIpcData) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t ext_open_ipc_handle([[maybe_unused]] void *providerIpcData,
[[maybe_unused]] void **ptr) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
umf_result_t ext_close_ipc_handle([[maybe_unused]] void *ptr,
[[maybe_unused]] size_t size) noexcept {
return UMF_RESULT_ERROR_UNKNOWN;
return UMF_RESULT_ERROR_NOT_SUPPORTED;
}
virtual ~provider_base_t() = default;
} provider_base_t;
Expand Down
32 changes: 22 additions & 10 deletions test/pools/jemalloc_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,24 +192,36 @@ TEST_F(test, jemallocPoolName) {
umf_jemalloc_pool_params_handle_t params = nullptr;
umf_result_t res = umfJemallocPoolParamsCreate(&params);
EXPECT_EQ(res, UMF_RESULT_SUCCESS);
umf_memory_provider_handle_t provider_handle = nullptr;
umf_memory_pool_handle_t pool = NULL;

struct memory_provider : public umf_test::provider_base_t {};
umf_memory_provider_ops_t provider_ops =
umf_test::providerMakeCOps<memory_provider, void>();
auto providerUnique =
wrapProviderUnique(createProviderChecked(&provider_ops, nullptr));
provider_handle = providerUnique.get();

res =
umfPoolCreate(umfJemallocPoolOps(), provider_handle, params, 0, &pool);
auto nullProvider = nullProviderCreate();
res = umfPoolCreate(umfJemallocPoolOps(), nullProvider, params, 0, &pool);
EXPECT_EQ(res, UMF_RESULT_SUCCESS);
const char *name = nullptr;
res = umfPoolGetName(pool, &name);
EXPECT_EQ(res, UMF_RESULT_SUCCESS);
EXPECT_STREQ(name, "jemalloc");

umfPoolDestroy(pool);
umfMemoryProviderDestroy(nullProvider);
umfJemallocPoolParamsDestroy(params);
}

TEST_F(test, jemallocProviderDoesNotSupportSplit) {
umf_jemalloc_pool_params_handle_t params = nullptr;
umf_result_t res = umfJemallocPoolParamsCreate(&params);
EXPECT_EQ(res, UMF_RESULT_SUCCESS);

umf_memory_provider_handle_t ba_provider;
umf_result_t ret =
umfMemoryProviderCreate(&BA_GLOBAL_PROVIDER_OPS, nullptr, &ba_provider);
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);

umf_memory_pool_handle_t pool = nullptr;
res = umfPoolCreate(umfJemallocPoolOps(), ba_provider, params, 0, &pool);
EXPECT_EQ(res, UMF_RESULT_ERROR_NOT_SUPPORTED);
EXPECT_EQ(pool, nullptr);

umfMemoryProviderDestroy(ba_provider);
umfJemallocPoolParamsDestroy(params);
}