blob: b7743ec70f2eff28f7d1febeea2bc3e55cb38ace [file] [log] [blame]
Damjan Marion8973b072022-03-01 15:51:18 +01001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2022 Cisco Systems, Inc.
3 */
4
5#include <vlib/vlib.h>
6#include <vlib/stats/stats.h>
7
8vlib_stats_main_t vlib_stats_main;
9
Damjan Marion8973b072022-03-01 15:51:18 +010010void
11vlib_stats_segment_lock (void)
12{
Damjan Mariond1bd9af2022-03-14 13:04:38 +010013 vlib_main_t *vm = vlib_get_main ();
Damjan Marion8973b072022-03-01 15:51:18 +010014 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
Damjan Mariond1bd9af2022-03-14 13:04:38 +010015
16 /* already locked by us */
17 if (sm->shared_header->in_progress &&
18 vm->thread_index == sm->locking_thread_index)
19 goto done;
20
21 ASSERT (sm->locking_thread_index == ~0);
22 ASSERT (sm->shared_header->in_progress == 0);
23 ASSERT (sm->n_locks == 0);
24
Damjan Marion8973b072022-03-01 15:51:18 +010025 clib_spinlock_lock (sm->stat_segment_lockp);
Damjan Mariond1bd9af2022-03-14 13:04:38 +010026
Damjan Marion8973b072022-03-01 15:51:18 +010027 sm->shared_header->in_progress = 1;
Damjan Mariond1bd9af2022-03-14 13:04:38 +010028 sm->locking_thread_index = vm->thread_index;
29done:
30 sm->n_locks++;
Damjan Marion8973b072022-03-01 15:51:18 +010031}
32
33void
34vlib_stats_segment_unlock (void)
35{
Damjan Mariond1bd9af2022-03-14 13:04:38 +010036 vlib_main_t *vm = vlib_get_main ();
Damjan Marion8973b072022-03-01 15:51:18 +010037 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
Damjan Mariond1bd9af2022-03-14 13:04:38 +010038
39 ASSERT (sm->shared_header->in_progress == 1);
40 ASSERT (sm->locking_thread_index == vm->thread_index);
41 ASSERT (sm->n_locks > 0);
42
43 sm->n_locks--;
44
45 if (sm->n_locks > 0)
46 return;
47
Damjan Marion8973b072022-03-01 15:51:18 +010048 sm->shared_header->epoch++;
Damjan Mariond1bd9af2022-03-14 13:04:38 +010049 __atomic_store_n (&sm->shared_header->in_progress, 0, __ATOMIC_RELEASE);
50 sm->locking_thread_index = ~0;
Damjan Marion8973b072022-03-01 15:51:18 +010051 clib_spinlock_unlock (sm->stat_segment_lockp);
52}
53
54/*
55 * Change heap to the stats shared memory segment
56 */
57void *
58vlib_stats_set_heap ()
59{
60 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
61
62 ASSERT (sm && sm->shared_header);
63 return clib_mem_set_heap (sm->heap);
64}
65
66u32
67vlib_stats_find_entry_index (char *fmt, ...)
68{
69 u8 *name;
70 va_list va;
71
72 va_start (va, fmt);
73 name = va_format (0, fmt, &va);
74 va_end (va);
75 vec_add1 (name, 0);
76
77 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
78 hash_pair_t *hp = hash_get_pair (sm->directory_vector_by_name, name);
79 vec_free (name);
80 return hp ? hp->value[0] : STAT_SEGMENT_INDEX_INVALID;
81}
82
83static void
84hash_set_str_key_alloc (uword **h, const char *key, uword v)
85{
86 int size = strlen (key) + 1;
87 void *copy = clib_mem_alloc (size);
88 clib_memcpy_fast (copy, key, size);
89 hash_set_mem (*h, copy, v);
90}
91
92static void
93hash_unset_str_key_free (uword **h, const char *key)
94{
95 hash_pair_t *hp = hash_get_pair_mem (*h, key);
96 if (hp)
97 {
98 void *_k = uword_to_pointer (hp->key, void *);
99 hash_unset_mem (*h, _k);
100 clib_mem_free (_k);
101 }
102}
103
104u32
105vlib_stats_create_counter (vlib_stats_entry_t *e)
106{
107 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
Damjan Marioneecec8c2022-04-06 12:06:41 +0200108 u32 index;
Damjan Marion8973b072022-03-01 15:51:18 +0100109
Damjan Marioneecec8c2022-04-06 12:06:41 +0200110 if (sm->dir_vector_first_free_elt != CLIB_U32_MAX)
111 {
112 index = sm->dir_vector_first_free_elt;
113 sm->dir_vector_first_free_elt = sm->directory_vector[index].index;
114 }
115 else
116 {
117 index = vec_len (sm->directory_vector);
118 vec_validate (sm->directory_vector, index);
119 }
Damjan Marion8973b072022-03-01 15:51:18 +0100120
Damjan Marion8973b072022-03-01 15:51:18 +0100121 sm->directory_vector[index] = *e;
122
Damjan Marion8973b072022-03-01 15:51:18 +0100123 hash_set_str_key_alloc (&sm->directory_vector_by_name, e->name, index);
124
125 return index;
126}
127
128void
129vlib_stats_remove_entry (u32 entry_index)
130{
131 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
132 vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
Damjan Marion8973b072022-03-01 15:51:18 +0100133 counter_t **c;
Damjan Marion58fd4812022-03-14 13:04:38 +0100134 vlib_counter_t **vc;
Damjan Marionc5d81b92022-04-15 15:53:17 +0200135 void *oldheap;
Damjan Marion8973b072022-03-01 15:51:18 +0100136 u32 i;
137
138 if (entry_index >= vec_len (sm->directory_vector))
139 return;
140
Damjan Marion58fd4812022-03-14 13:04:38 +0100141 vlib_stats_segment_lock ();
142
Damjan Marion8973b072022-03-01 15:51:18 +0100143 switch (e->type)
144 {
145 case STAT_DIR_TYPE_NAME_VECTOR:
146 for (i = 0; i < vec_len (e->string_vector); i++)
147 vec_free (e->string_vector[i]);
148 vec_free (e->string_vector);
149 break;
150
151 case STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE:
152 c = e->data;
153 e->data = 0;
Damjan Marionc5d81b92022-04-15 15:53:17 +0200154 oldheap = clib_mem_set_heap (sm->heap);
Damjan Marion8973b072022-03-01 15:51:18 +0100155 for (i = 0; i < vec_len (c); i++)
156 vec_free (c[i]);
157 vec_free (c);
Damjan Marionc5d81b92022-04-15 15:53:17 +0200158 clib_mem_set_heap (oldheap);
Damjan Marion8973b072022-03-01 15:51:18 +0100159 break;
160
Damjan Marion58fd4812022-03-14 13:04:38 +0100161 case STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED:
162 vc = e->data;
163 e->data = 0;
Damjan Marionc5d81b92022-04-15 15:53:17 +0200164 oldheap = clib_mem_set_heap (sm->heap);
Damjan Marion58fd4812022-03-14 13:04:38 +0100165 for (i = 0; i < vec_len (vc); i++)
166 vec_free (vc[i]);
167 vec_free (vc);
Damjan Marionc5d81b92022-04-15 15:53:17 +0200168 clib_mem_set_heap (oldheap);
Damjan Marion58fd4812022-03-14 13:04:38 +0100169 break;
170
Damjan Marion8973b072022-03-01 15:51:18 +0100171 case STAT_DIR_TYPE_SCALAR_INDEX:
172 case STAT_DIR_TYPE_SYMLINK:
173 break;
174 default:
175 ASSERT (0);
176 }
177
Damjan Marion58fd4812022-03-14 13:04:38 +0100178 vlib_stats_segment_unlock ();
179
Damjan Marion8973b072022-03-01 15:51:18 +0100180 hash_unset_str_key_free (&sm->directory_vector_by_name, e->name);
181
182 memset (e, 0, sizeof (*e));
183 e->type = STAT_DIR_TYPE_EMPTY;
Damjan Marioneecec8c2022-04-06 12:06:41 +0200184
185 e->value = sm->dir_vector_first_free_elt;
186 sm->dir_vector_first_free_elt = entry_index;
Damjan Marion8973b072022-03-01 15:51:18 +0100187}
188
189static void
190vlib_stats_set_entry_name (vlib_stats_entry_t *e, char *s)
191{
192 u32 i, len = VLIB_STATS_MAX_NAME_SZ - 1;
193
194 for (i = 0; i < len; i++)
195 {
196 e->name[i] = s[i];
197 if (s[i] == 0)
198 return;
199 }
200 ASSERT (i < VLIB_STATS_MAX_NAME_SZ - 1);
201 s[i] = 0;
202}
203
Damjan Marion58fd4812022-03-14 13:04:38 +0100204static u32
205vlib_stats_new_entry_internal (stat_directory_type_t t, u8 *name)
Damjan Marion8973b072022-03-01 15:51:18 +0100206{
Damjan Marion8973b072022-03-01 15:51:18 +0100207 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
208 vlib_stats_shared_header_t *shared_header = sm->shared_header;
Damjan Marion58fd4812022-03-14 13:04:38 +0100209 vlib_stats_entry_t e = { .type = t };
Damjan Marion8973b072022-03-01 15:51:18 +0100210
211 ASSERT (shared_header);
212
Damjan Marion58fd4812022-03-14 13:04:38 +0100213 u32 vector_index = vlib_stats_find_entry_index ("%v", name);
214 if (vector_index != STAT_SEGMENT_INDEX_INVALID) /* Already registered */
Damjan Marion8973b072022-03-01 15:51:18 +0100215 {
Damjan Marion58fd4812022-03-14 13:04:38 +0100216 vector_index = ~0;
217 goto done;
Damjan Marion8973b072022-03-01 15:51:18 +0100218 }
219
Damjan Marion58fd4812022-03-14 13:04:38 +0100220 vec_add1 (name, 0);
221 vlib_stats_set_entry_name (&e, (char *) name);
Damjan Marion8973b072022-03-01 15:51:18 +0100222
Damjan Marion58fd4812022-03-14 13:04:38 +0100223 vlib_stats_segment_lock ();
224 vector_index = vlib_stats_create_counter (&e);
225
Damjan Marion8973b072022-03-01 15:51:18 +0100226 shared_header->directory_vector = sm->directory_vector;
227
228 vlib_stats_segment_unlock ();
Damjan Marion58fd4812022-03-14 13:04:38 +0100229
230done:
231 vec_free (name);
232 return vector_index;
233}
234
235u32
236vlib_stats_add_gauge (char *fmt, ...)
237{
238 va_list va;
239 u8 *name;
240
241 va_start (va, fmt);
242 name = va_format (0, fmt, &va);
243 va_end (va);
244 return vlib_stats_new_entry_internal (STAT_DIR_TYPE_SCALAR_INDEX, name);
Damjan Marion8973b072022-03-01 15:51:18 +0100245}
246
247void
Damjan Marion8973b072022-03-01 15:51:18 +0100248vlib_stats_set_gauge (u32 index, u64 value)
249{
250 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
251
252 ASSERT (index < vec_len (sm->directory_vector));
253 sm->directory_vector[index].value = value;
254}
255
256u32
257vlib_stats_add_timestamp (char *fmt, ...)
258{
259 va_list va;
260 u8 *name;
261
262 va_start (va, fmt);
263 name = va_format (0, fmt, &va);
264 va_end (va);
265 return vlib_stats_new_entry_internal (STAT_DIR_TYPE_SCALAR_INDEX, name);
266}
267
268void
269vlib_stats_set_timestamp (u32 entry_index, f64 value)
270{
271 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
272
273 ASSERT (entry_index < vec_len (sm->directory_vector));
274 sm->directory_vector[entry_index].value = value;
275}
276
Damjan Marionc5d81b92022-04-15 15:53:17 +0200277vlib_stats_string_vector_t
Damjan Marion8973b072022-03-01 15:51:18 +0100278vlib_stats_add_string_vector (char *fmt, ...)
279{
Damjan Marionc5d81b92022-04-15 15:53:17 +0200280 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
Damjan Marion8973b072022-03-01 15:51:18 +0100281 va_list va;
Damjan Marionc5d81b92022-04-15 15:53:17 +0200282 vlib_stats_header_t *sh;
283 vlib_stats_string_vector_t sv;
284 u32 index;
Damjan Marion8973b072022-03-01 15:51:18 +0100285 u8 *name;
286
287 va_start (va, fmt);
288 name = va_format (0, fmt, &va);
289 va_end (va);
Damjan Marionc5d81b92022-04-15 15:53:17 +0200290
291 index = vlib_stats_new_entry_internal (STAT_DIR_TYPE_NAME_VECTOR, name);
292 if (index == CLIB_U32_MAX)
293 return 0;
294
295 sv = vec_new_generic (vlib_stats_string_vector_t, 0,
296 sizeof (vlib_stats_header_t), 0, sm->heap);
297 sh = vec_header (sv);
298 sh->entry_index = index;
299 sm->directory_vector[index].string_vector = sv;
300 return sv;
Damjan Marion8973b072022-03-01 15:51:18 +0100301}
302
303void
Damjan Marionc5d81b92022-04-15 15:53:17 +0200304vlib_stats_set_string_vector (vlib_stats_string_vector_t *svp,
305 u32 vector_index, char *fmt, ...)
Damjan Marion8973b072022-03-01 15:51:18 +0100306{
307 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
Damjan Marionc5d81b92022-04-15 15:53:17 +0200308 vlib_stats_header_t *sh = vec_header (*svp);
309 vlib_stats_entry_t *e = vlib_stats_get_entry (sm, sh->entry_index);
Damjan Marion8973b072022-03-01 15:51:18 +0100310 va_list va;
Damjan Marionc5d81b92022-04-15 15:53:17 +0200311 u8 *s;
Damjan Marion8973b072022-03-01 15:51:18 +0100312
Damjan Marionc5d81b92022-04-15 15:53:17 +0200313 if (fmt[0] == 0)
314 {
315 if (vec_len (e->string_vector) <= vector_index)
316 return;
317
318 if (e->string_vector[vector_index] == 0)
319 return;
320
321 vlib_stats_segment_lock ();
322 vec_free (e->string_vector[vector_index]);
323 vlib_stats_segment_unlock ();
324 return;
325 }
326
Damjan Marion8973b072022-03-01 15:51:18 +0100327 vlib_stats_segment_lock ();
328
Damjan Marionc5d81b92022-04-15 15:53:17 +0200329 ASSERT (e->string_vector);
330
Damjan Marion8973b072022-03-01 15:51:18 +0100331 vec_validate (e->string_vector, vector_index);
Damjan Marionc5d81b92022-04-15 15:53:17 +0200332 svp[0] = e->string_vector;
333
334 s = e->string_vector[vector_index];
335
336 if (s == 0)
337 s = vec_new_heap (u8 *, 0, sm->heap);
338
339 vec_reset_length (s);
Damjan Marion8973b072022-03-01 15:51:18 +0100340
341 va_start (va, fmt);
Damjan Marionc5d81b92022-04-15 15:53:17 +0200342 s = va_format (s, fmt, &va);
Damjan Marion8973b072022-03-01 15:51:18 +0100343 va_end (va);
Damjan Marion4cfb46d2022-05-06 12:38:19 +0200344 vec_add1 (s, 0);
Damjan Marion8973b072022-03-01 15:51:18 +0100345
Damjan Marionc5d81b92022-04-15 15:53:17 +0200346 e->string_vector[vector_index] = s;
347
Damjan Marion8973b072022-03-01 15:51:18 +0100348 vlib_stats_segment_unlock ();
Damjan Marion8973b072022-03-01 15:51:18 +0100349}
350
Damjan Marion0530d092022-05-06 12:39:10 +0200351void
352vlib_stats_free_string_vector (vlib_stats_string_vector_t *sv)
353{
354 vlib_stats_header_t *sh = vec_header (*sv);
355 vlib_stats_remove_entry (sh->entry_index);
356}
357
Damjan Marion8973b072022-03-01 15:51:18 +0100358u32
359vlib_stats_add_counter_vector (char *fmt, ...)
360{
361 va_list va;
362 u8 *name;
363
364 va_start (va, fmt);
365 name = va_format (0, fmt, &va);
366 va_end (va);
367 return vlib_stats_new_entry_internal (STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE,
368 name);
369}
370
Damjan Marion58fd4812022-03-14 13:04:38 +0100371u32
372vlib_stats_add_counter_pair_vector (char *fmt, ...)
373{
374 va_list va;
375 u8 *name;
376
377 va_start (va, fmt);
378 name = va_format (0, fmt, &va);
379 va_end (va);
380 return vlib_stats_new_entry_internal (STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED,
381 name);
382}
383
384static int
385vlib_stats_validate_will_expand_internal (u32 entry_index, va_list *va)
Damjan Marion8973b072022-03-01 15:51:18 +0100386{
387 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
388 vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
389 void *oldheap;
Damjan Marion58fd4812022-03-14 13:04:38 +0100390 int rv = 1;
Damjan Marion8973b072022-03-01 15:51:18 +0100391
392 oldheap = clib_mem_set_heap (sm->heap);
Damjan Marion58fd4812022-03-14 13:04:38 +0100393 if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE)
394 {
395 u32 idx0 = va_arg (*va, u32);
396 u32 idx1 = va_arg (*va, u32);
397 u64 **data = e->data;
Damjan Marion8973b072022-03-01 15:51:18 +0100398
Dmitry Valter1c8c6d32022-04-08 10:08:32 +0000399 if (idx0 >= vec_len (data))
Damjan Marion58fd4812022-03-14 13:04:38 +0100400 goto done;
Damjan Marion8973b072022-03-01 15:51:18 +0100401
Damjan Marion58fd4812022-03-14 13:04:38 +0100402 for (u32 i = 0; i <= idx0; i++)
Damjan Marionf0574da2022-03-21 21:08:00 +0100403 if (idx1 >= vec_max_len (data[i]))
Damjan Marion58fd4812022-03-14 13:04:38 +0100404 goto done;
405 }
406 else if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED)
407 {
408 u32 idx0 = va_arg (*va, u32);
409 u32 idx1 = va_arg (*va, u32);
410 vlib_counter_t **data = e->data;
411
412 va_end (*va);
413
Dmitry Valter1c8c6d32022-04-08 10:08:32 +0000414 if (idx0 >= vec_len (data))
Damjan Marion58fd4812022-03-14 13:04:38 +0100415 goto done;
416
417 for (u32 i = 0; i <= idx0; i++)
Damjan Marionf0574da2022-03-21 21:08:00 +0100418 if (idx1 >= vec_max_len (data[i]))
Damjan Marion58fd4812022-03-14 13:04:38 +0100419 goto done;
420 }
421 else
422 ASSERT (0);
423
424 rv = 0;
425done:
Damjan Marion8973b072022-03-01 15:51:18 +0100426 clib_mem_set_heap (oldheap);
Damjan Marion58fd4812022-03-14 13:04:38 +0100427 return rv;
428}
429
430int
431vlib_stats_validate_will_expand (u32 entry_index, ...)
432{
433 va_list va;
434 int rv;
435
436 va_start (va, entry_index);
437 rv = vlib_stats_validate_will_expand_internal (entry_index, &va);
438 va_end (va);
439 return rv;
440}
441
442void
443vlib_stats_validate (u32 entry_index, ...)
444{
445 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
446 vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
447 void *oldheap;
448 va_list va;
449 int will_expand;
450
451 va_start (va, entry_index);
452 will_expand = vlib_stats_validate_will_expand_internal (entry_index, &va);
453 va_end (va);
454
455 if (will_expand)
456 vlib_stats_segment_lock ();
457
458 oldheap = clib_mem_set_heap (sm->heap);
459
460 va_start (va, entry_index);
461
462 if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE)
463 {
464 u32 idx0 = va_arg (va, u32);
465 u32 idx1 = va_arg (va, u32);
466 u64 **data = e->data;
467
468 vec_validate_aligned (data, idx0, CLIB_CACHE_LINE_BYTES);
469
470 for (u32 i = 0; i <= idx0; i++)
471 vec_validate_aligned (data[i], idx1, CLIB_CACHE_LINE_BYTES);
472 e->data = data;
473 }
474 else if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED)
475 {
476 u32 idx0 = va_arg (va, u32);
477 u32 idx1 = va_arg (va, u32);
478 vlib_counter_t **data = e->data;
479
480 vec_validate_aligned (data, idx0, CLIB_CACHE_LINE_BYTES);
481
482 for (u32 i = 0; i <= idx0; i++)
483 vec_validate_aligned (data[i], idx1, CLIB_CACHE_LINE_BYTES);
484 e->data = data;
485 }
486 else
487 ASSERT (0);
488
489 va_end (va);
490
491 clib_mem_set_heap (oldheap);
492
493 if (will_expand)
494 vlib_stats_segment_unlock ();
Damjan Marion8973b072022-03-01 15:51:18 +0100495}
496
497u32
498vlib_stats_add_symlink (u32 entry_index, u32 vector_index, char *fmt, ...)
499{
500 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
501 vlib_stats_shared_header_t *shared_header = sm->shared_header;
502 vlib_stats_entry_t e;
503 va_list va;
504 u8 *name;
505
506 ASSERT (shared_header);
507 ASSERT (entry_index < vec_len (sm->directory_vector));
508
509 va_start (va, fmt);
510 name = va_format (0, fmt, &va);
511 va_end (va);
512
513 if (vlib_stats_find_entry_index ("%v", name) == STAT_SEGMENT_INDEX_INVALID)
514 {
515 vec_add1 (name, 0);
516 vlib_stats_set_entry_name (&e, (char *) name);
517 e.type = STAT_DIR_TYPE_SYMLINK;
518 e.index1 = entry_index;
519 e.index2 = vector_index;
520 vector_index = vlib_stats_create_counter (&e);
521
522 /* Warn clients to refresh any pointers they might be holding */
523 shared_header->directory_vector = sm->directory_vector;
524 }
525 else
526 vector_index = ~0;
527
528 vec_free (name);
529 return vector_index;
530}
531
532void
533vlib_stats_rename_symlink (u64 entry_index, char *fmt, ...)
534{
535 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
536 vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
537 va_list va;
538 u8 *new_name;
539
540 hash_unset_str_key_free (&sm->directory_vector_by_name, e->name);
541
542 va_start (va, fmt);
543 new_name = va_format (0, fmt, &va);
544 va_end (va);
545
546 vec_add1 (new_name, 0);
547 vlib_stats_set_entry_name (e, (char *) new_name);
548 hash_set_str_key_alloc (&sm->directory_vector_by_name, e->name, entry_index);
549 vec_free (new_name);
550}
551
552f64
553vlib_stats_get_segment_update_rate (void)
554{
555 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
556 return sm->update_interval;
557}
558
559void
560vlib_stats_register_collector_fn (vlib_stats_collector_reg_t *reg)
561{
562 vlib_stats_segment_t *sm = vlib_stats_get_segment ();
563 vlib_stats_collector_t *c;
564
565 ASSERT (reg->entry_index != ~0);
566
567 pool_get_zero (sm->collectors, c);
568 c->fn = reg->collect_fn;
569 c->entry_index = reg->entry_index;
570 c->vector_index = reg->vector_index;
571 c->private_data = reg->private_data;
572
573 return;
574}