LCOV - code coverage report
Current view: top level - vppinfra - heap.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 16 21 76.2 %
Date: 2023-07-05 22:20:52 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 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             :   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
      17             : 
      18             :   Permission is hereby granted, free of charge, to any person obtaining
      19             :   a copy of this software and associated documentation files (the
      20             :   "Software"), to deal in the Software without restriction, including
      21             :   without limitation the rights to use, copy, modify, merge, publish,
      22             :   distribute, sublicense, and/or sell copies of the Software, and to
      23             :   permit persons to whom the Software is furnished to do so, subject to
      24             :   the following conditions:
      25             : 
      26             :   The above copyright notice and this permission notice shall be
      27             :   included in all copies or substantial portions of the Software.
      28             : 
      29             :   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      30             :   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      31             :   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      32             :   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      33             :   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      34             :   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      35             :   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      36             : */
      37             : 
      38             : /* Heaps of objects of type T (e.g. int, struct foo, ...).
      39             : 
      40             :    Usage.  To declare a null heap:
      41             : 
      42             :      T * heap = 0;
      43             : 
      44             :    To allocate:
      45             : 
      46             :      offset = heap_alloc (heap, size, handle);
      47             : 
      48             :    New object is heap[offset] ... heap[offset + size]
      49             :    Handle is used to free/query object.
      50             : 
      51             :    To free object:
      52             : 
      53             :      heap_dealloc (heap, handle);
      54             : 
      55             :    To query the size of an object:
      56             : 
      57             :      heap_size (heap, handle)
      58             : 
      59             : */
      60             : 
      61             : #ifndef included_heap_h
      62             : #define included_heap_h
      63             : 
      64             : #include <vppinfra/clib.h>
      65             : #include <vppinfra/cache.h>
      66             : #include <vppinfra/hash.h>
      67             : #include <vppinfra/format.h>
      68             : #include <vppinfra/bitmap.h>
      69             : 
      70             : /* Doubly linked list of elements. */
      71             : typedef struct
      72             : {
      73             :   /* Offset of this element (plus free bit).
      74             :      If element is free, data at offset contains pointer to free list. */
      75             :   u32 offset;
      76             : 
      77             :   /* Index of next and previous elements relative to current element. */
      78             :   i32 next, prev;
      79             : } heap_elt_t;
      80             : 
      81             : /* Use high bit of offset as free bit. */
      82             : #define HEAP_ELT_FREE_BIT       (1 << 31)
      83             : 
      84             : always_inline uword
      85      176572 : heap_is_free (heap_elt_t * e)
      86             : {
      87      176572 :   return (e->offset & HEAP_ELT_FREE_BIT) != 0;
      88             : }
      89             : 
      90             : always_inline uword
      91      284886 : heap_offset (heap_elt_t * e)
      92             : {
      93      284886 :   return e->offset & ~HEAP_ELT_FREE_BIT;
      94             : }
      95             : 
      96             : always_inline heap_elt_t *
      97      472738 : heap_next (heap_elt_t * e)
      98             : {
      99      472738 :   return e + e->next;
     100             : }
     101             : 
     102             : always_inline heap_elt_t *
     103       61067 : heap_prev (heap_elt_t * e)
     104             : {
     105       61067 :   return e + e->prev;
     106             : }
     107             : 
     108             : always_inline uword
     109      118597 : heap_elt_size (void *v, heap_elt_t * e)
     110             : {
     111      118597 :   heap_elt_t *n = heap_next (e);
     112      118597 :   uword next_offset = n != e ? heap_offset (n) : vec_len (v);
     113      118597 :   return next_offset - heap_offset (e);
     114             : }
     115             : 
     116             : /* Sizes are binned.  Sizes 1 to 2^log2_small_bins have their
     117             :    own free lists.  Larger sizes are grouped in powers of two. */
     118             : #define HEAP_LOG2_SMALL_BINS    (5)
     119             : #define HEAP_SMALL_BINS         (1 << HEAP_LOG2_SMALL_BINS)
     120             : #define HEAP_N_BINS             (2 * HEAP_SMALL_BINS)
     121             : 
     122             : /* Header for heaps. */
     123             : typedef struct
     124             : {
     125             :   /* Vector of used and free elements. */
     126             :   heap_elt_t *elts;
     127             : 
     128             :   /* For elt_bytes < sizeof (u32) we need some extra space
     129             :      per elt to store free list index. */
     130             :   u32 *small_free_elt_free_index;
     131             : 
     132             :   /* Vector of free indices of elts array. */
     133             :   u32 *free_elts;
     134             : 
     135             :   /* Indices of free elts indexed by size bin. */
     136             :   u32 **free_lists;
     137             : 
     138             :   format_function_t *format_elt;
     139             : 
     140             :   /* Used for validation/debugging. */
     141             :   uword *used_elt_bitmap;
     142             : 
     143             :   /* First and last element of doubly linked chain of elements. */
     144             :   u32 head, tail;
     145             : 
     146             :   u32 used_count, max_len;
     147             : 
     148             :   /* Number of bytes in a help element. */
     149             :   u32 elt_bytes;
     150             : 
     151             :   u32 flags;
     152             :   /* Static heaps are made from external memory given to
     153             :      us by user and are not re-sizable vectors. */
     154             : #define HEAP_IS_STATIC (1)
     155             : } heap_header_t;
     156             : 
     157             : /* Start of heap elements is always cache aligned. */
     158             : #define HEAP_DATA_ALIGN (CLIB_CACHE_LINE_BYTES)
     159             : 
     160             : always_inline heap_header_t *
     161     1523530 : heap_header (void *v)
     162             : {
     163     1523530 :   return vec_header (v);
     164             : }
     165             : 
     166             : always_inline void
     167             : heap_dup_header (heap_header_t * old, heap_header_t * new)
     168             : {
     169             :   uword i;
     170             : 
     171             :   new[0] = old[0];
     172             :   new->elts = vec_dup (new->elts);
     173             :   new->free_elts = vec_dup (new->free_elts);
     174             :   new->free_lists = vec_dup (new->free_lists);
     175             :   for (i = 0; i < vec_len (new->free_lists); i++)
     176             :     new->free_lists[i] = vec_dup (new->free_lists[i]);
     177             :   new->used_elt_bitmap = clib_bitmap_dup (new->used_elt_bitmap);
     178             :   new->small_free_elt_free_index = vec_dup (new->small_free_elt_free_index);
     179             : }
     180             : 
     181             : /* Make a duplicate copy of a heap. */
     182             : #define heap_dup(v) _heap_dup(v, vec_len (v) * sizeof (v[0]))
     183             : 
     184             : always_inline void *
     185             : _heap_dup (void *v_old, uword v_bytes)
     186             : {
     187             :   heap_header_t *h_old, *h_new;
     188             :   vec_attr_t va = { .align = HEAP_DATA_ALIGN,
     189             :                     .hdr_sz = sizeof (heap_header_t),
     190             :                     .elt_sz = 1 };
     191             :   void *v_new;
     192             : 
     193             :   h_old = heap_header (v_old);
     194             : 
     195             :   if (!v_old)
     196             :     return v_old;
     197             : 
     198             :   v_new = _vec_alloc_internal (_vec_len (v_old), &va);
     199             :   h_new = heap_header (v_new);
     200             :   heap_dup_header (h_old, h_new);
     201             :   clib_memcpy_fast (v_new, v_old, v_bytes);
     202             :   return v_new;
     203             : }
     204             : 
     205             : always_inline uword
     206             : heap_elts (void *v)
     207             : {
     208             :   heap_header_t *h = heap_header (v);
     209             :   return h->used_count;
     210             : }
     211             : 
     212             : uword heap_bytes (void *v);
     213             : 
     214             : always_inline void *
     215           0 : _heap_new (u32 len, u32 n_elt_bytes)
     216             : {
     217           0 :   vec_attr_t va = { .align = HEAP_DATA_ALIGN,
     218             :                     .hdr_sz = sizeof (heap_header_t),
     219             :                     .elt_sz = n_elt_bytes };
     220           0 :   void *v = _vec_alloc_internal (len, &va);
     221           0 :   heap_header (v)->elt_bytes = n_elt_bytes;
     222           0 :   return v;
     223             : }
     224             : 
     225             : #define heap_new(v) (v) = _heap_new (0, sizeof ((v)[0]))
     226             : 
     227             : always_inline void
     228             : heap_set_format (void *v, format_function_t * format_elt)
     229             : {
     230             :   ASSERT (v);
     231             :   heap_header (v)->format_elt = format_elt;
     232             : }
     233             : 
     234             : always_inline void
     235             : heap_set_max_len (void *v, uword max_len)
     236             : {
     237             :   ASSERT (v);
     238             :   heap_header (v)->max_len = max_len;
     239             : }
     240             : 
     241             : always_inline uword
     242      285376 : heap_get_max_len (void *v)
     243             : {
     244      285376 :   return v ? heap_header (v)->max_len : 0;
     245             : }
     246             : 
     247             : /* Execute BODY for each allocated heap element. */
     248             : #define heap_foreach(var,len,heap,body)                 \
     249             : do {                                                    \
     250             :   if (vec_len (heap) > 0)                            \
     251             :     {                                                   \
     252             :       heap_header_t * _h = heap_header (heap);          \
     253             :       heap_elt_t * _e   = _h->elts + _h->head;            \
     254             :       heap_elt_t * _end = _h->elts + _h->tail;            \
     255             :       while (1)                                         \
     256             :         {                                               \
     257             :           if (! heap_is_free (_e))                      \
     258             :             {                                           \
     259             :               (var) = (heap) + heap_offset (_e);        \
     260             :               (len) = heap_elt_size ((heap), _e);       \
     261             :               do { body; } while (0);                   \
     262             :             }                                           \
     263             :           if (_e == _end)                               \
     264             :             break;                                      \
     265             :           _e = heap_next (_e);                          \
     266             :         }                                               \
     267             :     }                                                   \
     268             : } while (0)
     269             : 
     270             : #define heap_elt_at_index(v,index) vec_elt_at_index(v,index)
     271             : 
     272             : always_inline heap_elt_t *
     273             : heap_get_elt (void *v, uword handle)
     274             : {
     275             :   heap_header_t *h = heap_header (v);
     276             :   heap_elt_t *e = vec_elt_at_index (h->elts, handle);
     277             :   ASSERT (!heap_is_free (e));
     278             :   return e;
     279             : }
     280             : 
     281             : #define heap_elt_with_handle(v,handle)                  \
     282             : ({                                                      \
     283             :   heap_elt_t * _e = heap_get_elt ((v), (handle));       \
     284             :   (v) + heap_offset (_e);                               \
     285             : })
     286             : 
     287             : always_inline uword
     288             : heap_is_free_handle (void *v, uword heap_handle)
     289             : {
     290             :   heap_header_t *h = heap_header (v);
     291             :   heap_elt_t *e = vec_elt_at_index (h->elts, heap_handle);
     292             :   return heap_is_free (e);
     293             : }
     294             : 
     295             : extern uword heap_len (void *v, word handle);
     296             : 
     297             : /* Low level allocation call. */
     298             : extern void *_heap_alloc (void *v, uword size, uword alignment,
     299             :                           uword elt_bytes, uword * offset, uword * handle);
     300             : 
     301             : #define heap_alloc_aligned(v,size,align,handle)                 \
     302             : ({                                                              \
     303             :   uword _o, _h;                                                 \
     304             :   uword _a = (align);                                           \
     305             :   uword _s = (size);                                            \
     306             :   (v) = _heap_alloc ((v), _s, _a, sizeof ((v)[0]), &_o, &_h);   \
     307             :   (handle) = _h;                                                \
     308             :   _o;                                                           \
     309             : })
     310             : 
     311             : #define heap_alloc(v,size,handle) heap_alloc_aligned((v),(size),0,(handle))
     312             : 
     313             : extern void heap_dealloc (void *v, uword handle);
     314             : extern void heap_validate (void *v);
     315             : 
     316             : /* Format heap internal data structures as string. */
     317             : extern u8 *format_heap (u8 * s, va_list * va);
     318             : 
     319             : void *_heap_free (void *v);
     320             : 
     321             : #define heap_free(v) (v)=_heap_free(v)
     322             : 
     323             : #endif /* included_heap_h */
     324             : 
     325             : /*
     326             :  * fd.io coding-style-patch-verification: ON
     327             :  *
     328             :  * Local Variables:
     329             :  * eval: (c-set-style "gnu")
     330             :  * End:
     331             :  */

Generated by: LCOV version 1.14