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