LCOV - code coverage report
Current view: top level - vnet/util - refcount.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 19 19 100.0 %
Date: 2023-10-26 01:39:38 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : /*
      17             :  * vlib provides lock-free counters but those
      18             :  * - Have 16bits per-CPU counter, which may overflow.
      19             :  * - Would only increment.
      20             :  *
      21             :  * This is very similar to vlib counters, but may be used to count reference.
      22             :  * Such a counter includes an arbitrary number of counters. Each counter
      23             :  * is identified by its index. This is used to aggregate per-cpu memory.
      24             :  *
      25             :  * Warning:
      26             :  *   This reference counter is lock-free but is not race-condition free.
      27             :  *   The counting result is approximate and another mechanism needs to be used
      28             :  *   in order to ensure that an object may be freed.
      29             :  *
      30             :  */
      31             : 
      32             : #include <vnet/vnet.h>
      33             : #include <vppinfra/lock.h>
      34             : 
      35             : /*
      36             :  * Reference counting
      37             :  * A specific reference counter is used. The design is quite
      38             :  * similar to vlib counters but:
      39             :  *   - It is possible to decrease the value
      40             :  *   - Summing will not zero the per-thread counters
      41             :  *   - Only the thread can reallocate its own counters vector (to avoid concurrency issues)
      42             : */
      43             : typedef struct {
      44             :   u32 *counters;
      45             :   clib_spinlock_t counter_lock;
      46             :   CLIB_CACHE_LINE_ALIGN_MARK(o);
      47             : } vlib_refcount_per_cpu_t;
      48             : 
      49             : typedef struct {
      50             :   vlib_refcount_per_cpu_t *per_cpu;
      51             : } vlib_refcount_t;
      52             : 
      53             : static_always_inline
      54         528 : void vlib_refcount_lock (clib_spinlock_t counter_lock)
      55             : {
      56         528 :   clib_spinlock_lock (&counter_lock);
      57         528 : }
      58             : 
      59             : static_always_inline
      60         528 : void vlib_refcount_unlock (clib_spinlock_t counter_lock)
      61             : {
      62         528 :   clib_spinlock_unlock (&counter_lock);
      63         528 : }
      64             : 
      65             : void __vlib_refcount_resize(vlib_refcount_per_cpu_t *per_cpu, u32 size);
      66             : 
      67             : static_always_inline
      68      117288 : void vlib_refcount_add(vlib_refcount_t *r, u32 thread_index, u32 counter_index, i32 v)
      69             : {
      70      117288 :   vlib_refcount_per_cpu_t *per_cpu = &r->per_cpu[thread_index];
      71      117288 :   if (PREDICT_FALSE(counter_index >= vec_len(per_cpu->counters)))
      72           3 :     __vlib_refcount_resize(per_cpu, clib_max(counter_index + 16,(vec_len(per_cpu->counters)) * 2));
      73             : 
      74      117288 :   per_cpu->counters[counter_index] += v;
      75      117288 : }
      76             : 
      77             : u64 vlib_refcount_get(vlib_refcount_t *r, u32 index);
      78             : 
      79             : static_always_inline
      80         575 : void vlib_refcount_init(vlib_refcount_t *r)
      81             : {
      82         575 :   vlib_thread_main_t *tm = vlib_get_thread_main ();
      83             :   u32 thread_index;
      84         575 :   r->per_cpu = 0;
      85         575 :   vec_validate (r->per_cpu, tm->n_vlib_mains - 1);
      86             : 
      87        1205 :   for (thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++)
      88             :     {
      89         630 :       clib_spinlock_init (&r->per_cpu[thread_index].counter_lock);
      90             :     }
      91         575 : }
      92             : 
      93             : 

Generated by: LCOV version 1.14