LCOV - code coverage report
Current view: top level - vlib/stats - stats.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 263 313 84.0 %
Date: 2023-07-05 22:20:52 Functions: 22 26 84.6 %

          Line data    Source code
       1             : /* 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             : 
       8             : vlib_stats_main_t vlib_stats_main;
       9             : 
      10             : void
      11      666868 : vlib_stats_segment_lock (void)
      12             : {
      13      666868 :   vlib_main_t *vm = vlib_get_main ();
      14      666868 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
      15             : 
      16             :   /* already locked by us */
      17      666868 :   if (sm->shared_header->in_progress &&
      18       88841 :       vm->thread_index == sm->locking_thread_index)
      19       88841 :     goto done;
      20             : 
      21      578027 :   ASSERT (sm->locking_thread_index == ~0);
      22      578027 :   ASSERT (sm->shared_header->in_progress == 0);
      23      578027 :   ASSERT (sm->n_locks == 0);
      24             : 
      25      578027 :   clib_spinlock_lock (sm->stat_segment_lockp);
      26             : 
      27      578027 :   sm->shared_header->in_progress = 1;
      28      578027 :   sm->locking_thread_index = vm->thread_index;
      29      666868 : done:
      30      666868 :   sm->n_locks++;
      31      666868 : }
      32             : 
      33             : void
      34      666868 : vlib_stats_segment_unlock (void)
      35             : {
      36      666868 :   vlib_main_t *vm = vlib_get_main ();
      37      666868 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
      38             : 
      39      666868 :   ASSERT (sm->shared_header->in_progress == 1);
      40      666868 :   ASSERT (sm->locking_thread_index == vm->thread_index);
      41      666868 :   ASSERT (sm->n_locks > 0);
      42             : 
      43      666868 :   sm->n_locks--;
      44             : 
      45      666868 :   if (sm->n_locks > 0)
      46       88841 :     return;
      47             : 
      48      578027 :   sm->shared_header->epoch++;
      49      578027 :   __atomic_store_n (&sm->shared_header->in_progress, 0, __ATOMIC_RELEASE);
      50      578027 :   sm->locking_thread_index = ~0;
      51      578027 :   clib_spinlock_unlock (sm->stat_segment_lockp);
      52             : }
      53             : 
      54             : /*
      55             :  * Change heap to the stats shared memory segment
      56             :  */
      57             : void *
      58      100488 : vlib_stats_set_heap ()
      59             : {
      60      100488 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
      61             : 
      62      100488 :   ASSERT (sm && sm->shared_header);
      63      100488 :   return clib_mem_set_heap (sm->heap);
      64             : }
      65             : 
      66             : u32
      67     2414080 : vlib_stats_find_entry_index (char *fmt, ...)
      68             : {
      69             :   u8 *name;
      70             :   va_list va;
      71             : 
      72     2414080 :   va_start (va, fmt);
      73     2414080 :   name = va_format (0, fmt, &va);
      74     2414080 :   va_end (va);
      75     2414080 :   vec_add1 (name, 0);
      76             : 
      77     2414080 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
      78     2414080 :   hash_pair_t *hp = hash_get_pair (sm->directory_vector_by_name, name);
      79     2414080 :   vec_free (name);
      80     2414080 :   return hp ? hp->value[0] : STAT_SEGMENT_INDEX_INVALID;
      81             : }
      82             : 
      83             : static void
      84     2404580 : hash_set_str_key_alloc (uword **h, const char *key, uword v)
      85             : {
      86     2404580 :   int size = strlen (key) + 1;
      87     2404580 :   void *copy = clib_mem_alloc (size);
      88     2404580 :   clib_memcpy_fast (copy, key, size);
      89     4809160 :   hash_set_mem (*h, copy, v);
      90     2404580 : }
      91             : 
      92             : static void
      93       74634 : hash_unset_str_key_free (uword **h, const char *key)
      94             : {
      95       74634 :   hash_pair_t *hp = hash_get_pair_mem (*h, key);
      96       74634 :   if (hp)
      97             :     {
      98       74634 :       void *_k = uword_to_pointer (hp->key, void *);
      99       74634 :       hash_unset_mem (*h, _k);
     100       74634 :       clib_mem_free (_k);
     101             :     }
     102       74634 : }
     103             : 
     104             : u32
     105     2404580 : vlib_stats_create_counter (vlib_stats_entry_t *e)
     106             : {
     107     2404580 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     108             :   u32 index;
     109             : 
     110     2404580 :   if (sm->dir_vector_first_free_elt != CLIB_U32_MAX)
     111             :     {
     112       63119 :       index = sm->dir_vector_first_free_elt;
     113       63119 :       sm->dir_vector_first_free_elt = sm->directory_vector[index].index;
     114             :     }
     115             :   else
     116             :     {
     117     2341460 :       index = vec_len (sm->directory_vector);
     118     2341460 :       vec_validate (sm->directory_vector, index);
     119             :     }
     120             : 
     121     2404580 :   sm->directory_vector[index] = *e;
     122             : 
     123     2404580 :   hash_set_str_key_alloc (&sm->directory_vector_by_name, e->name, index);
     124             : 
     125     2404580 :   return index;
     126             : }
     127             : 
     128             : void
     129       74634 : vlib_stats_remove_entry (u32 entry_index)
     130             : {
     131       74634 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     132       74634 :   vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
     133             :   counter_t **c;
     134             :   vlib_counter_t **vc;
     135             :   void *oldheap;
     136             :   u32 i;
     137             : 
     138       74634 :   if (entry_index >= vec_len (sm->directory_vector))
     139           0 :     return;
     140             : 
     141       74634 :   vlib_stats_segment_lock ();
     142             : 
     143       74634 :   switch (e->type)
     144             :     {
     145           0 :     case STAT_DIR_TYPE_NAME_VECTOR:
     146           0 :       for (i = 0; i < vec_len (e->string_vector); i++)
     147           0 :         vec_free (e->string_vector[i]);
     148           0 :       vec_free (e->string_vector);
     149           0 :       break;
     150             : 
     151           1 :     case STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE:
     152           1 :       c = e->data;
     153           1 :       e->data = 0;
     154           1 :       oldheap = clib_mem_set_heap (sm->heap);
     155           2 :       for (i = 0; i < vec_len (c); i++)
     156           1 :         vec_free (c[i]);
     157           1 :       vec_free (c);
     158           1 :       clib_mem_set_heap (oldheap);
     159           1 :       break;
     160             : 
     161           1 :     case STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED:
     162           1 :       vc = e->data;
     163           1 :       e->data = 0;
     164           1 :       oldheap = clib_mem_set_heap (sm->heap);
     165           2 :       for (i = 0; i < vec_len (vc); i++)
     166           1 :         vec_free (vc[i]);
     167           1 :       vec_free (vc);
     168           1 :       clib_mem_set_heap (oldheap);
     169           1 :       break;
     170             : 
     171       74632 :     case STAT_DIR_TYPE_SCALAR_INDEX:
     172             :     case STAT_DIR_TYPE_SYMLINK:
     173       74632 :       break;
     174           0 :     default:
     175           0 :       ASSERT (0);
     176             :     }
     177             : 
     178       74634 :   vlib_stats_segment_unlock ();
     179             : 
     180       74634 :   hash_unset_str_key_free (&sm->directory_vector_by_name, e->name);
     181             : 
     182       74634 :   memset (e, 0, sizeof (*e));
     183       74634 :   e->type = STAT_DIR_TYPE_EMPTY;
     184             : 
     185       74634 :   e->value = sm->dir_vector_first_free_elt;
     186       74634 :   sm->dir_vector_first_free_elt = entry_index;
     187             : }
     188             : 
     189             : static void
     190     2404580 : vlib_stats_set_entry_name (vlib_stats_entry_t *e, char *s)
     191             : {
     192     2404580 :   u32 i, len = VLIB_STATS_MAX_NAME_SZ - 1;
     193             : 
     194    94421800 :   for (i = 0; i < len; i++)
     195             :     {
     196    94421800 :       e->name[i] = s[i];
     197    94421800 :       if (s[i] == 0)
     198     2404580 :         return;
     199             :     }
     200           0 :   ASSERT (i < VLIB_STATS_MAX_NAME_SZ - 1);
     201           0 :   s[i] = 0;
     202             : }
     203             : 
     204             : static u32
     205       69124 : vlib_stats_new_entry_internal (stat_directory_type_t t, u8 *name)
     206             : {
     207       69124 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     208       69124 :   vlib_stats_shared_header_t *shared_header = sm->shared_header;
     209       69124 :   vlib_stats_entry_t e = { .type = t };
     210             : 
     211       69124 :   ASSERT (shared_header);
     212             : 
     213       69124 :   u32 vector_index = vlib_stats_find_entry_index ("%v", name);
     214       69124 :   if (vector_index != STAT_SEGMENT_INDEX_INVALID) /* Already registered */
     215             :     {
     216           0 :       vector_index = ~0;
     217           0 :       goto done;
     218             :     }
     219             : 
     220       69124 :   vec_add1 (name, 0);
     221       69124 :   vlib_stats_set_entry_name (&e, (char *) name);
     222             : 
     223       69124 :   vlib_stats_segment_lock ();
     224       69124 :   vector_index = vlib_stats_create_counter (&e);
     225             : 
     226       69124 :   shared_header->directory_vector = sm->directory_vector;
     227             : 
     228       69124 :   vlib_stats_segment_unlock ();
     229             : 
     230       69124 : done:
     231       69124 :   vec_free (name);
     232       69124 :   return vector_index;
     233             : }
     234             : 
     235             : u32
     236        5102 : vlib_stats_add_gauge (char *fmt, ...)
     237             : {
     238             :   va_list va;
     239             :   u8 *name;
     240             : 
     241        5102 :   va_start (va, fmt);
     242        5102 :   name = va_format (0, fmt, &va);
     243        5102 :   va_end (va);
     244        5102 :   return vlib_stats_new_entry_internal (STAT_DIR_TYPE_SCALAR_INDEX, name);
     245             : }
     246             : 
     247             : void
     248        3254 : vlib_stats_set_gauge (u32 index, u64 value)
     249             : {
     250        3254 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     251             : 
     252        3254 :   ASSERT (index < vec_len (sm->directory_vector));
     253        3254 :   sm->directory_vector[index].value = value;
     254        3254 : }
     255             : 
     256             : u32
     257         559 : vlib_stats_add_timestamp (char *fmt, ...)
     258             : {
     259             :   va_list va;
     260             :   u8 *name;
     261             : 
     262         559 :   va_start (va, fmt);
     263         559 :   name = va_format (0, fmt, &va);
     264         559 :   va_end (va);
     265         559 :   return vlib_stats_new_entry_internal (STAT_DIR_TYPE_SCALAR_INDEX, name);
     266             : }
     267             : 
     268             : void
     269           0 : vlib_stats_set_timestamp (u32 entry_index, f64 value)
     270             : {
     271           0 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     272             : 
     273           0 :   ASSERT (entry_index < vec_len (sm->directory_vector));
     274           0 :   sm->directory_vector[entry_index].value = value;
     275           0 : }
     276             : 
     277             : vlib_stats_string_vector_t
     278         560 : vlib_stats_add_string_vector (char *fmt, ...)
     279             : {
     280         560 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     281             :   va_list va;
     282             :   vlib_stats_header_t *sh;
     283             :   vlib_stats_string_vector_t sv;
     284             :   u32 index;
     285             :   u8 *name;
     286             : 
     287         560 :   va_start (va, fmt);
     288         560 :   name = va_format (0, fmt, &va);
     289         560 :   va_end (va);
     290             : 
     291         560 :   index = vlib_stats_new_entry_internal (STAT_DIR_TYPE_NAME_VECTOR, name);
     292         560 :   if (index == CLIB_U32_MAX)
     293           0 :     return 0;
     294             : 
     295         560 :   sv = vec_new_generic (vlib_stats_string_vector_t, 0,
     296             :                         sizeof (vlib_stats_header_t), 0, sm->heap);
     297         560 :   sh = vec_header (sv);
     298         560 :   sh->entry_index = index;
     299         560 :   sm->directory_vector[index].string_vector = sv;
     300         560 :   return sv;
     301             : }
     302             : 
     303             : void
     304        8174 : vlib_stats_set_string_vector (vlib_stats_string_vector_t *svp,
     305             :                               u32 vector_index, char *fmt, ...)
     306             : {
     307        8174 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     308        8174 :   vlib_stats_header_t *sh = vec_header (*svp);
     309        8174 :   vlib_stats_entry_t *e = vlib_stats_get_entry (sm, sh->entry_index);
     310             :   va_list va;
     311             :   u8 *s;
     312             : 
     313        8174 :   if (fmt[0] == 0)
     314             :     {
     315           0 :       if (vec_len (e->string_vector) <= vector_index)
     316           0 :         return;
     317             : 
     318           0 :       if (e->string_vector[vector_index] == 0)
     319           0 :         return;
     320             : 
     321           0 :       vlib_stats_segment_lock ();
     322           0 :       vec_free (e->string_vector[vector_index]);
     323           0 :       vlib_stats_segment_unlock ();
     324           0 :       return;
     325             :     }
     326             : 
     327        8174 :   vlib_stats_segment_lock ();
     328             : 
     329        8174 :   ASSERT (e->string_vector);
     330             : 
     331        8174 :   vec_validate (e->string_vector, vector_index);
     332        8174 :   svp[0] = e->string_vector;
     333             : 
     334        8174 :   s = e->string_vector[vector_index];
     335             : 
     336        8174 :   if (s == 0)
     337        4629 :     s = vec_new_heap (u8 *, 0, sm->heap);
     338             : 
     339        8174 :   vec_reset_length (s);
     340             : 
     341        8174 :   va_start (va, fmt);
     342        8174 :   s = va_format (s, fmt, &va);
     343        8174 :   va_end (va);
     344        8174 :   vec_add1 (s, 0);
     345             : 
     346        8174 :   e->string_vector[vector_index] = s;
     347             : 
     348        8174 :   vlib_stats_segment_unlock ();
     349             : }
     350             : 
     351             : void
     352           0 : vlib_stats_free_string_vector (vlib_stats_string_vector_t *sv)
     353             : {
     354           0 :   vlib_stats_header_t *sh = vec_header (*sv);
     355           0 :   vlib_stats_remove_entry (sh->entry_index);
     356           0 : }
     357             : 
     358             : u32
     359       55182 : vlib_stats_add_counter_vector (char *fmt, ...)
     360             : {
     361             :   va_list va;
     362             :   u8 *name;
     363             : 
     364       55182 :   va_start (va, fmt);
     365       55182 :   name = va_format (0, fmt, &va);
     366       55182 :   va_end (va);
     367       55182 :   return vlib_stats_new_entry_internal (STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE,
     368             :                                         name);
     369             : }
     370             : 
     371             : u32
     372        7721 : vlib_stats_add_counter_pair_vector (char *fmt, ...)
     373             : {
     374             :   va_list va;
     375             :   u8 *name;
     376             : 
     377        7721 :   va_start (va, fmt);
     378        7721 :   name = va_format (0, fmt, &va);
     379        7721 :   va_end (va);
     380        7721 :   return vlib_stats_new_entry_internal (STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED,
     381             :                                         name);
     382             : }
     383             : 
     384             : static int
     385      819035 : vlib_stats_validate_will_expand_internal (u32 entry_index, va_list *va)
     386             : {
     387      819035 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     388      819035 :   vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
     389             :   void *oldheap;
     390      819035 :   int rv = 1;
     391             : 
     392      819035 :   oldheap = clib_mem_set_heap (sm->heap);
     393      819035 :   if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE)
     394             :     {
     395      597570 :       u32 idx0 = va_arg (*va, u32);
     396      597570 :       u32 idx1 = va_arg (*va, u32);
     397      597570 :       u64 **data = e->data;
     398             : 
     399      597570 :       if (idx0 >= vec_len (data))
     400       55236 :         goto done;
     401             : 
     402     1085080 :       for (u32 i = 0; i <= idx0; i++)
     403      561909 :         if (idx1 >= vec_max_len (data[i]))
     404       19163 :           goto done;
     405             :     }
     406      221465 :   else if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED)
     407             :     {
     408      221465 :       u32 idx0 = va_arg (*va, u32);
     409      221465 :       u32 idx1 = va_arg (*va, u32);
     410      221465 :       vlib_counter_t **data = e->data;
     411             : 
     412      221465 :       va_end (*va);
     413             : 
     414      221465 :       if (idx0 >= vec_len (data))
     415        7721 :         goto done;
     416             : 
     417      420275 :       for (u32 i = 0; i <= idx0; i++)
     418      222943 :         if (idx1 >= vec_max_len (data[i]))
     419       16412 :           goto done;
     420             :     }
     421             :   else
     422           0 :     ASSERT (0);
     423             : 
     424      720503 :   rv = 0;
     425      819035 : done:
     426      819035 :   clib_mem_set_heap (oldheap);
     427      819035 :   return rv;
     428             : }
     429             : 
     430             : int
     431           0 : vlib_stats_validate_will_expand (u32 entry_index, ...)
     432             : {
     433             :   va_list va;
     434             :   int rv;
     435             : 
     436           0 :   va_start (va, entry_index);
     437           0 :   rv = vlib_stats_validate_will_expand_internal (entry_index, &va);
     438           0 :   va_end (va);
     439           0 :   return rv;
     440             : }
     441             : 
     442             : void
     443      819035 : vlib_stats_validate (u32 entry_index, ...)
     444             : {
     445      819035 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     446      819035 :   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      819035 :   va_start (va, entry_index);
     452      819035 :   will_expand = vlib_stats_validate_will_expand_internal (entry_index, &va);
     453      819035 :   va_end (va);
     454             : 
     455      819035 :   if (will_expand)
     456       98532 :     vlib_stats_segment_lock ();
     457             : 
     458      819035 :   oldheap = clib_mem_set_heap (sm->heap);
     459             : 
     460      819035 :   va_start (va, entry_index);
     461             : 
     462      819035 :   if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE)
     463             :     {
     464      597570 :       u32 idx0 = va_arg (va, u32);
     465      597570 :       u32 idx1 = va_arg (va, u32);
     466      597570 :       u64 **data = e->data;
     467             : 
     468      597570 :       vec_validate_aligned (data, idx0, CLIB_CACHE_LINE_BYTES);
     469             : 
     470     1220800 :       for (u32 i = 0; i <= idx0; i++)
     471      623233 :         vec_validate_aligned (data[i], idx1, CLIB_CACHE_LINE_BYTES);
     472      597570 :       e->data = data;
     473             :     }
     474      221465 :   else if (e->type == STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED)
     475             :     {
     476      221465 :       u32 idx0 = va_arg (va, u32);
     477      221465 :       u32 idx1 = va_arg (va, u32);
     478      221465 :       vlib_counter_t **data = e->data;
     479             : 
     480      221465 :       vec_validate_aligned (data, idx0, CLIB_CACHE_LINE_BYTES);
     481             : 
     482      454541 :       for (u32 i = 0; i <= idx0; i++)
     483      233076 :         vec_validate_aligned (data[i], idx1, CLIB_CACHE_LINE_BYTES);
     484      221465 :       e->data = data;
     485             :     }
     486             :   else
     487           0 :     ASSERT (0);
     488             : 
     489      819035 :   va_end (va);
     490             : 
     491      819035 :   clib_mem_set_heap (oldheap);
     492             : 
     493      819035 :   if (will_expand)
     494       98532 :     vlib_stats_segment_unlock ();
     495      819035 : }
     496             : 
     497             : u32
     498     2335460 : vlib_stats_add_symlink (u32 entry_index, u32 vector_index, char *fmt, ...)
     499             : {
     500     2335460 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     501     2335460 :   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     2335460 :   ASSERT (shared_header);
     507     2335460 :   ASSERT (entry_index < vec_len (sm->directory_vector));
     508             : 
     509     2335460 :   va_start (va, fmt);
     510     2335460 :   name = va_format (0, fmt, &va);
     511     2335460 :   va_end (va);
     512             : 
     513     2335460 :   if (vlib_stats_find_entry_index ("%v", name) == STAT_SEGMENT_INDEX_INVALID)
     514             :     {
     515     2335460 :       vec_add1 (name, 0);
     516     2335460 :       vlib_stats_set_entry_name (&e, (char *) name);
     517     2335460 :       e.type = STAT_DIR_TYPE_SYMLINK;
     518     2335460 :       e.index1 = entry_index;
     519     2335460 :       e.index2 = vector_index;
     520     2335460 :       vector_index = vlib_stats_create_counter (&e);
     521             : 
     522             :       /* Warn clients to refresh any pointers they might be holding */
     523     2335460 :       shared_header->directory_vector = sm->directory_vector;
     524             :     }
     525             :   else
     526           0 :     vector_index = ~0;
     527             : 
     528     2335460 :   vec_free (name);
     529     2335460 :   return vector_index;
     530             : }
     531             : 
     532             : void
     533           0 : vlib_stats_rename_symlink (u64 entry_index, char *fmt, ...)
     534             : {
     535           0 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     536           0 :   vlib_stats_entry_t *e = vlib_stats_get_entry (sm, entry_index);
     537             :   va_list va;
     538             :   u8 *new_name;
     539             : 
     540           0 :   hash_unset_str_key_free (&sm->directory_vector_by_name, e->name);
     541             : 
     542           0 :   va_start (va, fmt);
     543           0 :   new_name = va_format (0, fmt, &va);
     544           0 :   va_end (va);
     545             : 
     546           0 :   vec_add1 (new_name, 0);
     547           0 :   vlib_stats_set_entry_name (e, (char *) new_name);
     548           0 :   hash_set_str_key_alloc (&sm->directory_vector_by_name, e->name, entry_index);
     549           0 :   vec_free (new_name);
     550           0 : }
     551             : 
     552             : f64
     553        1958 : vlib_stats_get_segment_update_rate (void)
     554             : {
     555        1958 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     556        1958 :   return sm->update_interval;
     557             : }
     558             : 
     559             : void
     560        4011 : vlib_stats_register_collector_fn (vlib_stats_collector_reg_t *reg)
     561             : {
     562        4011 :   vlib_stats_segment_t *sm = vlib_stats_get_segment ();
     563             :   vlib_stats_collector_t *c;
     564             : 
     565        4011 :   ASSERT (reg->entry_index != ~0);
     566             : 
     567        4011 :   pool_get_zero (sm->collectors, c);
     568        4011 :   c->fn = reg->collect_fn;
     569        4011 :   c->entry_index = reg->entry_index;
     570        4011 :   c->vector_index = reg->vector_index;
     571        4011 :   c->private_data = reg->private_data;
     572             : 
     573        4011 :   return;
     574             : }

Generated by: LCOV version 1.14