diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 588a359c6..aac50a9fb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ set(UMF_LIBS umf_utils) set(UMF_SOURCES base_alloc/base_alloc.c base_alloc/base_alloc_linear.c + base_alloc/base_alloc_global.c memory_pool.c memory_provider.c memory_provider_get_last_failed.c diff --git a/src/base_alloc/base_alloc.h b/src/base_alloc/base_alloc.h index c167fcc9c..1bbda8de9 100644 --- a/src/base_alloc/base_alloc.h +++ b/src/base_alloc/base_alloc.h @@ -12,6 +12,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct umf_ba_pool_t umf_ba_pool_t; umf_ba_pool_t *umf_ba_create(size_t size); @@ -19,4 +23,8 @@ void *umf_ba_alloc(umf_ba_pool_t *pool); void umf_ba_free(umf_ba_pool_t *pool, void *ptr); void umf_ba_destroy(umf_ba_pool_t *pool); +#ifdef __cplusplus +} +#endif + #endif /* UMF_BASE_ALLOC_H */ diff --git a/src/base_alloc/base_alloc_global.c b/src/base_alloc/base_alloc_global.c new file mode 100644 index 000000000..0489eaa68 --- /dev/null +++ b/src/base_alloc/base_alloc_global.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 Intel Corporation + * + * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include + +#include "base_alloc.h" + +#define SIZE_BA_POOL_CHUNK 128 + +// global base allocator used by all providers and pools +static umf_ba_pool_t *BA_pool = NULL; + +int umf_ba_create_global(void) { + assert(BA_pool == NULL); + + BA_pool = umf_ba_create(SIZE_BA_POOL_CHUNK); + if (!BA_pool) { + return -1; + } + + return 0; +} + +void umf_ba_destroy_global(void) { + assert(BA_pool); + umf_ba_destroy(BA_pool); + BA_pool = NULL; +} + +umf_ba_pool_t *umf_ba_get_pool(size_t size) { + // TODO: a specific class-size base allocator can be returned here + assert(BA_pool); + assert(size <= SIZE_BA_POOL_CHUNK); + + if (size > SIZE_BA_POOL_CHUNK) { + return NULL; + } + + return BA_pool; +} diff --git a/src/base_alloc/base_alloc_global.h b/src/base_alloc/base_alloc_global.h new file mode 100644 index 000000000..a048cf009 --- /dev/null +++ b/src/base_alloc/base_alloc_global.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 Intel Corporation + * + * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#ifndef UMF_BASE_ALLOC_GLOBAL_H +#define UMF_BASE_ALLOC_GLOBAL_H 1 + +#include "base_alloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int umf_ba_create_global(void); +void umf_ba_destroy_global(void); +umf_ba_pool_t *umf_ba_get_pool(size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* UMF_BASE_ALLOC_GLOBAL_H */ diff --git a/src/base_alloc/base_alloc_internal.h b/src/base_alloc/base_alloc_internal.h index 3234495de..04a290b72 100644 --- a/src/base_alloc/base_alloc_internal.h +++ b/src/base_alloc/base_alloc_internal.h @@ -14,8 +14,16 @@ #include #endif +#ifdef __cplusplus +extern "C" { +#endif + void *ba_os_alloc(size_t size); void ba_os_free(void *ptr, size_t size); size_t ba_os_get_page_size(void); +#ifdef __cplusplus +} +#endif + #endif /* UMF_BASE_ALLOC_INTERNAL_H */ diff --git a/src/base_alloc/base_alloc_linear.c b/src/base_alloc/base_alloc_linear.c index 114c09189..00fd73579 100644 --- a/src/base_alloc/base_alloc_linear.c +++ b/src/base_alloc/base_alloc_linear.c @@ -77,6 +77,7 @@ void *umf_ba_linear_alloc(umf_ba_linear_pool_t *pool, size_t size) { "space left: %zu)\n", aligned_size, pool->metadata.size_left); util_mutex_unlock(&pool->metadata.lock); + assert(pool->metadata.size_left >= aligned_size); return NULL; // out of memory } diff --git a/src/base_alloc/base_alloc_linear.h b/src/base_alloc/base_alloc_linear.h index 2543baef9..710bc560d 100644 --- a/src/base_alloc/base_alloc_linear.h +++ b/src/base_alloc/base_alloc_linear.h @@ -17,10 +17,18 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct umf_ba_linear_pool umf_ba_linear_pool_t; umf_ba_linear_pool_t *umf_ba_linear_create(size_t pool_size); void *umf_ba_linear_alloc(umf_ba_linear_pool_t *pool, size_t size); void umf_ba_linear_destroy(umf_ba_linear_pool_t *pool); +#ifdef __cplusplus +} +#endif + #endif /* UMF_BASE_ALLOC_LINEAR_H */ diff --git a/src/base_alloc/base_alloc_linux.c b/src/base_alloc/base_alloc_linux.c index e7bcf2180..f258f9aec 100644 --- a/src/base_alloc/base_alloc_linux.c +++ b/src/base_alloc/base_alloc_linux.c @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include #include #include #include @@ -17,6 +18,10 @@ void *ba_os_alloc(size_t size) { -1, 0); } -void ba_os_free(void *ptr, size_t size) { munmap(ptr, size); } +void ba_os_free(void *ptr, size_t size) { + int ret = munmap(ptr, size); + assert(ret == 0); + (void)ret; // unused +} size_t ba_os_get_page_size(void) { return sysconf(_SC_PAGE_SIZE); } diff --git a/src/libumf_linux.c b/src/libumf_linux.c index 5ce198c5e..0c95214b7 100644 --- a/src/libumf_linux.c +++ b/src/libumf_linux.c @@ -7,16 +7,20 @@ * */ -#include "provider_tracking.h" - #include +#include "base_alloc_global.h" +#include "provider_tracking.h" + umf_memory_tracker_handle_t TRACKER = NULL; void __attribute__((constructor)) umfCreate(void) { TRACKER = umfMemoryTrackerCreate(); + umf_ba_create_global(); } + void __attribute__((destructor)) umfDestroy(void) { + umf_ba_destroy_global(); umfMemoryTrackerDestroy(TRACKER); } diff --git a/src/libumf_windows.c b/src/libumf_windows.c index a39381a4c..1a3e2cfd8 100644 --- a/src/libumf_windows.c +++ b/src/libumf_windows.c @@ -7,21 +7,30 @@ * */ -#include "provider_tracking.h" - #include #include +#include "base_alloc_global.h" +#include "provider_tracking.h" + umf_memory_tracker_handle_t TRACKER = NULL; -static void providerFini(void) { umfMemoryTrackerDestroy(TRACKER); } +static void umfCreate(void) { + TRACKER = umfMemoryTrackerCreate(); + umf_ba_create_global(); +} + +static void umfDestroy(void) { + umf_ba_destroy_global(); + umfMemoryTrackerDestroy(TRACKER); +} #if defined(UMF_SHARED_LIBRARY) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if (fdwReason == DLL_PROCESS_DETACH) { - providerFini(); + umfDestroy(); } else if (fdwReason == DLL_PROCESS_ATTACH) { - TRACKER = umfMemoryTrackerCreate(); + umfCreate(); } return TRUE; } @@ -34,8 +43,8 @@ INIT_ONCE init_once_flag = INIT_ONCE_STATIC_INIT; BOOL CALLBACK initOnceCb(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext) { - TRACKER = umfMemoryTrackerCreate(); - atexit(providerFini); + umfCreate(); + atexit(umfDestroy); return TRACKER ? TRUE : FALSE; } diff --git a/src/memory_pool_default.c b/src/memory_pool_default.c index 57a8063e6..ef7b52e05 100644 --- a/src/memory_pool_default.c +++ b/src/memory_pool_default.c @@ -7,12 +7,14 @@ * */ -#include "memory_pool_internal.h" +#include +#include #include -#include -#include +#include "base_alloc_global.h" +#include "memory_pool_internal.h" +#include "memory_provider_internal.h" umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, umf_memory_provider_handle_t provider, @@ -23,20 +25,26 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, } umf_result_t ret = UMF_RESULT_SUCCESS; - umf_memory_pool_handle_t pool = malloc(sizeof(umf_memory_pool_t)); + umf_ba_pool_t *base_allocator = umf_ba_get_pool(sizeof(umf_memory_pool_t)); + if (!base_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + umf_memory_pool_handle_t pool = umf_ba_alloc(base_allocator); if (!pool) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } assert(ops->version == UMF_VERSION_CURRENT); + pool->base_allocator = base_allocator; pool->provider = provider; pool->own_provider = false; pool->ops = *ops; ret = ops->initialize(pool->provider, params, &pool->pool_priv); if (ret != UMF_RESULT_SUCCESS) { - free(pool); + umf_ba_free(base_allocator, pool); return ret; } @@ -52,7 +60,8 @@ void umfPoolDestroy(umf_memory_pool_handle_t hPool) { umfPoolGetMemoryProvider(hPool, &hProvider); umfMemoryProviderDestroy(hProvider); } - free(hPool); + // TODO: this free keeps memory in base allocator, so it can lead to OOM in some scenarios (it should be optimized) + umf_ba_free(hPool->base_allocator, hPool); } umf_result_t umfFree(void *ptr) { diff --git a/src/memory_pool_internal.h b/src/memory_pool_internal.h index 50c01b3e4..bbbae844e 100644 --- a/src/memory_pool_internal.h +++ b/src/memory_pool_internal.h @@ -21,6 +21,8 @@ extern "C" { #endif +#include "base_alloc.h" + typedef struct umf_memory_pool_t { void *pool_priv; umf_memory_pool_ops_t ops; @@ -29,6 +31,9 @@ typedef struct umf_memory_pool_t { umf_memory_provider_handle_t provider; // Tells whether memory provider is owned by the pool. bool own_provider; + + // saved pointer to the global base allocator + umf_ba_pool_t *base_allocator; } umf_memory_pool_t; umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, diff --git a/src/memory_pool_tracking.c b/src/memory_pool_tracking.c index 2ea2cfc12..4c932df5f 100644 --- a/src/memory_pool_tracking.c +++ b/src/memory_pool_tracking.c @@ -7,14 +7,15 @@ * */ -#include "memory_pool_internal.h" -#include "memory_provider_internal.h" -#include "provider_tracking.h" +#include +#include #include -#include -#include +#include "base_alloc_global.h" +#include "memory_pool_internal.h" +#include "memory_provider_internal.h" +#include "provider_tracking.h" umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, umf_memory_provider_handle_t provider, @@ -25,7 +26,12 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, } umf_result_t ret = UMF_RESULT_SUCCESS; - umf_memory_pool_handle_t pool = malloc(sizeof(umf_memory_pool_t)); + umf_ba_pool_t *base_allocator = umf_ba_get_pool(sizeof(umf_memory_pool_t)); + if (!base_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + umf_memory_pool_handle_t pool = umf_ba_alloc(base_allocator); if (!pool) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } @@ -37,6 +43,8 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, if (ret != UMF_RESULT_SUCCESS) { goto err_provider_create; } + + pool->base_allocator = base_allocator; pool->own_provider = false; pool->ops = *ops; @@ -51,8 +59,7 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops, err_pool_init: umfMemoryProviderDestroy(pool->provider); err_provider_create: - free(pool); - + umf_ba_free(base_allocator, pool); return ret; } @@ -66,7 +73,8 @@ void umfPoolDestroy(umf_memory_pool_handle_t hPool) { } // Destroy tracking provider. umfMemoryProviderDestroy(hPool->provider); - free(hPool); + // TODO: this free keeps memory in base allocator, so it can lead to OOM in some scenarios (it should be optimized) + umf_ba_free(hPool->base_allocator, hPool); } umf_result_t umfFree(void *ptr) { diff --git a/src/memory_provider.c b/src/memory_provider.c index 9c5344926..f5c7936d8 100644 --- a/src/memory_provider.c +++ b/src/memory_provider.c @@ -7,19 +7,24 @@ * */ -#include "libumf.h" -#include "memory_provider_internal.h" -#include "utils_common.h" - -#include - #include #include #include +#include + +#include "base_alloc.h" +#include "base_alloc_global.h" +#include "libumf.h" +#include "memory_provider_internal.h" +#include "utils_common.h" + typedef struct umf_memory_provider_t { umf_memory_provider_ops_t ops; void *provider_priv; + + // saved pointer to the global base allocator + umf_ba_pool_t *base_allocator; } umf_memory_provider_t; umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops, @@ -30,8 +35,13 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - umf_memory_provider_handle_t provider = - malloc(sizeof(umf_memory_provider_t)); + umf_ba_pool_t *base_allocator = + umf_ba_get_pool(sizeof(umf_memory_provider_t)); + if (!base_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + umf_memory_provider_handle_t provider = umf_ba_alloc(base_allocator); if (!provider) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } @@ -39,11 +49,12 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops, assert(ops->version == UMF_VERSION_CURRENT); provider->ops = *ops; + provider->base_allocator = base_allocator; void *provider_priv; umf_result_t ret = ops->initialize(params, &provider_priv); if (ret != UMF_RESULT_SUCCESS) { - free(provider); + umf_ba_free(base_allocator, provider); return ret; } @@ -56,7 +67,7 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops, void umfMemoryProviderDestroy(umf_memory_provider_handle_t hProvider) { hProvider->ops.finalize(hProvider->provider_priv); - free(hProvider); + umf_ba_free(hProvider->base_allocator, hProvider); } static void diff --git a/src/memory_target.c b/src/memory_target.c index c44e313c5..0999d7013 100644 --- a/src/memory_target.c +++ b/src/memory_target.c @@ -10,9 +10,11 @@ #include #include +#include "base_alloc_global.h" #include "libumf.h" #include "memory_target.h" #include "memory_target_ops.h" +#include "utils_concurrency.h" umf_result_t umfMemoryTargetCreate(const umf_memory_target_ops_t *ops, void *params, @@ -22,20 +24,27 @@ umf_result_t umfMemoryTargetCreate(const umf_memory_target_ops_t *ops, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } + umf_ba_pool_t *base_allocator = + umf_ba_get_pool(sizeof(umf_memory_target_t)); + if (!base_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + umf_memory_target_handle_t target = - (umf_memory_target_t *)malloc(sizeof(umf_memory_target_t)); + (umf_memory_target_t *)umf_ba_alloc(base_allocator); if (!target) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } assert(ops->version == UMF_VERSION_CURRENT); + target->base_allocator = base_allocator; target->ops = ops; void *target_priv; umf_result_t ret = ops->initialize(params, &target_priv); if (ret != UMF_RESULT_SUCCESS) { - free(target); + umf_ba_free(base_allocator, target); return ret; } @@ -49,5 +58,5 @@ umf_result_t umfMemoryTargetCreate(const umf_memory_target_ops_t *ops, void umfMemoryTargetDestroy(umf_memory_target_handle_t memoryTarget) { assert(memoryTarget); memoryTarget->ops->finalize(memoryTarget->priv); - free(memoryTarget); + umf_ba_free(memoryTarget->base_allocator, memoryTarget); } diff --git a/src/memory_target.h b/src/memory_target.h index 2a087294b..fccd809fe 100644 --- a/src/memory_target.h +++ b/src/memory_target.h @@ -16,12 +16,17 @@ extern "C" { #endif +#include "base_alloc.h" + struct umf_memory_target_ops_t; typedef struct umf_memory_target_ops_t umf_memory_target_ops_t; typedef struct umf_memory_target_t { const umf_memory_target_ops_t *ops; void *priv; + + // saved pointer to the global base allocator + umf_ba_pool_t *base_allocator; } umf_memory_target_t; typedef umf_memory_target_t *umf_memory_target_handle_t; diff --git a/src/memory_targets/memory_target_numa.c b/src/memory_targets/memory_target_numa.c index b413adc11..0b48a8cd0 100644 --- a/src/memory_targets/memory_target_numa.c +++ b/src/memory_targets/memory_target_numa.c @@ -11,13 +11,20 @@ #include #include -#include "../memory_pool_internal.h" -#include "memory_target_numa.h" #include #include +#include "../memory_pool_internal.h" +#include "base_alloc.h" +#include "base_alloc_global.h" +#include "base_alloc_linear.h" +#include "memory_target_numa.h" + struct numa_memory_target_t { size_t id; + + // saved pointer to the global base allocator + umf_ba_pool_t *base_allocator; }; static umf_result_t numa_initialize(void *params, void **memTarget) { @@ -28,24 +35,35 @@ static umf_result_t numa_initialize(void *params, void **memTarget) { struct umf_numa_memory_target_config_t *config = (struct umf_numa_memory_target_config_t *)params; - struct numa_memory_target_t *numaTarget = - malloc(sizeof(struct numa_memory_target_t)); + umf_ba_pool_t *base_allocator = + umf_ba_get_pool(sizeof(struct numa_memory_target_t)); + if (!base_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + struct numa_memory_target_t *numaTarget = umf_ba_alloc(base_allocator); if (!numaTarget) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } + numaTarget->base_allocator = base_allocator; numaTarget->id = config->id; *memTarget = numaTarget; return UMF_RESULT_SUCCESS; } -static void numa_finalize(void *memTarget) { free(memTarget); } +static void numa_finalize(void *memTarget) { + struct numa_memory_target_t *numaTarget = + (struct numa_memory_target_t *)memTarget; + umf_ba_free(numaTarget->base_allocator, memTarget); +} // sets maxnode and allocates and initializes mask based on provided memory targets static umf_result_t numa_targets_create_nodemask(struct numa_memory_target_t **targets, size_t numTargets, unsigned long **mask, - unsigned *maxnode) { + unsigned *maxnode, + umf_ba_linear_pool_t *linear_allocator) { assert(targets); assert(mask); assert(maxnode); @@ -76,7 +94,8 @@ numa_targets_create_nodemask(struct numa_memory_target_t **targets, unsigned bits_per_long = sizeof(unsigned long) * 8; int nrUlongs = (lastBit + bits_per_long) / bits_per_long; - unsigned long *nodemask = malloc(sizeof(unsigned long) * nrUlongs); + unsigned long *nodemask = umf_ba_linear_alloc( + linear_allocator, (sizeof(unsigned long) * nrUlongs)); if (!nodemask) { hwloc_bitmap_free(bitmap); return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; @@ -86,7 +105,7 @@ numa_targets_create_nodemask(struct numa_memory_target_t **targets, hwloc_bitmap_free(bitmap); if (ret) { - free(nodemask); + // nodemask is freed during destroying linear_allocator return UMF_RESULT_ERROR_UNKNOWN; } @@ -109,8 +128,14 @@ static enum umf_result_t numa_memory_provider_create_from_memspace( unsigned long *nodemask; unsigned maxnode; - umf_result_t ret = numa_targets_create_nodemask(numaTargets, numTargets, - &nodemask, &maxnode); + umf_ba_linear_pool_t *linear_allocator = + umf_ba_linear_create(0 /* minimal pool size */); + if (!linear_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + umf_result_t ret = numa_targets_create_nodemask( + numaTargets, numTargets, &nodemask, &maxnode, linear_allocator); if (ret != UMF_RESULT_SUCCESS) { return ret; } @@ -124,8 +149,9 @@ static enum umf_result_t numa_memory_provider_create_from_memspace( umf_memory_provider_handle_t numaProvider = NULL; ret = umfMemoryProviderCreate(umfOsMemoryProviderOps(), ¶ms, &numaProvider); - free(nodemask); + umf_ba_linear_destroy(linear_allocator); // nodemask is freed here if (ret) { + return ret; } diff --git a/src/memory_targets/memory_target_numa.h b/src/memory_targets/memory_target_numa.h index 37ae04511..7800de754 100644 --- a/src/memory_targets/memory_target_numa.h +++ b/src/memory_targets/memory_target_numa.h @@ -15,6 +15,7 @@ #include "../memory_target.h" #include "../memory_target_ops.h" +#include "base_alloc_linear.h" #ifdef __cplusplus extern "C" { diff --git a/src/memspace.c b/src/memspace.c index 89adce1a6..fe4515893 100644 --- a/src/memspace.c +++ b/src/memspace.c @@ -37,7 +37,8 @@ static umf_result_t verifyMemTargetsTypes(umf_memspace_handle_t memspace) { static umf_result_t memoryTargetHandlesToPriv(umf_memspace_handle_t memspace, void ***pPrivs) { assert(memspace); - void **privs = malloc(sizeof(void *) * memspace->size); + void **privs = umf_ba_linear_alloc(memspace->linear_allocator, + sizeof(void *) * memspace->size); if (privs == NULL) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } @@ -68,7 +69,7 @@ umf_result_t umfPoolCreateFromMemspace(umf_memspace_handle_t memspace, assert(verifyMemTargetsTypes(memspace) == UMF_RESULT_SUCCESS); ret = memspace->nodes[0]->ops->pool_create_from_memspace( memspace, privs, memspace->size, policy, pool); - free(privs); + // privs is freed during destroying memspace->linear_allocator return ret; } @@ -92,7 +93,7 @@ umfMemoryProviderCreateFromMemspace(umf_memspace_handle_t memspace, assert(verifyMemTargetsTypes(memspace) == UMF_RESULT_SUCCESS); ret = memspace->nodes[0]->ops->memory_provider_create_from_memspace( memspace, privs, memspace->size, policy, provider); - free(privs); + // privs is freed during destroying memspace->linear_allocator return ret; } @@ -102,6 +103,7 @@ void umfMemspaceDestroy(umf_memspace_handle_t memspace) { for (size_t i = 0; i < memspace->size; i++) { umfMemoryTargetDestroy(memspace->nodes[i]); } - free(memspace->nodes); - free(memspace); + + umf_ba_linear_destroy(memspace->linear_allocator); + umf_ba_free(memspace->base_allocator, memspace); } diff --git a/src/memspace_internal.h b/src/memspace_internal.h index 0c88e3ec6..834a68037 100644 --- a/src/memspace_internal.h +++ b/src/memspace_internal.h @@ -12,6 +12,8 @@ #include +#include "base_alloc.h" +#include "base_alloc_linear.h" #include "memory_target.h" #ifdef __cplusplus @@ -21,6 +23,12 @@ extern "C" { struct umf_memspace_t { size_t size; umf_memory_target_handle_t *nodes; + + // saved pointer to the global base allocator + umf_ba_pool_t *base_allocator; + + // own local linear base allocator + umf_ba_linear_pool_t *linear_allocator; }; /// diff --git a/src/memspaces/memspace_numa.c b/src/memspaces/memspace_numa.c index 1a78af8d4..693ace2a6 100644 --- a/src/memspaces/memspace_numa.c +++ b/src/memspaces/memspace_numa.c @@ -11,6 +11,8 @@ #include "../memory_targets/memory_target_numa.h" #include "../memspace_internal.h" +#include "base_alloc_global.h" +#include "base_alloc_linear.h" #include "memspace_numa.h" enum umf_result_t @@ -21,16 +23,32 @@ umfMemspaceCreateFromNumaArray(size_t *nodeIds, size_t numIds, } enum umf_result_t ret = UMF_RESULT_SUCCESS; + + umf_ba_pool_t *base_allocator = + umf_ba_get_pool(sizeof(struct umf_memspace_t)); + if (!base_allocator) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + umf_memspace_handle_t memspace = - (struct umf_memspace_t *)malloc(sizeof(struct umf_memspace_t)); + (struct umf_memspace_t *)umf_ba_alloc(base_allocator); if (!memspace) { + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + umf_ba_linear_pool_t *linear_allocator = + umf_ba_linear_create(0 /* minimal pool size */); + if (!linear_allocator) { ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; - goto err_memspace_alloc; + goto err_umf_ba_linear_create; } + memspace->base_allocator = base_allocator; + memspace->linear_allocator = linear_allocator; + memspace->size = numIds; - memspace->nodes = (umf_memory_target_handle_t *)calloc( - numIds, sizeof(umf_memory_target_handle_t)); + memspace->nodes = (umf_memory_target_handle_t *)umf_ba_linear_alloc( + linear_allocator, numIds * sizeof(umf_memory_target_handle_t)); if (!memspace->nodes) { ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; goto err_nodes_alloc; @@ -54,9 +72,9 @@ umfMemspaceCreateFromNumaArray(size_t *nodeIds, size_t numIds, for (size_t i = 0; i < nodeIdx; i++) { umfMemoryTargetDestroy(memspace->nodes[i]); } - free(memspace->nodes); err_nodes_alloc: - free(memspace); -err_memspace_alloc: + umf_ba_linear_destroy(linear_allocator); +err_umf_ba_linear_create: + umf_ba_free(base_allocator, memspace); return ret; }