Skip to content

Commit 266f117

Browse files
committed
add ctl to fixed provider
1 parent d4c2672 commit 266f117

8 files changed

+229
-108
lines changed

benchmark/benchmark_umf.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ struct provider_interface {
4444
if (state.thread_index() != 0) {
4545
return;
4646
}
47-
umfCtlExec("umf.provider.by_handle.stats.reset", provider, NULL);
47+
umfCtlExec("umf.provider.by_handle.stats.peak_memory.reset", provider,
48+
NULL);
4849
}
4950

5051
void postBench([[maybe_unused]] ::benchmark::State &state) {

src/ctl/ctl.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ umf_result_t umfCtlSet(const char *name, void *ctx, void *arg) {
102102
}
103103

104104
umf_result_t umfCtlExec(const char *name, void *ctx, void *arg) {
105-
if (name == NULL || arg == NULL || ctx == NULL) {
105+
if (name == NULL || ctx == NULL) {
106106
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
107107
}
108108
return ctl_query(NULL, ctx, CTL_QUERY_PROGRAMMATIC, name,
@@ -140,6 +140,7 @@ static const umf_ctl_node_t *ctl_find_node(const umf_ctl_node_t *nodes,
140140
* in the main ctl tree.
141141
*/
142142
while (node_name != NULL) {
143+
char *next_node = strtok_r(NULL, CTL_QUERY_NODE_SEPARATOR, &sptr);
143144
*name_offset = node_name - parse_str;
144145
if (n != NULL && n->type == CTL_NODE_SUBTREE) {
145146
// if a subtree occurs, the subtree handler should be called
@@ -168,6 +169,14 @@ static const umf_ctl_node_t *ctl_find_node(const umf_ctl_node_t *nodes,
168169
if (index_entry && n->type == CTL_NODE_INDEXED) {
169170
break;
170171
} else if (strcmp(n->name, node_name) == 0) {
172+
if (n->type == CTL_NODE_LEAF && next_node != NULL) {
173+
// this is not the last node in the query, so it couldn't be leaf
174+
continue;
175+
}
176+
if (n->type != CTL_NODE_LEAF && next_node == NULL) {
177+
// this is the last node in the query, so it must be a leaf
178+
continue;
179+
}
171180
break;
172181
}
173182
}
@@ -181,7 +190,7 @@ static const umf_ctl_node_t *ctl_find_node(const umf_ctl_node_t *nodes,
181190
}
182191

183192
nodes = n->children;
184-
node_name = strtok_r(NULL, CTL_QUERY_NODE_SEPARATOR, &sptr);
193+
node_name = next_node;
185194
}
186195

187196
umf_ba_global_free(parse_str);
+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (C) 2025 Intel Corporation
3+
*
4+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*/
7+
8+
#ifdef UMF_PROVIDER_CTL_STATS_IMPL_H
9+
#error This file should not be included more than once
10+
#else
11+
#define UMF_PROVIDER_CTL_STATS_IMPL_H 1
12+
13+
#ifndef CTL_PROVIDER_TYPE
14+
#error "CTL_PROVIDER_TYPE must be defined"
15+
#endif
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
#include "ctl/ctl.h"
22+
#include "utils/utils_assert.h"
23+
24+
static int CTL_READ_HANDLER(peak_memory)(void *ctx,
25+
umf_ctl_query_source_t source,
26+
void *arg,
27+
umf_ctl_index_utlist_t *indexes,
28+
const char *extra_name,
29+
umf_ctl_query_type_t query_type) {
30+
/* suppress unused-parameter errors */
31+
(void)source, (void)indexes, (void)extra_name, (void)query_type;
32+
33+
size_t *arg_out = arg;
34+
CTL_PROVIDER_TYPE *provider = (CTL_PROVIDER_TYPE *)ctx;
35+
utils_atomic_load_acquire_size_t(&provider->stats.peak_memory, arg_out);
36+
return 0;
37+
}
38+
39+
static int CTL_READ_HANDLER(allocated_memory)(void *ctx,
40+
umf_ctl_query_source_t source,
41+
void *arg,
42+
umf_ctl_index_utlist_t *indexes,
43+
const char *extra_name,
44+
umf_ctl_query_type_t query_type) {
45+
/* suppress unused-parameter errors */
46+
(void)source, (void)indexes, (void)extra_name, (void)query_type;
47+
48+
size_t *arg_out = arg;
49+
CTL_PROVIDER_TYPE *provider = (CTL_PROVIDER_TYPE *)ctx;
50+
utils_atomic_load_acquire_size_t(&provider->stats.allocated_memory,
51+
arg_out);
52+
return 0;
53+
}
54+
55+
static int CTL_RUNNABLE_HANDLER(reset)(void *ctx, umf_ctl_query_source_t source,
56+
void *arg,
57+
umf_ctl_index_utlist_t *indexes,
58+
const char *extra_name,
59+
umf_ctl_query_type_t query_type) {
60+
/* suppress unused-parameter errors */
61+
(void)source, (void)indexes, (void)arg, (void)extra_name, (void)query_type;
62+
63+
CTL_PROVIDER_TYPE *provider = (CTL_PROVIDER_TYPE *)ctx;
64+
size_t allocated;
65+
size_t current_peak;
66+
67+
utils_atomic_load_acquire_size_t(&provider->stats.peak_memory,
68+
&current_peak);
69+
do {
70+
utils_atomic_load_acquire_size_t(&provider->stats.allocated_memory,
71+
&allocated);
72+
} while (!utils_compare_exchange_size_t(&provider->stats.peak_memory,
73+
&allocated, &current_peak));
74+
75+
return 0;
76+
}
77+
78+
static const umf_ctl_node_t CTL_NODE(peak_memory)[] = {CTL_LEAF_RUNNABLE(reset),
79+
CTL_NODE_END};
80+
81+
static const umf_ctl_node_t CTL_NODE(stats)[] = {
82+
CTL_LEAF_RO(allocated_memory), CTL_LEAF_RO(peak_memory),
83+
CTL_CHILD(peak_memory), CTL_LEAF_RUNNABLE(reset), CTL_NODE_END};
84+
85+
static inline void provider_ctl_stats_alloc(CTL_PROVIDER_TYPE *provider,
86+
size_t size) {
87+
size_t allocated =
88+
utils_fetch_and_add_size_t(&provider->stats.allocated_memory, size) +
89+
size;
90+
91+
size_t peak;
92+
utils_atomic_load_acquire_size_t(&provider->stats.peak_memory, &peak);
93+
94+
// If the compare-exchange fails, 'peak' is updated to the current value
95+
// of peak_memory. We then re-check whether allocated is still greater than
96+
// the updated peak value.
97+
while (allocated > peak &&
98+
!utils_compare_exchange_size_t(&provider->stats.peak_memory, &peak,
99+
&allocated))
100+
;
101+
}
102+
103+
static inline void provider_ctl_stats_free(CTL_PROVIDER_TYPE *provider,
104+
size_t size) {
105+
utils_fetch_and_sub_size_t(&provider->stats.allocated_memory, size);
106+
}
107+
108+
#ifdef __cplusplus
109+
}
110+
#endif
111+
#endif
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (C) 2025 Intel Corporation
3+
*
4+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*/
7+
8+
#ifndef UMF_PROVIDER_CTL_STATS_TYPE_H
9+
#define UMF_PROVIDER_CTL_STATS_TYPE_H 1
10+
11+
#include <stddef.h>
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
typedef struct ctl_stats_t {
18+
size_t allocated_memory;
19+
size_t peak_memory;
20+
} ctl_stats_t;
21+
22+
#define CTL_STATS ctl_stats_t stats
23+
24+
#ifdef __cplusplus
25+
}
26+
#endif
27+
#endif

src/provider/provider_fixed_memory.c

+39-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "base_alloc_global.h"
2121
#include "coarse.h"
2222
#include "libumf.h"
23+
#include "provider_ctl_stats_type.h"
2324
#include "utils_common.h"
2425
#include "utils_concurrency.h"
2526
#include "utils_log.h"
@@ -30,6 +31,7 @@ typedef struct fixed_memory_provider_t {
3031
void *base; // base address of memory
3132
size_t size; // size of the memory region
3233
coarse_t *coarse; // coarse library handle
34+
CTL_STATS;
3335
} fixed_memory_provider_t;
3436

3537
// Fixed Memory provider settings struct
@@ -52,6 +54,17 @@ static __TLS fixed_last_native_error_t TLS_last_native_error;
5254
#define _UMF_FIXED_RESULT_ERROR_PURGE_FORCE_FAILED \
5355
(UMF_FIXED_RESULT_ERROR_PURGE_FORCE_FAILED - UMF_FIXED_RESULT_SUCCESS)
5456

57+
#define CTL_PROVIDER_TYPE fixed_memory_provider_t
58+
#include "provider_ctl_stats_impl.h"
59+
60+
struct ctl *fixed_memory_ctl_root;
61+
static UTIL_ONCE_FLAG ctl_initialized = UTIL_ONCE_FLAG_INIT;
62+
63+
static void initialize_fixed_ctl(void) {
64+
fixed_memory_ctl_root = ctl_new();
65+
CTL_REGISTER_MODULE(fixed_memory_ctl_root, stats);
66+
}
67+
5568
static const char *Native_error_str[] = {
5669
[_UMF_FIXED_RESULT_SUCCESS] = "success",
5770
[_UMF_FIXED_RESULT_ERROR_PURGE_FORCE_FAILED] = "force purging failed"};
@@ -153,7 +166,14 @@ static umf_result_t fixed_alloc(void *provider, size_t size, size_t alignment,
153166
fixed_memory_provider_t *fixed_provider =
154167
(fixed_memory_provider_t *)provider;
155168

156-
return coarse_alloc(fixed_provider->coarse, size, alignment, resultPtr);
169+
umf_result_t ret =
170+
coarse_alloc(fixed_provider->coarse, size, alignment, resultPtr);
171+
172+
if (ret == UMF_RESULT_SUCCESS) {
173+
provider_ctl_stats_alloc(fixed_provider, size);
174+
}
175+
176+
return ret;
157177
}
158178

159179
static void fixed_get_last_native_error(void *provider, const char **ppMessage,
@@ -250,7 +270,22 @@ static umf_result_t fixed_allocation_merge(void *provider, void *lowPtr,
250270
static umf_result_t fixed_free(void *provider, void *ptr, size_t size) {
251271
fixed_memory_provider_t *fixed_provider =
252272
(fixed_memory_provider_t *)provider;
253-
return coarse_free(fixed_provider->coarse, ptr, size);
273+
274+
umf_result_t ret = coarse_free(fixed_provider->coarse, ptr, size);
275+
276+
if (ret == UMF_RESULT_SUCCESS) {
277+
provider_ctl_stats_free(fixed_provider, size);
278+
}
279+
280+
return ret;
281+
}
282+
283+
static umf_result_t fixed_ctl(void *provider, int operationType,
284+
const char *name, void *arg,
285+
umf_ctl_query_type_t query_type) {
286+
utils_init_once(&ctl_initialized, initialize_fixed_ctl);
287+
return ctl_query(fixed_memory_ctl_root, provider, operationType, name,
288+
query_type, arg);
254289
}
255290

256291
static umf_memory_provider_ops_t UMF_FIXED_MEMORY_PROVIDER_OPS = {
@@ -271,7 +306,8 @@ static umf_memory_provider_ops_t UMF_FIXED_MEMORY_PROVIDER_OPS = {
271306
.ipc.get_ipc_handle = NULL,
272307
.ipc.put_ipc_handle = NULL,
273308
.ipc.open_ipc_handle = NULL,
274-
.ipc.close_ipc_handle = NULL};
309+
.ipc.close_ipc_handle = NULL,
310+
.ctl = fixed_ctl};
275311

276312
umf_memory_provider_ops_t *umfFixedMemoryProviderOps(void) {
277313
return &UMF_FIXED_MEMORY_PROVIDER_OPS;

0 commit comments

Comments
 (0)