Skip to content

Commit a6b39f3

Browse files
committed
expose disjoint pool stats thru CTL
1 parent d291734 commit a6b39f3

File tree

3 files changed

+408
-4
lines changed

3 files changed

+408
-4
lines changed

src/memory_pool.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ typedef struct by_name_arg_t {
313313
} by_name_arg_t;
314314

315315
// parses optional size_t argument. if arg is not integer then sets out to size_max
316-
int by_name_index_parser(const void *arg, void *dest, size_t dest_size) {
316+
static int by_name_index_parser(const void *arg, void *dest, size_t dest_size) {
317317
size_t *out = (size_t *)dest;
318318

319319
if (arg == NULL) {

src/pool/pool_disjoint.c

Lines changed: 170 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ static umf_result_t CTL_READ_HANDLER(name)(void *ctx,
4444
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
4545

4646
if (arg == NULL) {
47+
LOG_ERR("arg is NULL");
4748
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
4849
}
4950

@@ -64,6 +65,7 @@ static umf_result_t CTL_WRITE_HANDLER(name)(void *ctx,
6465
(void)source, (void)indexes, (void)size;
6566
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
6667
if (arg == NULL) {
68+
LOG_ERR("arg is NULL");
6769
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
6870
}
6971

@@ -81,6 +83,7 @@ CTL_READ_HANDLER(used_memory)(void *ctx, umf_ctl_query_source_t source,
8183
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
8284

8385
if (arg == NULL || size != sizeof(size_t)) {
86+
LOG_ERR("arg is NULL or size is not sizeof(size_t)");
8487
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
8588
}
8689

@@ -119,6 +122,7 @@ CTL_READ_HANDLER(reserved_memory)(void *ctx, umf_ctl_query_source_t source,
119122
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
120123

121124
if (arg == NULL || size != sizeof(size_t)) {
125+
LOG_ERR("arg is NULL or size is not sizeof(size_t)");
122126
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
123127
}
124128

@@ -148,12 +152,175 @@ CTL_READ_HANDLER(reserved_memory)(void *ctx, umf_ctl_query_source_t source,
148152
return UMF_RESULT_SUCCESS;
149153
}
150154

151-
static const umf_ctl_node_t CTL_NODE(stats)[] = {CTL_LEAF_RO(used_memory),
152-
CTL_LEAF_RO(reserved_memory)};
155+
static umf_result_t CTL_READ_HANDLER(count)(void *ctx,
156+
umf_ctl_query_source_t source,
157+
void *arg, size_t size,
158+
umf_ctl_index_utlist_t *indexes) {
159+
(void)source;
160+
161+
disjoint_pool_t *pool = (disjoint_pool_t *)ctx;
162+
if (arg == NULL || size != sizeof(size_t)) {
163+
LOG_ERR("arg is NULL or size is not sizeof(size_t)");
164+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
165+
}
166+
167+
if (*(size_t *)indexes->arg != SIZE_MAX) {
168+
LOG_ERR("to read bucket count, you must call it without bucket id");
169+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
170+
}
171+
*(size_t *)arg = pool->buckets_num;
172+
173+
return UMF_RESULT_SUCCESS;
174+
}
175+
176+
#define DEFINE_STATS_HANDLER(NAME, MEMBER) \
177+
static umf_result_t CTL_READ_HANDLER(NAME)( \
178+
void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, \
179+
umf_ctl_index_utlist_t *indexes) { \
180+
(void)source; \
181+
(void)indexes; \
182+
disjoint_pool_t *pool = (disjoint_pool_t *)ctx; \
183+
\
184+
if (arg == NULL || size != sizeof(size_t)) { \
185+
LOG_ERR("arg is NULL or size is not sizeof(size_t)"); \
186+
return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
187+
} \
188+
\
189+
if (!pool->params.pool_trace) { \
190+
LOG_ERR("pool trace is disabled, cannot read " #NAME); \
191+
return UMF_RESULT_ERROR_NOT_SUPPORTED; \
192+
} \
193+
\
194+
size_t total = 0; \
195+
for (size_t i = 0; i < pool->buckets_num; ++i) { \
196+
bucket_t *bucket = pool->buckets[i]; \
197+
utils_mutex_lock(&bucket->bucket_lock); \
198+
total += bucket->MEMBER; \
199+
utils_mutex_unlock(&bucket->bucket_lock); \
200+
} \
201+
\
202+
*(size_t *)arg = total; \
203+
return UMF_RESULT_SUCCESS; \
204+
}
205+
206+
DEFINE_STATS_HANDLER(alloc_num, alloc_count)
207+
DEFINE_STATS_HANDLER(alloc_pool_num, alloc_pool_count)
208+
DEFINE_STATS_HANDLER(free_num, free_count)
209+
DEFINE_STATS_HANDLER(curr_slabs_in_use, curr_slabs_in_use)
210+
DEFINE_STATS_HANDLER(curr_slabs_in_pool, curr_slabs_in_pool)
211+
DEFINE_STATS_HANDLER(max_slabs_in_use, max_slabs_in_use)
212+
DEFINE_STATS_HANDLER(max_slabs_in_pool, max_slabs_in_pool)
213+
214+
static const umf_ctl_node_t CTL_NODE(stats)[] = {
215+
CTL_LEAF_RO(used_memory), CTL_LEAF_RO(reserved_memory),
216+
CTL_LEAF_RO(alloc_num), CTL_LEAF_RO(alloc_pool_num),
217+
CTL_LEAF_RO(free_num), CTL_LEAF_RO(curr_slabs_in_use),
218+
CTL_LEAF_RO(curr_slabs_in_pool), CTL_LEAF_RO(max_slabs_in_use),
219+
CTL_LEAF_RO(max_slabs_in_pool), CTL_NODE_END,
220+
};
221+
222+
#undef DEFINE_STATS_HANDLER
223+
224+
#ifdef UMF_DEVELOPER_MODE
225+
#define VALIDATE_BUCKETS_NAME(indexes) \
226+
if (strcmp("buckets", indexes->name) != 0) { \
227+
return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
228+
}
229+
#else
230+
#define VALIDATE_BUCKETS_NAME(indexes) \
231+
do { \
232+
} while (0);
233+
#endif
234+
235+
#define DEFINE_BUCKET_STATS_HANDLER(NAME, MEMBER) \
236+
static umf_result_t CTL_READ_HANDLER(NAME, perBucket)( \
237+
void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, \
238+
umf_ctl_index_utlist_t *indexes) { \
239+
(void)source; \
240+
\
241+
disjoint_pool_t *pool = (disjoint_pool_t *)ctx; \
242+
if (arg == NULL || size != sizeof(size_t)) { \
243+
LOG_ERR("arg is NULL or size is not sizeof(size_t)"); \
244+
return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
245+
} \
246+
\
247+
VALIDATE_BUCKETS_NAME(indexes); \
248+
if (strcmp(#MEMBER, "size") != 0 && !pool->params.pool_trace) { \
249+
LOG_ERR("pool trace is disabled, cannot read " #NAME); \
250+
return UMF_RESULT_ERROR_NOT_SUPPORTED; \
251+
} \
252+
\
253+
size_t idx; \
254+
idx = *(size_t *)indexes->arg; \
255+
\
256+
if (idx >= pool->buckets_num) { \
257+
LOG_ERR("bucket id %zu is out of range [0, %zu)", idx, \
258+
pool->buckets_num); \
259+
return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
260+
} \
261+
\
262+
bucket_t *bucket = pool->buckets[idx]; \
263+
*(size_t *)arg = bucket->MEMBER; \
264+
\
265+
return UMF_RESULT_SUCCESS; \
266+
}
267+
268+
DEFINE_BUCKET_STATS_HANDLER(alloc_num, alloc_count)
269+
DEFINE_BUCKET_STATS_HANDLER(alloc_pool_num, alloc_pool_count)
270+
DEFINE_BUCKET_STATS_HANDLER(free_num, free_count)
271+
DEFINE_BUCKET_STATS_HANDLER(curr_slabs_in_use, curr_slabs_in_use)
272+
DEFINE_BUCKET_STATS_HANDLER(curr_slabs_in_pool, curr_slabs_in_pool)
273+
DEFINE_BUCKET_STATS_HANDLER(max_slabs_in_use, max_slabs_in_use)
274+
DEFINE_BUCKET_STATS_HANDLER(max_slabs_in_pool, max_slabs_in_pool)
275+
276+
static const umf_ctl_node_t CTL_NODE(stats, perBucket)[] = {
277+
CTL_LEAF_RO(alloc_num, perBucket),
278+
CTL_LEAF_RO(alloc_pool_num, perBucket),
279+
CTL_LEAF_RO(free_num, perBucket),
280+
CTL_LEAF_RO(curr_slabs_in_use, perBucket),
281+
CTL_LEAF_RO(curr_slabs_in_pool, perBucket),
282+
CTL_LEAF_RO(max_slabs_in_use, perBucket),
283+
CTL_LEAF_RO(max_slabs_in_pool, perBucket),
284+
CTL_NODE_END,
285+
};
286+
287+
// Not a counter; but it is read exactly like other per-bucket stats, so we can use macro.
288+
DEFINE_BUCKET_STATS_HANDLER(size, size)
289+
290+
#undef DEFINE_BUCKET_STATS_HANDLER
291+
292+
static const umf_ctl_node_t CTL_NODE(buckets)[] = {
293+
CTL_LEAF_RO(count), CTL_LEAF_RO(size, perBucket),
294+
CTL_CHILD(stats, perBucket), CTL_NODE_END};
295+
296+
static int bucket_id_parser(const void *arg, void *dest, size_t dest_size) {
297+
size_t *out = (size_t *)dest;
298+
299+
if (arg == NULL) {
300+
*out = SIZE_MAX;
301+
return 1; // node n
302+
}
303+
304+
int ret = ctl_arg_unsigned(arg, dest, dest_size);
305+
if (ret) {
306+
*out = SIZE_MAX;
307+
return 1;
308+
}
309+
310+
return 0;
311+
}
312+
313+
static const struct ctl_argument CTL_ARG(buckets) = {
314+
sizeof(size_t),
315+
{{0, sizeof(size_t), CTL_ARG_TYPE_UNSIGNED_LONG_LONG, bucket_id_parser},
316+
CTL_ARG_PARSER_END}};
153317

154318
static void initialize_disjoint_ctl(void) {
155319
CTL_REGISTER_MODULE(&disjoint_ctl_root, stats);
156-
// CTL_REGISTER_MODULE(&disjoint_ctl_root, name);
320+
CTL_REGISTER_MODULE(&disjoint_ctl_root, buckets);
321+
// TODO: this is hack. Need some way to register module as node with argument
322+
disjoint_ctl_root.root[disjoint_ctl_root.first_free - 1].arg =
323+
&CTL_ARG(buckets);
157324
}
158325

159326
umf_result_t disjoint_pool_ctl(void *hPool,

0 commit comments

Comments
 (0)