Skip to content

Add proxy_pool #185

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
merged 1 commit into from
Feb 8, 2024
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ A memory provider that provides memory from an operating system.

## Memory pool managers

### proxy_pool (part of libumf)

This memory pool is distributed as part of libumf. It forwards all requests to the underlying
memory provider. Currently umfPoolRealloc, umfPoolCalloc and umfPoolMallocUsableSize functions
are not supported by the proxy pool.

### libumf_pool_disjoint

TODO: Add a description
Expand Down
27 changes: 27 additions & 0 deletions include/umf/pools/pool_proxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*
* 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_PROXY_MEMORY_POOL_H
#define UMF_PROXY_MEMORY_POOL_H 1

#include <umf/base.h>
#include <umf/memory_pool.h>
#include <umf/memory_provider.h>

#ifdef __cplusplus
extern "C" {
#endif

UMF_EXPORT umf_memory_pool_ops_t *umfProxyPoolOps(void);

#ifdef __cplusplus
}
#endif

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

set(UMF_SOURCES_LINUX
Expand Down
126 changes: 126 additions & 0 deletions src/pool/pool_proxy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
*
* 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 <umf/memory_pool_ops.h>
#include <umf/pools/pool_proxy.h>

#include <assert.h>
#include <stdlib.h>

#include "utils_common.h"

static __TLS umf_result_t TLS_last_allocation_error;

struct proxy_memory_pool {
umf_memory_provider_handle_t hProvider;
};

static umf_result_t
proxy_pool_initialize(umf_memory_provider_handle_t hProvider, void *params,
void **ppPool) {
(void)params; // unused

// TODO: use ba_alloc here
struct proxy_memory_pool *pool = malloc(sizeof(struct proxy_memory_pool));
if (!pool) {
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
}

pool->hProvider = hProvider;
*ppPool = (void *)pool;

return UMF_RESULT_SUCCESS;
}

static void proxy_pool_finalize(void *pool) { free(pool); }

static void *proxy_aligned_malloc(void *pool, size_t size, size_t alignment) {
assert(pool);

void *ptr;
struct proxy_memory_pool *hPool = (struct proxy_memory_pool *)pool;

umf_result_t ret =
umfMemoryProviderAlloc(hPool->hProvider, size, alignment, &ptr);
if (ret != UMF_RESULT_SUCCESS) {
TLS_last_allocation_error = ret;
return NULL;
}

TLS_last_allocation_error = UMF_RESULT_SUCCESS;
return ptr;
}

static void *proxy_malloc(void *pool, size_t size) {
assert(pool);

return proxy_aligned_malloc(pool, size, 0);
}

static void *proxy_calloc(void *pool, size_t num, size_t size) {
assert(pool);

(void)pool;
(void)num;
(void)size;

// Currently we cannot implement calloc in a way that would
// work for memory that is inaccessible on the host
TLS_last_allocation_error = UMF_RESULT_ERROR_NOT_SUPPORTED;
return NULL;
}

static void *proxy_realloc(void *pool, void *ptr, size_t size) {
assert(pool);

(void)pool;
(void)ptr;
(void)size;

// Currently we cannot implement realloc in a way that would
// work for memory that is inaccessible on the host
TLS_last_allocation_error = UMF_RESULT_ERROR_NOT_SUPPORTED;
return NULL;
}

static umf_result_t proxy_free(void *pool, void *ptr) {
assert(pool);

struct proxy_memory_pool *hPool = (struct proxy_memory_pool *)pool;
return umfMemoryProviderFree(hPool->hProvider, ptr, 0);
}

static size_t proxy_malloc_usable_size(void *pool, void *ptr) {
assert(pool);

(void)pool;
(void)ptr;

TLS_last_allocation_error = UMF_RESULT_ERROR_NOT_SUPPORTED;
return 0;
}

static umf_result_t proxy_get_last_allocation_error(void *pool) {
(void)pool; // not used
return TLS_last_allocation_error;
}

static umf_memory_pool_ops_t UMF_PROXY_POOL_OPS = {
.version = UMF_VERSION_CURRENT,
.initialize = proxy_pool_initialize,
.finalize = proxy_pool_finalize,
.malloc = proxy_malloc,
.calloc = proxy_calloc,
.realloc = proxy_realloc,
.aligned_malloc = proxy_aligned_malloc,
.malloc_usable_size = proxy_malloc_usable_size,
.free = proxy_free,
.get_last_allocation_error = proxy_get_last_allocation_error};

umf_memory_pool_ops_t *umfProxyPoolOps(void) { return &UMF_PROXY_POOL_OPS; }
53 changes: 3 additions & 50 deletions test/common/pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ namespace umf_test {

umf_memory_pool_handle_t
createPoolChecked(umf_memory_pool_ops_t *ops,
umf_memory_provider_handle_t hProvider, void *params) {
umf_memory_provider_handle_t hProvider, void *params,
umf_pool_create_flags_t flags = 0) {
umf_memory_pool_handle_t hPool;
auto ret = umfPoolCreate(ops, hProvider, params, 0, &hPool);
auto ret = umfPoolCreate(ops, hProvider, params, flags, &hPool);
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
return hPool;
}
Expand Down Expand Up @@ -130,54 +131,6 @@ struct malloc_pool : public pool_base_t {
umf_memory_pool_ops_t MALLOC_POOL_OPS =
umf::poolMakeCOps<umf_test::malloc_pool, void>();

struct proxy_pool : public pool_base_t {
umf_result_t initialize(umf_memory_provider_handle_t provider) noexcept {
this->provider = provider;
return UMF_RESULT_SUCCESS;
}
void *malloc(size_t size) noexcept { return aligned_malloc(size, 0); }
void *calloc(size_t num, size_t size) noexcept {
void *ptr = nullptr;
auto ret = umfMemoryProviderAlloc(provider, num * size, 0, &ptr);
umf::getPoolLastStatusRef<proxy_pool>() = ret;

if (!ptr) {
return ptr;
}

memset(ptr, 0, num * size);
return ptr;
}
void *realloc([[maybe_unused]] void *ptr,
[[maybe_unused]] size_t size) noexcept {
// TODO: not supported
umf::getPoolLastStatusRef<proxy_pool>() =
UMF_RESULT_ERROR_NOT_SUPPORTED;
return nullptr;
}
void *aligned_malloc(size_t size, size_t alignment) noexcept {
void *ptr = nullptr;
auto ret = umfMemoryProviderAlloc(provider, size, alignment, &ptr);
umf::getPoolLastStatusRef<proxy_pool>() = ret;
return ptr;
}
size_t malloc_usable_size([[maybe_unused]] void *ptr) noexcept {
// TODO: not supported
return 0;
}
umf_result_t free(void *ptr) noexcept {
auto ret = umfMemoryProviderFree(provider, ptr, 0);
return ret;
}
umf_result_t get_last_allocation_error() {
return umf::getPoolLastStatusRef<proxy_pool>();
}
umf_memory_provider_handle_t provider;
};

umf_memory_pool_ops_t PROXY_POOL_OPS =
umf::poolMakeCOps<umf_test::proxy_pool, void>();

} // namespace umf_test

#endif /* UMF_TEST_POOL_HPP */
Loading