API support for src/dst based routing policy in LISP
[vpp.git] / vppinfra / vppinfra / mem.h
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 #ifndef _included_clib_mem_h
39 #define _included_clib_mem_h
40
41 #include <stdarg.h>
42
43 #include <vppinfra/clib.h>          /* uword, etc */
44 #include <vppinfra/mheap_bootstrap.h>
45 #include <vppinfra/os.h>
46 #include <vppinfra/string.h>        /* memcpy, memset */
47 #include <vppinfra/valgrind.h>
48
49 #define CLIB_MAX_MHEAPS 256
50
51 /* Per CPU heaps. */
52 extern void * clib_per_cpu_mheaps[CLIB_MAX_MHEAPS];
53
54 always_inline void * clib_mem_get_per_cpu_heap (void)
55 {
56   int cpu = os_get_cpu_number ();
57   return clib_per_cpu_mheaps[cpu];
58 }
59
60 always_inline void * clib_mem_set_per_cpu_heap (u8 * new_heap)
61 {
62   int cpu = os_get_cpu_number ();
63   void * old = clib_per_cpu_mheaps[cpu];
64   clib_per_cpu_mheaps[cpu] = new_heap;
65   return old;
66 }
67
68 /* Memory allocator which returns null when it fails. */
69 always_inline void *
70 clib_mem_alloc_aligned_at_offset (uword size,
71                                   uword align,
72                                   uword align_offset)
73 {
74   void * heap, * p;
75   uword offset, cpu;
76
77   if (align_offset > align)
78     {
79       if (align > 0)
80         align_offset %= align;
81       else
82         align_offset = align;
83     }
84
85   cpu = os_get_cpu_number ();
86   heap = clib_per_cpu_mheaps[cpu];
87   heap = mheap_get_aligned (heap,
88                             size, align, align_offset,
89                             &offset);
90   clib_per_cpu_mheaps[cpu] = heap;
91
92   if (offset != ~0)
93     {
94       p = heap + offset;
95 #if CLIB_DEBUG > 0
96       VALGRIND_MALLOCLIKE_BLOCK (p, mheap_data_bytes (heap, offset), 0, 0);
97 #endif
98       return p;
99     }
100   else
101     {
102       os_out_of_memory ();
103       return 0;
104     }
105 }
106
107 /* Memory allocator which returns null when it fails. */
108 always_inline void *
109 clib_mem_alloc (uword size)
110 { return clib_mem_alloc_aligned_at_offset (size, /* align */ 1, /* align_offset */ 0); }
111
112 always_inline void *
113 clib_mem_alloc_aligned (uword size, uword align)
114 { return clib_mem_alloc_aligned_at_offset (size, align, /* align_offset */ 0); }
115
116 /* Memory allocator which panics when it fails.
117    Use macro so that clib_panic macro can expand __FUNCTION__ and __LINE__. */
118 #define clib_mem_alloc_aligned_no_fail(size,align)                              \
119 ({                                                                              \
120   uword _clib_mem_alloc_size = (size);                                          \
121   void * _clib_mem_alloc_p;                                                     \
122   _clib_mem_alloc_p = clib_mem_alloc_aligned (_clib_mem_alloc_size, (align));   \
123   if (! _clib_mem_alloc_p)                                                      \
124     clib_panic ("failed to allocate %d bytes", _clib_mem_alloc_size);           \
125   _clib_mem_alloc_p;                                                            \
126 })
127
128 #define clib_mem_alloc_no_fail(size) clib_mem_alloc_aligned_no_fail(size,1)
129
130 /* Alias to stack allocator for naming consistency. */
131 #define clib_mem_alloc_stack(bytes) __builtin_alloca(bytes)
132
133 always_inline uword clib_mem_is_heap_object (void * p)
134 {
135   void * heap = clib_mem_get_per_cpu_heap ();
136   uword offset = (uword)p - (uword)heap;
137   mheap_elt_t * e, * n;
138
139   if (offset >= vec_len (heap))
140     return 0;
141
142   e = mheap_elt_at_uoffset (heap, offset);
143   n = mheap_next_elt (e);
144   
145   /* Check that heap forward and reverse pointers agree. */
146   return e->n_user_data == n->prev_n_user_data;
147 }
148
149 always_inline void clib_mem_free (void * p)
150 {
151   u8 * heap = clib_mem_get_per_cpu_heap ();
152
153   /* Make sure object is in the correct heap. */
154   ASSERT (clib_mem_is_heap_object (p));
155
156   mheap_put (heap, (u8 *) p - heap);
157
158 #if CLIB_DEBUG > 0
159   VALGRIND_FREELIKE_BLOCK (p, 0);
160 #endif
161 }
162
163 always_inline void * clib_mem_realloc (void * p, uword new_size, uword old_size)
164 {
165   /* By default use alloc, copy and free to emulate realloc. */
166   void * q = clib_mem_alloc (new_size);
167   if (q)
168     {
169       uword copy_size;
170       if (old_size < new_size)
171         copy_size = old_size;
172       else
173         copy_size = new_size;
174       clib_memcpy (q, p, copy_size);
175       clib_mem_free (p);
176     }
177   return q;
178 }
179
180 always_inline uword clib_mem_size (void * p)
181 {
182   ASSERT (clib_mem_is_heap_object (p));
183   mheap_elt_t * e = mheap_user_pointer_to_elt (p);
184   return mheap_elt_data_bytes (e);
185 }
186
187 always_inline void * clib_mem_get_heap (void)
188 { return clib_mem_get_per_cpu_heap (); }
189
190 always_inline void * clib_mem_set_heap (void * heap)
191 { return clib_mem_set_per_cpu_heap (heap); }
192
193 void * clib_mem_init (void * heap, uword size);
194
195 void clib_mem_exit (void);
196
197 uword clib_mem_get_page_size (void);
198
199 void clib_mem_validate (void);
200
201 void clib_mem_trace (int enable);
202
203 typedef struct {
204   /* Total number of objects allocated. */
205   uword object_count;
206
207   /* Total allocated bytes.  Bytes used and free.
208      used + free = total */
209   uword bytes_total, bytes_used, bytes_free;
210
211   /* Number of bytes used by mheap data structure overhead
212      (e.g. free lists, mheap header). */
213   uword bytes_overhead;
214
215   /* Amount of free space returned to operating system. */
216   uword bytes_free_reclaimed;
217   
218   /* For malloc which puts small objects in sbrk region and
219      large objects in mmap'ed regions. */
220   uword bytes_used_sbrk;
221   uword bytes_used_mmap;
222
223   /* Max. number of bytes in this heap. */
224   uword bytes_max;
225 } clib_mem_usage_t;
226
227 void clib_mem_usage (clib_mem_usage_t * usage);
228
229 u8 * format_clib_mem_usage (u8 * s, va_list * args);
230
231 /* Include appropriate VM functions depending on whether
232    we are compiling for linux kernel, for Unix or standalone. */
233 #ifdef CLIB_LINUX_KERNEL
234 #include <vppinfra/vm_linux_kernel.h>
235 #endif
236
237 #ifdef CLIB_UNIX
238 #include <vppinfra/vm_unix.h>
239 #endif
240
241 #ifdef CLIB_STANDALONE
242 #include <vppinfra/vm_standalone.h>
243 #endif
244
245 #include <vppinfra/error.h>             /* clib_panic */
246
247 #endif /* _included_clib_mem_h */