FD.io VPP  v16.06
Vector Packet Processing
heap.h
Go to the documentation of this file.
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  /* Offset of this element (plus free bit).
73  If element is free, data at offset contains pointer to free list. */
75 
76  /* Index of next and previous elements relative to current element. */
77  i32 next, prev;
78 } heap_elt_t;
79 
80 /* Use high bit of offset as free bit. */
81 #define HEAP_ELT_FREE_BIT (1 << 31)
82 
84 { return (e->offset & HEAP_ELT_FREE_BIT) != 0; }
85 
87 { return e->offset &~ HEAP_ELT_FREE_BIT; }
88 
90 { return e + e->next; }
91 
93 { return e + e->prev; }
94 
96 {
97  heap_elt_t * n = heap_next (e);
98  uword next_offset = n != e ? heap_offset (n) : vec_len (v);
99  return next_offset - heap_offset (e);
100 }
101 
102 /* Sizes are binned. Sizes 1 to 2^log2_small_bins have their
103  own free lists. Larger sizes are grouped in powers of two. */
104 #define HEAP_LOG2_SMALL_BINS (5)
105 #define HEAP_SMALL_BINS (1 << HEAP_LOG2_SMALL_BINS)
106 #define HEAP_N_BINS (2 * HEAP_SMALL_BINS)
107 
108 /* Header for heaps. */
109 typedef struct {
110  /* Vector of used and free elements. */
112 
113  /* For elt_bytes < sizeof (u32) we need some extra space
114  per elt to store free list index. */
116 
117  /* Vector of free indices of elts array. */
119 
120  /* Indices of free elts indexed by size bin. */
122 
124 
125  /* Used for validattion/debugging. */
127 
128  /* First and last element of doubly linked chain of elements. */
129  u32 head, tail;
130 
131  u32 used_count, max_len;
132 
133  /* Number of bytes in a help element. */
135 
137  /* Static heaps are made from external memory given to
138  us by user and are not re-sizeable vectors. */
139 #define HEAP_IS_STATIC (1)
140 } heap_header_t;
141 
142 /* Start of heap elements is always cache aligned. */
143 #define HEAP_DATA_ALIGN (CLIB_CACHE_LINE_BYTES)
144 
146 { return vec_header (v, sizeof (heap_header_t)); }
147 
149 { return vec_header_bytes (sizeof (heap_header_t)); }
150 
152 {
153  uword i;
154 
155  new[0] = old[0];
156  new->elts = vec_dup (new->elts);
157  new->free_elts = vec_dup (new->free_elts);
158  new->free_lists = vec_dup (new->free_lists);
159  for (i = 0; i < vec_len (new->free_lists); i++)
160  new->free_lists[i] = vec_dup (new->free_lists[i]);
161  new->used_elt_bitmap = clib_bitmap_dup (new->used_elt_bitmap);
162  new->small_free_elt_free_index = vec_dup (new->small_free_elt_free_index);
163 }
164 
165 /* Make a duplicate copy of a heap. */
166 #define heap_dup(v) _heap_dup(v, vec_len (v) * sizeof (v[0]))
167 
168 always_inline void * _heap_dup (void * v_old, uword v_bytes)
169 {
170  heap_header_t * h_old, * h_new;
171  void * v_new;
172 
173  h_old = heap_header (v_old);
174 
175  if (! v_old)
176  return v_old;
177 
178  v_new = 0;
179  v_new = _vec_resize (v_new, _vec_len (v_old), v_bytes, sizeof (heap_header_t),
181  h_new = heap_header (v_new);
182  heap_dup_header (h_old, h_new);
183  clib_memcpy (v_new, v_old, v_bytes);
184  return v_new;
185 }
186 
188 {
189  heap_header_t * h = heap_header (v);
190  return h->used_count;
191 }
192 
193 uword heap_bytes (void * v);
194 
195 always_inline void * _heap_new (u32 len, u32 n_elt_bytes)
196 {
197  void * v = _vec_resize (0, len, len*n_elt_bytes,
198  sizeof (heap_header_t),
200  heap_header (v)->elt_bytes = n_elt_bytes;
201  return v;
202 }
203 
204 #define heap_new(v) (v) = _heap_new (0, sizeof ((v)[0]))
205 
206 always_inline void
207 heap_set_format (void * v, format_function_t * format_elt)
208 {
209  ASSERT (v);
210  heap_header (v)->format_elt = format_elt;
211 }
212 
213 always_inline void
214 heap_set_max_len (void * v, uword max_len)
215 {
216  ASSERT (v);
217  heap_header (v)->max_len = max_len;
218 }
219 
221 { return v ? heap_header (v)->max_len : 0; }
222 
223 /* Create fixed size heap with given block of memory. */
224 always_inline void *
225 heap_create_from_memory (void * memory, uword max_len, uword elt_bytes)
226 {
227  heap_header_t * h;
228  void * v;
229 
230  if (max_len * elt_bytes < sizeof (h[0]))
231  return 0;
232 
233  h = memory;
234  memset (h, 0, sizeof (h[0]));
235  h->max_len = max_len;
236  h->elt_bytes = elt_bytes;
237  h->flags = HEAP_IS_STATIC;
238 
239  v = (void *) (memory + heap_header_bytes ());
240  _vec_len (v) = 0;
241  return v;
242 }
243 
244 /* Execute BODY for each allocated heap element. */
245 #define heap_foreach(var,len,heap,body) \
246 do { \
247  if (vec_len (heap) > 0) \
248  { \
249  heap_header_t * _h = heap_header (heap); \
250  heap_elt_t * _e = _h->elts + _h->head; \
251  heap_elt_t * _end = _h->elts + _h->tail; \
252  while (1) \
253  { \
254  if (! heap_is_free (_e)) \
255  { \
256  (var) = (heap) + heap_offset (_e); \
257  (len) = heap_elt_size ((heap), _e); \
258  do { body; } while (0); \
259  } \
260  if (_e == _end) \
261  break; \
262  _e = heap_next (_e); \
263  } \
264  } \
265 } while (0)
266 
267 #define heap_elt_at_index(v,index) vec_elt_at_index(v,index)
268 
270 heap_get_elt (void * v, uword handle)
271 {
272  heap_header_t * h = heap_header (v);
273  heap_elt_t * e = vec_elt_at_index (h->elts, handle);
274  ASSERT (! heap_is_free (e));
275  return e;
276 }
277 
278 #define heap_elt_with_handle(v,handle) \
279 ({ \
280  heap_elt_t * _e = heap_get_elt ((v), (handle)); \
281  (v) + heap_offset (_e); \
282 })
283 
285 heap_is_free_handle (void * v, uword heap_handle)
286 {
287  heap_header_t * h = heap_header (v);
288  heap_elt_t * e = vec_elt_at_index (h->elts, heap_handle);
289  return heap_is_free (e);
290 }
291 
292 extern uword heap_len (void * v, word handle);
293 
294 /* Low level allocation call. */
295 extern void * _heap_alloc (void * v, uword size, uword alignment,
296  uword elt_bytes,
297  uword * offset, uword * handle);
298 
299 #define heap_alloc_aligned(v,size,align,handle) \
300 ({ \
301  uword _o, _h; \
302  uword _a = (align); \
303  uword _s = (size); \
304  (v) = _heap_alloc ((v), _s, _a, sizeof ((v)[0]), &_o, &_h); \
305  (handle) = _h; \
306  _o; \
307 })
308 
309 #define heap_alloc(v,size,handle) heap_alloc_aligned((v),(size),0,(handle))
310 
311 extern void heap_dealloc (void * v, uword handle);
312 extern void heap_validate (void * v);
313 
314 /* Format heap internal data structures as string. */
315 extern u8 * format_heap (u8 * s, va_list * va);
316 
317 void * _heap_free (void * v);
318 
319 #define heap_free(v) (v)=_heap_free(v)
320 
321 #endif /* included_heap_h */
always_inline void heap_set_max_len(void *v, uword max_len)
Definition: heap.h:214
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
i32 next
Definition: heap.h:77
always_inline uword heap_elts(void *v)
Definition: heap.h:187
always_inline heap_elt_t * heap_get_elt(void *v, uword handle)
Definition: heap.h:270
always_inline void heap_set_format(void *v, format_function_t *format_elt)
Definition: heap.h:207
u32 tail
Definition: heap.h:129
u32 offset
Definition: heap.h:74
always_inline uword heap_get_max_len(void *v)
Definition: heap.h:220
always_inline void heap_dup_header(heap_header_t *old, heap_header_t *new)
Definition: heap.h:151
always_inline heap_elt_t * heap_next(heap_elt_t *e)
Definition: heap.h:89
#define clib_bitmap_dup(v)
Definition: bitmap.h:73
vhost_user_memory_t memory
Definition: vhost-user.h:79
format_function_t * format_elt
Definition: heap.h:123
always_inline uword heap_is_free(heap_elt_t *e)
Definition: heap.h:83
u32 * free_elts
Definition: heap.h:118
always_inline heap_header_t * heap_header(void *v)
Definition: heap.h:145
uword heap_bytes(void *v)
Definition: heap.c:605
#define always_inline
Definition: clib.h:84
int i32
Definition: types.h:81
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
always_inline uword heap_offset(heap_elt_t *e)
Definition: heap.h:86
uword * used_elt_bitmap
Definition: heap.h:126
u8 * format_heap(u8 *s, va_list *va)
Definition: heap.c:669
#define HEAP_DATA_ALIGN
Definition: heap.h:143
#define HEAP_IS_STATIC
Definition: heap.h:139
i32 prev
Definition: heap.h:77
void heap_validate(void *v)
Definition: heap.c:695
heap_elt_t * elts
Definition: heap.h:111
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:332
u32 max_len
Definition: heap.h:131
uword heap_len(void *v, word handle)
Definition: heap.c:576
u32 elt_bytes
Definition: heap.h:134
u32 used_count
Definition: heap.h:131
always_inline uword heap_header_bytes()
Definition: heap.h:148
#define clib_memcpy(a, b, c)
Definition: string.h:63
u32 * small_free_elt_free_index
Definition: heap.h:115
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
always_inline heap_elt_t * heap_prev(heap_elt_t *e)
Definition: heap.h:92
u32 size
Definition: vhost-user.h:74
u8 *( format_function_t)(u8 *s, va_list *args)
Definition: format.h:48
u32 flags
Definition: heap.h:136
u64 uword
Definition: types.h:112
i64 word
Definition: types.h:111
#define HEAP_ELT_FREE_BIT
Definition: heap.h:81
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
always_inline uword heap_elt_size(void *v, heap_elt_t *e)
Definition: heap.h:95
always_inline void * vec_header(void *v, uword header_bytes)
Find a user vector header.
Definition: vec_bootstrap.h:88
always_inline void * heap_create_from_memory(void *memory, uword max_len, uword elt_bytes)
Definition: heap.h:225
always_inline uword heap_is_free_handle(void *v, uword heap_handle)
Definition: heap.h:285
void heap_dealloc(void *v, uword handle)
Definition: heap.c:478
always_inline uword vec_header_bytes(uword header_bytes)
Definition: vec_bootstrap.h:78
u32 ** free_lists
Definition: heap.h:121