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