blob: 63c5ac16a026dbf222be303c4d3887341a22fc6f [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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
Dave Barachc3799992016-08-15 11:12:27 -040043#include <vppinfra/clib.h> /* uword, etc */
Ed Warnickecb9cada2015-12-08 15:45:58 -070044#include <vppinfra/mheap_bootstrap.h>
45#include <vppinfra/os.h>
Dave Barachc3799992016-08-15 11:12:27 -040046#include <vppinfra/string.h> /* memcpy, memset */
Ed Warnickecb9cada2015-12-08 15:45:58 -070047#include <vppinfra/valgrind.h>
48
Damjan Marionce8debf2016-02-06 19:16:21 +010049#define CLIB_MAX_MHEAPS 256
50
Ed Warnickecb9cada2015-12-08 15:45:58 -070051/* Per CPU heaps. */
Dave Barachc3799992016-08-15 11:12:27 -040052extern void *clib_per_cpu_mheaps[CLIB_MAX_MHEAPS];
Ed Warnickecb9cada2015-12-08 15:45:58 -070053
Dave Barachc3799992016-08-15 11:12:27 -040054always_inline void *
55clib_mem_get_per_cpu_heap (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -070056{
Damjan Marionf55f9b82017-05-10 21:06:28 +020057 int cpu = os_get_thread_index ();
Ed Warnickecb9cada2015-12-08 15:45:58 -070058 return clib_per_cpu_mheaps[cpu];
59}
60
Dave Barachc3799992016-08-15 11:12:27 -040061always_inline void *
62clib_mem_set_per_cpu_heap (u8 * new_heap)
Ed Warnickecb9cada2015-12-08 15:45:58 -070063{
Damjan Marionf55f9b82017-05-10 21:06:28 +020064 int cpu = os_get_thread_index ();
Dave Barachc3799992016-08-15 11:12:27 -040065 void *old = clib_per_cpu_mheaps[cpu];
Ed Warnickecb9cada2015-12-08 15:45:58 -070066 clib_per_cpu_mheaps[cpu] = new_heap;
67 return old;
68}
69
Dave Barach241e5222016-10-13 10:53:26 -040070/* Memory allocator which may call os_out_of_memory() if it fails */
Ed Warnickecb9cada2015-12-08 15:45:58 -070071always_inline void *
Dave Barach241e5222016-10-13 10:53:26 -040072clib_mem_alloc_aligned_at_offset (uword size, uword align, uword align_offset,
73 int os_out_of_memory_on_failure)
Ed Warnickecb9cada2015-12-08 15:45:58 -070074{
Dave Barachc3799992016-08-15 11:12:27 -040075 void *heap, *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -070076 uword offset, cpu;
77
78 if (align_offset > align)
79 {
80 if (align > 0)
81 align_offset %= align;
82 else
83 align_offset = align;
84 }
85
Damjan Marionf55f9b82017-05-10 21:06:28 +020086 cpu = os_get_thread_index ();
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 heap = clib_per_cpu_mheaps[cpu];
Dave Barachc3799992016-08-15 11:12:27 -040088 heap = mheap_get_aligned (heap, size, align, align_offset, &offset);
Ed Warnickecb9cada2015-12-08 15:45:58 -070089 clib_per_cpu_mheaps[cpu] = heap;
90
91 if (offset != ~0)
92 {
93 p = heap + offset;
94#if CLIB_DEBUG > 0
95 VALGRIND_MALLOCLIKE_BLOCK (p, mheap_data_bytes (heap, offset), 0, 0);
96#endif
97 return p;
98 }
99 else
100 {
Dave Barach241e5222016-10-13 10:53:26 -0400101 if (os_out_of_memory_on_failure)
102 os_out_of_memory ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103 return 0;
104 }
105}
106
Dave Barach241e5222016-10-13 10:53:26 -0400107/* Memory allocator which calls os_out_of_memory() when it fails */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700108always_inline void *
109clib_mem_alloc (uword size)
Dave Barachc3799992016-08-15 11:12:27 -0400110{
111 return clib_mem_alloc_aligned_at_offset (size, /* align */ 1,
Dave Barach241e5222016-10-13 10:53:26 -0400112 /* align_offset */ 0,
113 /* os_out_of_memory */ 1);
Dave Barachc3799992016-08-15 11:12:27 -0400114}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700115
116always_inline void *
117clib_mem_alloc_aligned (uword size, uword align)
Dave Barachc3799992016-08-15 11:12:27 -0400118{
Dave Barach241e5222016-10-13 10:53:26 -0400119 return clib_mem_alloc_aligned_at_offset (size, align, /* align_offset */ 0,
120 /* os_out_of_memory */ 1);
Dave Barachc3799992016-08-15 11:12:27 -0400121}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122
Dave Barach241e5222016-10-13 10:53:26 -0400123/* Memory allocator which calls os_out_of_memory() when it fails */
124always_inline void *
125clib_mem_alloc_or_null (uword size)
126{
127 return clib_mem_alloc_aligned_at_offset (size, /* align */ 1,
128 /* align_offset */ 0,
129 /* os_out_of_memory */ 0);
130}
131
132always_inline void *
133clib_mem_alloc_aligned_or_null (uword size, uword align)
134{
135 return clib_mem_alloc_aligned_at_offset (size, align, /* align_offset */ 0,
136 /* os_out_of_memory */ 0);
137}
138
139
140
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141/* Memory allocator which panics when it fails.
142 Use macro so that clib_panic macro can expand __FUNCTION__ and __LINE__. */
143#define clib_mem_alloc_aligned_no_fail(size,align) \
144({ \
145 uword _clib_mem_alloc_size = (size); \
146 void * _clib_mem_alloc_p; \
147 _clib_mem_alloc_p = clib_mem_alloc_aligned (_clib_mem_alloc_size, (align)); \
148 if (! _clib_mem_alloc_p) \
149 clib_panic ("failed to allocate %d bytes", _clib_mem_alloc_size); \
150 _clib_mem_alloc_p; \
151})
152
153#define clib_mem_alloc_no_fail(size) clib_mem_alloc_aligned_no_fail(size,1)
154
155/* Alias to stack allocator for naming consistency. */
156#define clib_mem_alloc_stack(bytes) __builtin_alloca(bytes)
157
Dave Barachc3799992016-08-15 11:12:27 -0400158always_inline uword
159clib_mem_is_heap_object (void *p)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700160{
Dave Barachc3799992016-08-15 11:12:27 -0400161 void *heap = clib_mem_get_per_cpu_heap ();
162 uword offset = (uword) p - (uword) heap;
163 mheap_elt_t *e, *n;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164
165 if (offset >= vec_len (heap))
166 return 0;
167
168 e = mheap_elt_at_uoffset (heap, offset);
169 n = mheap_next_elt (e);
Dave Barachc3799992016-08-15 11:12:27 -0400170
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171 /* Check that heap forward and reverse pointers agree. */
172 return e->n_user_data == n->prev_n_user_data;
173}
174
Dave Barachc3799992016-08-15 11:12:27 -0400175always_inline void
176clib_mem_free (void *p)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177{
Dave Barachc3799992016-08-15 11:12:27 -0400178 u8 *heap = clib_mem_get_per_cpu_heap ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700179
180 /* Make sure object is in the correct heap. */
181 ASSERT (clib_mem_is_heap_object (p));
182
183 mheap_put (heap, (u8 *) p - heap);
184
185#if CLIB_DEBUG > 0
186 VALGRIND_FREELIKE_BLOCK (p, 0);
187#endif
188}
189
Dave Barachc3799992016-08-15 11:12:27 -0400190always_inline void *
191clib_mem_realloc (void *p, uword new_size, uword old_size)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192{
193 /* By default use alloc, copy and free to emulate realloc. */
Dave Barachc3799992016-08-15 11:12:27 -0400194 void *q = clib_mem_alloc (new_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700195 if (q)
196 {
197 uword copy_size;
198 if (old_size < new_size)
199 copy_size = old_size;
200 else
201 copy_size = new_size;
Damjan Marionf1213b82016-03-13 02:22:06 +0100202 clib_memcpy (q, p, copy_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700203 clib_mem_free (p);
204 }
205 return q;
206}
207
Dave Barachc3799992016-08-15 11:12:27 -0400208always_inline uword
209clib_mem_size (void *p)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210{
211 ASSERT (clib_mem_is_heap_object (p));
Dave Barachc3799992016-08-15 11:12:27 -0400212 mheap_elt_t *e = mheap_user_pointer_to_elt (p);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213 return mheap_elt_data_bytes (e);
214}
215
Dave Barachc3799992016-08-15 11:12:27 -0400216always_inline void *
217clib_mem_get_heap (void)
218{
219 return clib_mem_get_per_cpu_heap ();
220}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700221
Dave Barachc3799992016-08-15 11:12:27 -0400222always_inline void *
223clib_mem_set_heap (void *heap)
224{
225 return clib_mem_set_per_cpu_heap (heap);
226}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700227
Dave Barachc3799992016-08-15 11:12:27 -0400228void *clib_mem_init (void *heap, uword size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229
230void clib_mem_exit (void);
231
232uword clib_mem_get_page_size (void);
233
234void clib_mem_validate (void);
235
236void clib_mem_trace (int enable);
237
Dave Barachc3799992016-08-15 11:12:27 -0400238typedef struct
239{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240 /* Total number of objects allocated. */
241 uword object_count;
242
243 /* Total allocated bytes. Bytes used and free.
244 used + free = total */
245 uword bytes_total, bytes_used, bytes_free;
246
247 /* Number of bytes used by mheap data structure overhead
248 (e.g. free lists, mheap header). */
249 uword bytes_overhead;
250
251 /* Amount of free space returned to operating system. */
252 uword bytes_free_reclaimed;
Dave Barachc3799992016-08-15 11:12:27 -0400253
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254 /* For malloc which puts small objects in sbrk region and
255 large objects in mmap'ed regions. */
256 uword bytes_used_sbrk;
257 uword bytes_used_mmap;
258
259 /* Max. number of bytes in this heap. */
260 uword bytes_max;
261} clib_mem_usage_t;
262
263void clib_mem_usage (clib_mem_usage_t * usage);
264
Dave Barachc3799992016-08-15 11:12:27 -0400265u8 *format_clib_mem_usage (u8 * s, va_list * args);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700266
267/* Include appropriate VM functions depending on whether
268 we are compiling for linux kernel, for Unix or standalone. */
269#ifdef CLIB_LINUX_KERNEL
270#include <vppinfra/vm_linux_kernel.h>
271#endif
272
273#ifdef CLIB_UNIX
274#include <vppinfra/vm_unix.h>
275#endif
276
277#ifdef CLIB_STANDALONE
278#include <vppinfra/vm_standalone.h>
279#endif
280
Dave Barachc3799992016-08-15 11:12:27 -0400281#include <vppinfra/error.h> /* clib_panic */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282
283#endif /* _included_clib_mem_h */
Dave Barachc3799992016-08-15 11:12:27 -0400284
285/*
286 * fd.io coding-style-patch-verification: ON
287 *
288 * Local Variables:
289 * eval: (c-set-style "gnu")
290 * End:
291 */