@@ -148,12 +148,176 @@ CTL_READ_HANDLER(reserved_memory)(void *ctx, umf_ctl_query_source_t source,
148148    return  UMF_RESULT_SUCCESS ;
149149}
150150
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 }};
153314
154315static  void  initialize_disjoint_ctl (void ) {
155316    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 );
157321}
158322
159323umf_result_t  disjoint_pool_ctl (void  * hPool ,
0 commit comments