65 while (__sync_lock_test_and_set (&h->
lock, 1))
92 uword n_user_data_words;
93 word small_bin, large_bin;
102 ASSERT (n_user_data_words > 0);
128 uword n_user_data_bytes,
180 nf->
free_elt.prev_uoffset = uoffset;
222 #define MHEAP_VM_MAP (1 << 0) 223 #define MHEAP_VM_UNMAP (1 << 1) 224 #define MHEAP_VM_NOMAP (0 << 1) 225 #define MHEAP_VM_ROUND (1 << 2) 226 #define MHEAP_VM_ROUND_UP MHEAP_VM_ROUND 227 #define MHEAP_VM_ROUND_DOWN (0 << 2) 232 {
return (addr + mheap_page_size - 1) &~ (mheap_page_size - 1); }
235 {
return addr &~ (mheap_page_size - 1); }
249 end_addr = start_addr +
size;
260 if (end_page > start_page)
262 mapped_bytes = end_page - start_page;
281 return mheap_vm (v, flags, start_addr, end_addr - start_addr);
290 #if !defined (CLIB_HAVE_VEC128) || defined (__ALTIVEC__) 297 #define _(i) ((uword) u8x16_compare_byte_mask (u8x16_is_equal (b, c->bins.as_u8x16[i])) << (uword) ((i)*16)) 298 mask = _ (0) | _ (1);
300 mask |= _ (2) | _ (3);
360 uword * n_user_data_bytes_arg,
369 word o0, o1, f0, f1, search_n_user_data_bytes;
370 word lo_free_usize, hi_free_usize;
375 search_n_user_data_bytes = *n_user_data_bytes_arg;
378 o0 = o1 = f0 = f1 = 0;
389 ASSERT (this_object_n_user_data_bytes >= search_n_user_data_bytes);
393 if (this_object_n_user_data_bytes < search_n_user_data_bytes)
398 f1 = f0 + this_object_n_user_data_bytes;
401 o0 = ((f1 - search_n_user_data_bytes) &~ (align - 1)) - align_offset;
415 o1 = o0 + search_n_user_data_bytes;
418 if (o0 >= f0 && o1 <= f1)
438 search_n_user_data_bytes += f1 - o1;
451 uword f0_page_start, f0_page_end;
452 uword o0_page_start, o0_page_end;
461 if (o0_page_start < f0_page_start)
462 o0_page_start = f0_page_start;
463 if (o0_page_end > f0_page_end)
464 o0_page_end = f0_page_end;
466 if (o0_page_end > o0_page_start)
468 o0_page_end - o0_page_start);
475 if (lo_free_usize > 0)
477 ASSERT (lo_free_usize >= (
word) MHEAP_MIN_USER_DATA_BYTES);
484 if (hi_free_usize > 0)
492 *n_user_data_bytes_arg = search_n_user_data_bytes;
502 uword * n_user_bytes_arg,
507 uword bin, n_user_bytes,
i, bi;
509 n_user_bytes = *n_user_bytes_arg;
516 && align_offset == 0)
548 uword n_user_data_bytes,
551 uword * offset_return)
554 uword f0, f1, o0, o1;
559 if (_vec_len (v) == 0)
580 o1 = o0 + n_user_data_bytes;
603 if (f1_page > f0_page)
622 uword n_user_data_bytes,
625 uword * offset_return)
637 align_offset &= (align - 1);
666 if (offset == ~0 && _vec_len (v) < h->
max_size)
673 *offset_return = offset;
731 uword n_user_data_bytes, bin;
733 uword trace_uoffset, trace_n_user_data_bytes;
753 trace_uoffset = uoffset;
754 trace_n_user_data_bytes = n_user_data_bytes;
788 uword f0, f1, n_combine;
791 f1 = f0 + n_user_data_bytes;
848 if (! mheap_page_size)
877 size = memory + memory_size - v;
885 memset (h, 0,
sizeof (h[0]));
898 if (! (h->
flags & MHEAP_FLAG_DISABLE_VM))
915 #ifdef CLIB_HAVE_VEC128 922 void * _mheap_free (
void * v)
938 u8 * stack_heap, * clib_mem_mheap_save;
939 u8 tmp_heap_memory[16*1024];
946 clib_mem_mheap_save = 0;
955 stack_heap =
mheap_alloc (tmp_heap_memory,
sizeof (tmp_heap_memory));
956 clib_mem_mheap_save = v;
972 if (clib_mem_mheap_save)
994 uword used = 0, free = 0, free_vm_unmapped = 0;
1037 return format (s,
"%wd", n_bytes);
1039 return format (s,
"%wdk", n_bytes / 1024);
1076 s =
format (s,
"alloc. from small object cache: %Ld hits %Ld attempts (%.2f%%) replacements %d",
1084 s =
format (s,
"\n%Ualloc. from free-list: %Ld attempts, %Ld hits (%.2f%%), %Ld considered (per-attempt %.2f)",
1096 s =
format (s,
"\n%Ualloc. from vector-expand: %Ld",
1100 s =
format (s,
"\n%Uallocs: %Ld %.2f clocks/call",
1105 s =
format (s,
"\n%Ufrees: %Ld %.2f clocks/call",
1115 void * v = va_arg (*va,
u8 *);
1116 int verbose = va_arg (*va,
int);
1131 s =
format (s,
"%d objects, %U of %U used, %U free, %U reclaimed, %U overhead",
1149 memset (hist, 0,
sizeof (hist));
1165 s =
format (s,
"\n%U%=12s%=12s%=16s",
1167 "Size",
"Count",
"Fraction");
1173 s =
format (s,
"\n%U%12d%12wd%16.4f",
1177 (
f64) hist[i] / (
f64) n_hist);
1190 uword indent, total_objects_traced;
1193 qsort (traces_copy,
vec_len (traces_copy),
sizeof (traces_copy[0]),
1196 total_objects_traced = 0;
1206 if (! verbose && t->
n_bytes < 1024)
1209 if (t == traces_copy)
1210 s =
format (s,
"%=9s%=9s %=10s Traceback\n",
"Bytes",
"Count",
1227 s =
format (s,
"%d total traced objects\n", total_objects_traced);
1236 s =
format (s,
"\n first corrupt object: %p, size %wd\n %U",
1256 s =
format (s,
"%8d: ", i);
1261 s =
format (s,
"(%8d) ", o);
1263 s =
format (s,
" %8d ", o);
1265 if ((i % 8) == 7 || (i + 1) >= h->
n_elts)
1286 uword elt_count, elt_size;
1287 uword free_count_from_free_lists, free_size_from_free_lists;
1288 uword small_elt_free_count, small_elt_free_size;
1290 #define CHECK(x) if (! (x)) { mheap_validate_breakpoint (); os_panic (); } 1298 free_size_from_free_lists = free_count_from_free_lists = 0;
1331 free_count_from_free_lists += 1;
1332 free_size_from_free_lists += s;
1334 if (e->
free_elt.next_uoffset == ~0)
1347 small_elt_free_count = small_elt_free_size = 0;
1365 small_elt_free_count += 1;
1366 small_elt_free_size += s;
1372 uword elt_free_size, elt_free_count;
1374 elt_count = elt_size = elt_free_size = elt_free_count = 0;
1402 CHECK (free_count_from_free_lists == elt_free_count);
1403 CHECK (free_size_from_free_lists == elt_free_size);
1404 CHECK (elt_count == h->
n_elts + elt_free_count + small_elt_free_count);
1432 uword i, n_callers, trace_index, * p;
1436 memset(&trace, 0,
sizeof(trace));
1456 t = tm->
traces + trace_index;
1473 if (tm->
traces != old_start) {
1477 q = uword_to_pointer (p->key, mheap_trace_t *);
1478 ASSERT (q >= old_start && q < old_end);
1479 p->key = pointer_to_uword (tm->traces + (q - old_start));
1482 trace_index = t - tm->
traces;
1485 t = tm->
traces + trace_index;
1503 uword trace_index, * p;
1515 t = tm->
traces + trace_index;
1524 memset (t, 0,
sizeof (t[0]));
#define MHEAP_LOG2_N_SMALL_OBJECT_BINS
static_always_inline uword mheap_page_truncate(uword addr)
struct mheap_stats_t::@19 free_list
always_inline void * clib_mem_vm_map(void *addr, uword size)
struct mheap_elt_t::@16::@18 free_elt
always_inline uword max_pow2(uword x)
always_inline uword round_pow2(uword x, uword pow2)
#define hash_set(h, key, value)
sll srl srl sll sra u16x4 i
always_inline uword mheap_elts(void *v)
always_inline uword mheap_elt_uoffset(void *v, mheap_elt_t *e)
always_inline void * mheap_elt_data(void *v, mheap_elt_t *e)
always_inline mheap_elt_t * mheap_prev_elt(mheap_elt_t *e)
always_inline void mheap_elt_set_size(void *v, uword uoffset, uword n_user_data_bytes, uword is_free)
always_inline void mheap_maybe_unlock(void *v)
#define MHEAP_ELT_OVERHEAD_BYTES
#define hash_unset(h, key)
static_always_inline uword mheap_vm(void *v, uword flags, clib_address_t start_addr, uword size)
vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
static u8 * format_mheap_byte_count(u8 *s, va_list *va)
always_inline uword mheap_max_size(void *v)
uword offsets[BITS(uword)]
uword vm_alloc_offset_from_header
always_inline void set_first_free_elt_offset(mheap_t *h, uword bin, uword uoffset)
uword bytes_free_reclaimed
void * mheap_alloc(void *memory, uword size)
uword clib_backtrace(uword *callers, uword max_callers, uword n_frames_to_skip)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
always_inline void * clib_mem_vm_alloc(uword size)
u64 n_small_object_cache_hits
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
u64 n_small_object_cache_attempts
always_inline uword max_log2(uword x)
#define hash_set_mem(h, key, value)
#define STRUCT_OFFSET_OF(t, f)
#define MHEAP_N_SMALL_OBJECT_BINS
always_inline void mheap_trace_main_free(mheap_trace_main_t *tm)
static void mheap_put_trace(void *v, uword offset, uword size)
#define MHEAP_FLAG_THREAD_SAFE
#define vec_bytes(v)
Number of data bytes in vector.
u8 * format_mheap(u8 *s, va_list *va)
#define foreach_set_bit(var, mask, body)
always_inline u8x16 u8x16_splat(u8 a)
vhost_user_memory_t memory
mheap_trace_main_t trace_main
always_inline uword mheap_elt_size_to_user_n_words(uword n_bytes)
#define static_always_inline
#define MHEAP_FLAG_DISABLE_VM
void mheap_usage(void *v, clib_mem_usage_t *usage)
always_inline void remove_free_elt(void *v, mheap_elt_t *e, uword bin)
#define vec_end(v)
End (last data address) of vector.
always_inline mheap_t * mheap_header(u8 *v)
static uword pointer_to_uword(const void *p)
uword non_empty_free_elt_heads[(MHEAP_N_BINS+BITS(uword)-1)/BITS(uword)]
#define hash_create_mem(elts, key_bytes, value_bytes)
#define hash_unset_mem(h, key)
uword os_get_cpu_number(void)
#define vec_dup(V)
Return copy of vector (no header, no alignment)
always_inline uword mheap_put_small_object(mheap_t *h, uword bin, uword offset)
static uword mheap_page_size
static_always_inline uword mheap_vm_elt(void *v, uword flags, uword offset)
always_inline void * clib_mem_set_heap(void *heap)
always_inline void * clib_mem_get_heap(void)
#define MHEAP_N_USER_DATA_INVALID
#define uword_to_pointer(u, type)
always_inline uword mheap_elt_data_bytes(mheap_elt_t *e)
static void mheap_validate_breakpoint()
void * mheap_get_aligned(void *v, uword n_user_data_bytes, uword align, uword align_offset, uword *offset_return)
static void free_last_elt(void *v, mheap_elt_t *e)
#define vec_free(V)
Free vector's memory (no header).
always_inline void remove_free_elt2(void *v, mheap_elt_t *e)
static never_inline void * mheap_get_extend_vector(void *v, uword n_user_data_bytes, uword align, uword align_offset, uword *offset_return)
mheap_small_object_cache_t small_object_cache
always_inline mheap_elt_t * mheap_next_elt(mheap_elt_t *e)
void * mheap_alloc_with_flags(void *memory, uword memory_size, uword flags)
static uword mheap_get_search_free_list(void *v, uword *n_user_bytes_arg, uword align, uword align_offset)
void mheap_trace(void *v, int enable)
always_inline uword mheap_small_object_cache_mask(mheap_small_object_cache_t *c, uword bin)
always_inline mheap_elt_t * mheap_elt_at_uoffset(void *v, uword uo)
union mheap_small_object_cache_t::@20 bins
always_inline uword mheap_bytes_overhead(void *v)
#define MHEAP_FLAG_VALIDATE
always_inline u8 * mheap_vector(mheap_t *h)
always_inline u32 * elt_data(void *v, heap_elt_t *e)
static_always_inline uword mheap_page_round(uword addr)
always_inline void clib_mem_vm_free(void *addr, uword size)
static uword mheap_get_search_free_bin(void *v, uword bin, uword *n_user_data_bytes_arg, uword align, uword align_offset)
static mheap_elt_t * mheap_first_corrupt(void *v)
#define MHEAP_FLAG_SMALL_OBJECT_CACHE
uword mheap_bytes(void *v)
#define MHEAP_HAVE_SMALL_OBJECT_CACHE
always_inline uword mheap_elt_size_to_user_n_bytes(uword n_bytes)
void qsort(void *base, uword n, uword size, int(*compar)(const void *, const void *))
void mheap_put(void *v, uword uoffset)
static int mheap_trace_sort(const void *t1, const void *t2)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define hash_foreach_pair(p, v, body)
#define MHEAP_VM_ROUND_UP
static void mheap_get_trace(void *v, uword offset, uword size)
static u8 * format_mheap_stats(u8 *s, va_list *va)
format_function_t format_clib_elf_symbol_with_address
#define hash_get_mem(h, key)
always_inline void new_free_elt(void *v, uword uoffset, uword n_user_data_bytes)
#define STRUCT_SIZE_OF(t, f)
void mheap_validate(void *v)
#define vec_foreach(var, vec)
Vector iterator.
void mheap_foreach(void *v, uword(*func)(void *arg, void *v, void *elt_data, uword elt_size), void *arg)
always_inline uword min_log2(uword x)
always_inline uword user_data_size_to_bin_index(uword n_user_data_bytes)
#define CLIB_MEMORY_BARRIER()
#define MHEAP_USER_DATA_WORD_BYTES
always_inline void set_free_elt(void *v, uword uoffset, uword n_user_data_bytes)
always_inline uword pow2_mask(uword x)
always_inline uword mheap_get_small_object(mheap_t *h, uword bin)
always_inline u64 clib_cpu_time_now(void)
always_inline void * clib_mem_vm_unmap(void *addr, uword size)
always_inline void mheap_maybe_lock(void *v)
uword clib_mem_get_page_size(void)
uword * trace_index_by_offset
static void mheap_usage_no_lock(void *v, clib_mem_usage_t *usage)
#define MHEAP_MIN_USER_DATA_BYTES
u32 first_free_elt_uoffset_by_bin[MHEAP_N_BINS]