Skip to content

Commit 9dce66e

Browse files
committed
[CTL] Add allocation counter for disjoint pool
1 parent 222e26d commit 9dce66e

File tree

2 files changed

+106
-6
lines changed

2 files changed

+106
-6
lines changed

src/pool/pool_disjoint.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static char *DEFAULT_NAME = "disjoint";
3333
struct ctl disjoint_ctl_root;
3434
static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT;
3535

36+
// CTL: name attribute
3637
static int CTL_READ_HANDLER(name)(void *ctx, umf_ctl_query_source_t source,
3738
void *arg, size_t size,
3839
umf_ctl_index_utlist_t *indexes,
@@ -66,8 +67,30 @@ static int CTL_WRITE_HANDLER(name)(void *ctx, umf_ctl_query_source_t source,
6667
return 0;
6768
}
6869

69-
static const umf_ctl_node_t CTL_NODE(disjoint)[] = {CTL_LEAF_RW(name),
70-
CTL_NODE_END};
70+
// CTL: allocation counters
71+
uint64_t allocation_balance = 0;
72+
73+
static int CTL_READ_HANDLER(allocation_balance)(
74+
void *ctx, umf_ctl_query_source_t source, void *arg, size_t size,
75+
umf_ctl_index_utlist_t *indexes, const char *extra_name,
76+
umf_ctl_query_type_t queryType) {
77+
(void)ctx, (void)source, (void)size, (void)indexes, (void)extra_name,
78+
(void)queryType;
79+
// Calculate from pool buckets
80+
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
81+
printf("Calculating allocation balance for pool: %p\n", (void *)pool);
82+
if (arg == NULL) {
83+
return -1;
84+
}
85+
uint64_t *balance = (uint64_t *)arg;
86+
*balance = 0;
87+
utils_atomic_load_acquire_u64(&allocation_balance, balance);
88+
89+
return 0;
90+
}
91+
92+
static const umf_ctl_node_t CTL_NODE(disjoint)[] = {
93+
CTL_LEAF_RW(name), CTL_LEAF_RO(allocation_balance), CTL_NODE_END};
7194

7295
static void initialize_disjoint_ctl(void) {
7396
CTL_REGISTER_MODULE(&disjoint_ctl_root, disjoint);
@@ -579,7 +602,6 @@ static void *disjoint_pool_allocate(disjoint_pool_t *pool, size_t size) {
579602
}
580603

581604
void *ptr = NULL;
582-
583605
if (size > pool->params.max_poolable_size) {
584606
umf_result_t ret =
585607
umfMemoryProviderAlloc(pool->provider, size, 0, &ptr);
@@ -755,7 +777,7 @@ umf_result_t disjoint_pool_initialize(umf_memory_provider_handle_t provider,
755777
void *disjoint_pool_malloc(void *pool, size_t size) {
756778
disjoint_pool_t *hPool = (disjoint_pool_t *)pool;
757779
void *ptr = disjoint_pool_allocate(hPool, size);
758-
780+
utils_atomic_increment_u64(&allocation_balance);
759781
return ptr;
760782
}
761783

@@ -939,8 +961,9 @@ umf_result_t disjoint_pool_free(void *pool, void *ptr) {
939961
if (ret != UMF_RESULT_SUCCESS) {
940962
TLS_last_allocation_error = ret;
941963
LOG_ERR("deallocation from the memory provider failed");
964+
} else {
965+
utils_atomic_decrement_u64(&allocation_balance);
942966
}
943-
944967
return ret;
945968
}
946969

@@ -971,6 +994,9 @@ umf_result_t disjoint_pool_free(void *pool, void *ptr) {
971994
critnib_release(disjoint_pool->known_slabs, ref_slab);
972995

973996
if (disjoint_pool->params.pool_trace > 1) {
997+
printf("Freeing %8zu %s bytes from %s -> %p\n", bucket->size,
998+
disjoint_pool->params.name, (to_pool ? "pool" : "provider"),
999+
unaligned_ptr);
9741000
bucket->free_count++;
9751001
}
9761002

@@ -985,7 +1011,7 @@ umf_result_t disjoint_pool_free(void *pool, void *ptr) {
9851011
disjoint_pool_get_limits(disjoint_pool)->total_size, name,
9861012
disjoint_pool->params.cur_pool_size);
9871013
}
988-
1014+
utils_atomic_decrement_u64(&allocation_balance);
9891015
return UMF_RESULT_SUCCESS;
9901016
}
9911017

test/pools/disjoint_pool_ctl.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exceptiongi
44

5+
#include <cstdint>
56
#include <gtest/gtest.h>
67
#include <umf/memory_pool.h>
78
#include <umf/memory_provider.h>
@@ -85,6 +86,79 @@ class ProviderWrapper {
8586
void *m_params;
8687
};
8788

89+
TEST_F(test, disjointCtlAllocationBalance) {
90+
umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr;
91+
if (UMF_RESULT_ERROR_NOT_SUPPORTED ==
92+
umfOsMemoryProviderParamsCreate(&os_memory_provider_params)) {
93+
GTEST_SKIP() << "OS memory provider is not supported!";
94+
}
95+
96+
ProviderWrapper providerWrapper(umfOsMemoryProviderOps(),
97+
os_memory_provider_params);
98+
if (providerWrapper.get() == NULL) {
99+
GTEST_SKIP() << "OS memory provider is not supported!";
100+
}
101+
102+
umf_disjoint_pool_params_handle_t params = nullptr;
103+
ASSERT_SUCCESS(umfDisjointPoolParamsCreate(&params));
104+
105+
// Set max poolable size to a reasonable value
106+
ASSERT_SUCCESS(
107+
umfDisjointPoolParamsSetMaxPoolableSize(params, 1024 * 1024));
108+
109+
// Set the capacity of the pool to a reasonable value
110+
ASSERT_SUCCESS(
111+
umfDisjointPoolParamsSetSlabMinSize(params, 64 * 1024)); // 64 KiB
112+
113+
// Set the trace level to 3 to enable allocation balance tracking
114+
ASSERT_SUCCESS(umfDisjointPoolParamsSetTrace(params, 3));
115+
116+
PoolWrapper poolWrapper(providerWrapper.get(), umfDisjointPoolOps(),
117+
params);
118+
119+
// Check that the allocation balance is zero
120+
uint64_t allocation_balance = 0;
121+
ASSERT_SUCCESS(umfCtlGet("umf.pool.by_handle.disjoint.allocation_balance",
122+
poolWrapper.get(), &allocation_balance,
123+
sizeof(allocation_balance)));
124+
ASSERT_EQ(allocation_balance, 0);
125+
126+
// Allocate some memory from the pool
127+
size_t allocation_size = 64; // 64 B
128+
const int max_allocations = 2;
129+
void *ptr[max_allocations] = {nullptr};
130+
int i = 0;
131+
while (i < max_allocations) {
132+
ptr[i] = umfPoolMalloc(poolWrapper.get(), allocation_size);
133+
printf("Allocated %d: %p\n", i, ptr[i]);
134+
ASSERT_NE(ptr[i], nullptr);
135+
++i;
136+
}
137+
138+
// Check the allocation balance after allocations
139+
ASSERT_SUCCESS(umfCtlGet("umf.pool.by_handle.disjoint.allocation_balance",
140+
poolWrapper.get(), &allocation_balance,
141+
sizeof(allocation_balance)));
142+
ASSERT_EQ(allocation_balance, max_allocations);
143+
144+
// Check balance after freeing the allocations
145+
for (int j = 0; j < max_allocations; ++j) {
146+
if (ptr[j]) {
147+
printf("Freeing allocation %p with %d\n", ptr[j], j);
148+
ASSERT_EQ(umfPoolFree(poolWrapper.get(), ptr[j]),
149+
UMF_RESULT_SUCCESS);
150+
}
151+
}
152+
allocation_balance = 123;
153+
ASSERT_SUCCESS(umfCtlGet("umf.pool.by_handle.disjoint.allocation_balance",
154+
poolWrapper.get(), &allocation_balance,
155+
sizeof(allocation_balance)));
156+
ASSERT_EQ(allocation_balance, 0);
157+
158+
ASSERT_SUCCESS(umfDisjointPoolParamsDestroy(params));
159+
ASSERT_SUCCESS(umfOsMemoryProviderParamsDestroy(os_memory_provider_params));
160+
}
161+
88162
TEST_F(test, disjointCtlName) {
89163
umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr;
90164
if (UMF_RESULT_ERROR_NOT_SUPPORTED ==

0 commit comments

Comments
 (0)