Skip to content

Commit ce7ee13

Browse files
Merge pull request #1487 from lplewa/ctl_disjoints_stats
expose disjoint pool stats thru CTL
2 parents 503d302 + ff1e386 commit ce7ee13

File tree

3 files changed

+420
-4
lines changed

3 files changed

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

154321
static void initialize_disjoint_ctl(void) {
155322
CTL_REGISTER_MODULE(&disjoint_ctl_root, stats);
156-
// CTL_REGISTER_MODULE(&disjoint_ctl_root, name);
323+
CTL_REGISTER_MODULE(&disjoint_ctl_root, buckets);
324+
// TODO: this is hack. Need some way to register module as node with argument
325+
disjoint_ctl_root.root[disjoint_ctl_root.first_free - 1].arg =
326+
&CTL_ARG(buckets);
157327
}
158328

159329
umf_result_t disjoint_pool_ctl(void *hPool,

0 commit comments

Comments
 (0)