Skip to content
Open
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
3 changes: 3 additions & 0 deletions include/umf/memory_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ UMF_EXPORT size_t umfPoolMallocUsableSize(umf_memory_pool_handle_t hPool,
///
UMF_EXPORT umf_result_t umfPoolFree(umf_memory_pool_handle_t hPool, void *ptr);

UMF_EXPORT umf_result_t umfPoolFreeSized(umf_memory_pool_handle_t hPool,
void *ptr, size_t size);

///
/// @brief Frees the memory space pointed by ptr if it belongs to UMF pool, does nothing otherwise.
/// @param ptr pointer to the allocated memory
Expand Down
2 changes: 1 addition & 1 deletion include/umf/memory_pool_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ typedef struct umf_memory_pool_ops_t {
/// Whether any status other than UMF_RESULT_SUCCESS can be returned
/// depends on the memory provider used by the \p pool.
///
umf_result_t (*free)(void *pool, void *);
umf_result_t (*free)(void *pool, void *, size_t size);

///
/// @brief Retrieve \p umf_result_t representing the error of the last failed allocation
Expand Down
25 changes: 25 additions & 0 deletions include/umf/pools/pool_base.h
Original file line number Diff line number Diff line change
@@ -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_MEMORY_POOL_H
#define UMF_BASE_MEMORY_POOL_H 1

#ifdef __cplusplus
extern "C" {
#endif

#include <umf/memory_pool_ops.h>

umf_memory_pool_ops_t *umfBasePoolOps(void);

#ifdef __cplusplus
}
#endif

#endif /* UMF_JEMALLOC_MEMORY_POOL_H */
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(UMF_SOURCES
provider/provider_tracking.c
critnib/critnib.c
pool/pool_proxy.c
pool/pool_base.c
)

set(UMF_SOURCES_LINUX
Expand Down
24 changes: 0 additions & 24 deletions src/base_alloc/base_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,29 +196,6 @@ void *umf_ba_alloc(umf_ba_pool_t *pool) {
return chunk;
}

#ifndef NDEBUG
// Checks if given pointer belongs to the pool. Should be called
// under the lock
static int pool_contains_pointer(umf_ba_pool_t *pool, void *ptr) {
char *cptr = (char *)ptr;
if (cptr >= pool->data &&
cptr < ((char *)(pool)) + pool->metadata.pool_size) {
return 1;
}

umf_ba_next_pool_t *next_pool = pool->next_pool;
while (next_pool) {
if (cptr >= next_pool->data &&
cptr < ((char *)(next_pool)) + pool->metadata.pool_size) {
return 1;
}
next_pool = next_pool->next_pool;
}

return 0;
}
#endif

void umf_ba_free(umf_ba_pool_t *pool, void *ptr) {
if (ptr == NULL) {
return;
Expand All @@ -227,7 +204,6 @@ void umf_ba_free(umf_ba_pool_t *pool, void *ptr) {
umf_ba_chunk_t *chunk = (umf_ba_chunk_t *)ptr;

util_mutex_lock(&pool->metadata.free_lock);
assert(pool_contains_pointer(pool, ptr));
chunk->next = pool->metadata.free_list;
pool->metadata.free_list = chunk;
#ifndef NDEBUG
Expand Down
52 changes: 28 additions & 24 deletions src/base_alloc/base_alloc_global.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,44 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#include <assert.h>
/* A MT-safe base allocator */

#include "base_alloc.h"
#include <umf/pools/pool_base.h>

#define SIZE_BA_POOL_CHUNK 128
#include <assert.h>

// global base allocator used by all providers and pools
static umf_ba_pool_t *BA_pool = NULL;
// this is where base pool will allocate it's own metadata
char base_pool_metadata[128];

int umf_ba_create_global(void) {
assert(BA_pool == NULL);
static int base_pool_init;
static umf_memory_pool_ops_t *ops;
static void *pool;

BA_pool = umf_ba_create(SIZE_BA_POOL_CHUNK);
if (!BA_pool) {
return -1;
}
void umf_ba_create_global(void) {
ops = umfBasePoolOps();

return 0;
// do not call umfPoolCreate to avoid inifite recursion
ops->initialize(NULL, NULL, &pool);
}

void umf_ba_destroy_global(void) {
assert(BA_pool);
umf_ba_destroy(BA_pool);
BA_pool = NULL;
}
void umf_ba_destroy_global(void) { ops->finalize(pool); }

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);
void *umf_ba_global_alloc(size_t size) {
if (!base_pool_init) {
assert(size <= sizeof(base_pool_metadata));
base_pool_init = 1;
return &base_pool_metadata;
}

return ops->malloc(pool, size);
}

if (size > SIZE_BA_POOL_CHUNK) {
return NULL;
void umf_ba_global_free(void *ptr, size_t size) {
if (ptr == &base_pool_metadata) {
// nothing to do
return;
}

return BA_pool;
umf_result_t ret = ops->free(pool, ptr, size);
assert(ret == UMF_RESULT_SUCCESS);
}
6 changes: 4 additions & 2 deletions src/base_alloc/base_alloc_global.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
extern "C" {
#endif

int umf_ba_create_global(void);
void umf_ba_create_global(void);
void umf_ba_destroy_global(void);
umf_ba_pool_t *umf_ba_get_pool(size_t size);

void *umf_ba_global_alloc(size_t size);
void umf_ba_global_free(void *ptr, size_t size);

#ifdef __cplusplus
}
Expand Down
8 changes: 7 additions & 1 deletion src/memory_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,16 @@ size_t umfPoolMallocUsableSize(umf_memory_pool_handle_t hPool, void *ptr) {

umf_result_t umfPoolFree(umf_memory_pool_handle_t hPool, void *ptr) {
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
return hPool->ops.free(hPool->pool_priv, ptr);
return hPool->ops.free(hPool->pool_priv, ptr, 0);
}

umf_result_t umfPoolGetLastAllocationError(umf_memory_pool_handle_t hPool) {
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
return hPool->ops.get_last_allocation_error(hPool->pool_priv);
}

umf_result_t umfPoolFreeSized(umf_memory_pool_handle_t hPool, void *ptr,
size_t size) {
UMF_CHECK((hPool != NULL), UMF_RESULT_ERROR_INVALID_ARGUMENT);
return hPool->ops.free(hPool->pool_priv, ptr, size);
}
15 changes: 5 additions & 10 deletions src/memory_pool_default.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,26 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
umf_memory_provider_handle_t provider,
void *params,
umf_memory_pool_handle_t *hPool) {
if (!ops || !provider || !hPool) {
if (!ops || !hPool) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

umf_result_t ret = UMF_RESULT_SUCCESS;
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);
umf_memory_pool_handle_t pool =
umf_ba_global_alloc(sizeof(umf_memory_pool_t));
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) {
umf_ba_free(base_allocator, pool);
umf_ba_global_free(pool, sizeof(umf_memory_pool_t));
return ret;
}

Expand All @@ -61,7 +56,7 @@ void umfPoolDestroy(umf_memory_pool_handle_t hPool) {
umfMemoryProviderDestroy(hProvider);
}
// 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_ba_global_free(hPool, sizeof(umf_memory_pool_t));
}

umf_result_t umfFree(void *ptr) {
Expand Down
3 changes: 0 additions & 3 deletions src/memory_pool_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ 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,
Expand Down
15 changes: 5 additions & 10 deletions src/memory_pool_tracking.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,13 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
umf_memory_provider_handle_t provider,
void *params,
umf_memory_pool_handle_t *hPool) {
if (!ops || !provider || !hPool) {
if (!ops || !hPool) {
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

umf_result_t ret = UMF_RESULT_SUCCESS;
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);
umf_memory_pool_handle_t pool =
umf_ba_global_alloc(sizeof(umf_memory_pool_t));
if (!pool) {
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}
Expand All @@ -44,7 +40,6 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
goto err_provider_create;
}

pool->base_allocator = base_allocator;
pool->own_provider = false;

pool->ops = *ops;
Expand All @@ -59,7 +54,7 @@ umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
err_pool_init:
umfMemoryProviderDestroy(pool->provider);
err_provider_create:
umf_ba_free(base_allocator, pool);
umf_ba_global_free(pool, sizeof(umf_memory_pool_t));
return ret;
}

Expand All @@ -74,7 +69,7 @@ void umfPoolDestroy(umf_memory_pool_handle_t hPool) {
// Destroy tracking provider.
umfMemoryProviderDestroy(hPool->provider);
// 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_ba_global_free(hPool, sizeof(umf_memory_pool_t));
}

umf_result_t umfFree(void *ptr) {
Expand Down
17 changes: 4 additions & 13 deletions src/memory_provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
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,
Expand All @@ -35,26 +32,20 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops,
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
}

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);
umf_memory_provider_handle_t provider =
umf_ba_global_alloc(sizeof(umf_memory_provider_t));
if (!provider) {
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}

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) {
umf_ba_free(base_allocator, provider);
umf_ba_global_free(provider, sizeof(umf_memory_provider_t));
return ret;
}

Expand All @@ -67,7 +58,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);
umf_ba_free(hProvider->base_allocator, hProvider);
umf_ba_global_free(hProvider, sizeof(umf_memory_provider_t));
}

static void
Expand Down
13 changes: 3 additions & 10 deletions src/memory_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,20 @@ 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 *)umf_ba_alloc(base_allocator);
(umf_memory_target_t *)umf_ba_global_alloc(sizeof(umf_memory_target_t));
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) {
umf_ba_free(base_allocator, target);
umf_ba_global_free(target, sizeof(umf_memory_target_t));
return ret;
}

Expand All @@ -58,5 +51,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);
umf_ba_free(memoryTarget->base_allocator, memoryTarget);
umf_ba_global_free(memoryTarget, sizeof(umf_memory_target_t));
}
3 changes: 0 additions & 3 deletions src/memory_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ 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;
Expand Down
Loading