@@ -148,12 +148,178 @@ 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
+ CTL_NODE_END ,
219
+ };
220
+
221
+ #undef DEFINE_STATS_HANDLER
222
+
223
+ #ifdef UMF_DEVELOPER_MODE
224
+ #define VALIDATE_BUCKETS_NAME (indexes ) \
225
+ if (strcmp("buckets", indexes->name) != 0) { \
226
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
227
+ }
228
+ #else
229
+ #define VALIDATE_BUCKETS_NAME (indexes ) \
230
+ do { \
231
+ } while (0);
232
+ #endif
233
+
234
+ #define DEFINE_BUCKET_STATS_HANDLER (NAME , MEMBER ) \
235
+ static umf_result_t CTL_READ_HANDLER(NAME, perBucket)( \
236
+ void *ctx, umf_ctl_query_source_t source, void *arg, size_t size, \
237
+ umf_ctl_index_utlist_t *indexes) { \
238
+ (void)source; \
239
+ \
240
+ disjoint_pool_t *pool = (disjoint_pool_t *)ctx; \
241
+ if (arg == NULL || size != sizeof(size_t)) { \
242
+ LOG_ERR("arg is NULL or size is not sizeof(size_t)"); \
243
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
244
+ } \
245
+ \
246
+ VALIDATE_BUCKETS_NAME(indexes); \
247
+ if (strcmp(#MEMBER, "size") != 0 && !pool->params.pool_trace) { \
248
+ LOG_ERR("pool trace is disabled, cannot read " #NAME); \
249
+ return UMF_RESULT_ERROR_NOT_SUPPORTED; \
250
+ } \
251
+ \
252
+ size_t idx; \
253
+ idx = *(size_t *)indexes->arg; \
254
+ \
255
+ if (idx >= pool->buckets_num) { \
256
+ LOG_ERR("bucket id %zu is out of range [0, %zu)", idx, \
257
+ pool->buckets_num); \
258
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT; \
259
+ } \
260
+ \
261
+ bucket_t *bucket = pool->buckets[idx]; \
262
+ *(size_t *)arg = bucket->MEMBER; \
263
+ \
264
+ return UMF_RESULT_SUCCESS; \
265
+ }
266
+
267
+ DEFINE_BUCKET_STATS_HANDLER (alloc_nr , alloc_count )
268
+ DEFINE_BUCKET_STATS_HANDLER (alloc_pool_nr , alloc_pool_count )
269
+ DEFINE_BUCKET_STATS_HANDLER (free_nr , free_count )
270
+ DEFINE_BUCKET_STATS_HANDLER (curr_slabs_in_use , curr_slabs_in_use )
271
+ DEFINE_BUCKET_STATS_HANDLER (curr_slabs_in_pool , curr_slabs_in_pool )
272
+ DEFINE_BUCKET_STATS_HANDLER (max_slabs_in_use , max_slabs_in_use )
273
+ DEFINE_BUCKET_STATS_HANDLER (max_slabs_in_pool , max_slabs_in_pool )
274
+
275
+ static const umf_ctl_node_t CTL_NODE (stats , perBucket )[] = {
276
+ CTL_LEAF_RO (alloc_nr , perBucket ),
277
+ CTL_LEAF_RO (alloc_pool_nr , perBucket ),
278
+ CTL_LEAF_RO (free_nr , perBucket ),
279
+ CTL_LEAF_RO (curr_slabs_in_use , perBucket ),
280
+ CTL_LEAF_RO (curr_slabs_in_pool , perBucket ),
281
+ CTL_LEAF_RO (max_slabs_in_use , perBucket ),
282
+ CTL_LEAF_RO (max_slabs_in_pool , perBucket ),
283
+ CTL_NODE_END ,
284
+ };
285
+
286
+ // Not a counter; but it is read exactly like other per-bucket stats, so we can use macro.
287
+ DEFINE_BUCKET_STATS_HANDLER (size , size )
288
+
289
+ #undef DEFINE_BUCKET_STATS_HANDLER
290
+
291
+ static const umf_ctl_node_t CTL_NODE (buckets )[] = {
292
+ CTL_LEAF_RO (count ), CTL_LEAF_RO (size , perBucket ),
293
+ CTL_CHILD (stats , perBucket ), CTL_NODE_END };
294
+
295
+ static int bucket_id_parser (const void * arg , void * dest , size_t dest_size ) {
296
+ size_t * out = (size_t * )dest ;
297
+
298
+ if (arg == NULL ) {
299
+ * out = SIZE_MAX ;
300
+ return 1 ; // node n
301
+ }
302
+
303
+ int ret = ctl_arg_unsigned (arg , dest , dest_size );
304
+ if (ret ) {
305
+ * out = SIZE_MAX ;
306
+ return 1 ;
307
+ }
308
+
309
+ return 0 ;
310
+ }
311
+
312
+ static const struct ctl_argument CTL_ARG (buckets ) = {
313
+ sizeof (size_t ),
314
+ {{0 , sizeof (size_t ), CTL_ARG_TYPE_UNSIGNED_LONG_LONG , bucket_id_parser },
315
+ CTL_ARG_PARSER_END }};
153
316
154
317
static void initialize_disjoint_ctl (void ) {
155
318
CTL_REGISTER_MODULE (& disjoint_ctl_root , stats );
156
- // CTL_REGISTER_MODULE(&disjoint_ctl_root, name);
319
+ CTL_REGISTER_MODULE (& disjoint_ctl_root , buckets );
320
+ // TODO: this is hack. Need some way to register module as node with argument
321
+ disjoint_ctl_root .root [disjoint_ctl_root .first_free - 1 ].arg =
322
+ & CTL_ARG (buckets );
157
323
}
158
324
159
325
umf_result_t disjoint_pool_ctl (void * hPool ,
0 commit comments