#include <vppinfra/lock.h>
#include <vppinfra/hash.h>
#include <vppinfra/elf_clib.h>
+#include <vppinfra/sanitizer.h>
+#include <numaif.h>
void *clib_per_cpu_mheaps[CLIB_MAX_MHEAPS];
+void *clib_per_numa_mheaps[CLIB_MAX_NUMAS];
typedef struct
{
uword callers[12];
/* Count of allocations with this traceback. */
-#if CLIB_VEC64 > 0
- u64 n_allocations;
-#else
u32 n_allocations;
-#endif
/* Count of bytes allocated with this traceback. */
u32 n_bytes;
/* Hash table mapping mheap offset to trace index. */
uword *trace_index_by_offset;
+
+ /* So we can easily shut off current segment trace, if any */
+ void *current_traced_mheap;
+
} mheap_trace_main_t;
mheap_trace_main_t mheap_trace_main;
mheap_trace_t trace;
uword save_enabled;
- if (tm->enabled == 0)
+ if (tm->enabled == 0 || (clib_mem_get_heap () != tm->current_traced_mheap))
return;
/* Spurious Coverity warnings be gone. */
- memset (&trace, 0, sizeof (trace));
+ clib_memset (&trace, 0, sizeof (trace));
/* Skip our frame and mspace_get_aligned's frame */
n_callers = clib_backtrace (trace.callers, ARRAY_LEN (trace.callers), 2);
if (n_callers == 0)
return;
- /* $$$ This looks like dreck to remove... */
- if (0)
- for (i = n_callers; i < ARRAY_LEN (trace.callers); i++)
- trace.callers[i] = 0;
-
clib_spinlock_lock (&tm->lock);
/* Turn off tracing to avoid embarrassment... */
{
hash_unset_mem (tm->trace_by_callers, t->callers);
vec_add1 (tm->trace_free_list, trace_index);
- memset (t, 0, sizeof (t[0]));
+ clib_memset (t, 0, sizeof (t[0]));
}
tm->enabled = save_enabled;
clib_spinlock_unlock (&tm->lock);
/* Initialize CLIB heap based on memory/size given by user.
Set memory to 0 and CLIB will try to allocate its own heap. */
-void *
-clib_mem_init (void *memory, uword memory_size)
+static void *
+clib_mem_init_internal (void *memory, uword memory_size, int set_heap)
{
u8 *heap;
else
heap = create_mspace (memory_size, 1 /* locked */ );
- clib_mem_set_heap (heap);
+ CLIB_MEM_POISON (mspace_least_addr (heap), mspace_footprint (heap));
+
+ if (set_heap)
+ clib_mem_set_heap (heap);
if (mheap_trace_main.lock == 0)
clib_spinlock_init (&mheap_trace_main.lock);
}
void *
-clib_mem_init_thread_safe (void *memory, uword memory_size)
+clib_mem_init (void *memory, uword memory_size)
{
- return clib_mem_init (memory, memory_size);
+ return clib_mem_init_internal (memory, memory_size,
+ 1 /* do clib_mem_set_heap */ );
}
-#ifdef CLIB_LINUX_KERNEL
-#include <asm/page.h>
-
-uword
-clib_mem_get_page_size (void)
+void *
+clib_mem_init_thread_safe (void *memory, uword memory_size)
{
- return PAGE_SIZE;
+ return clib_mem_init_internal (memory, memory_size,
+ 1 /* do clib_mem_set_heap */ );
}
-#endif
-#ifdef CLIB_UNIX
-uword
-clib_mem_get_page_size (void)
+void *
+clib_mem_init_thread_safe_numa (void *memory, uword memory_size, u8 numa)
{
- return getpagesize ();
-}
-#endif
+ clib_mem_vm_alloc_t alloc = { 0 };
+ clib_error_t *err;
+ void *heap;
+
+ alloc.size = memory_size;
+ alloc.flags = CLIB_MEM_VM_F_NUMA_FORCE;
+ alloc.numa_node = numa;
+ if ((err = clib_mem_vm_ext_alloc (&alloc)))
+ {
+ clib_error_report (err);
+ return 0;
+ }
-/* Make a guess for standalone. */
-#ifdef CLIB_STANDALONE
-uword
-clib_mem_get_page_size (void)
-{
- return 4096;
+ heap = clib_mem_init_internal (memory, memory_size,
+ 0 /* do NOT clib_mem_set_heap */ );
+
+ ASSERT (heap);
+
+ return heap;
}
-#endif
u8 *
format_clib_mem_usage (u8 * s, va_list * va)
int i;
clib_spinlock_lock (&tm->lock);
- if (vec_len (tm->traces) > 0)
+ if (vec_len (tm->traces) > 0 &&
+ clib_mem_get_heap () == tm->current_traced_mheap)
{
have_traces = 1;
format (s, "\n max total allocated %U", format_msize, mi.usmblks);
}
- s = format (s, "\n%U", format_mheap_trace, tm, verbose);
+ if (mspace_is_traced (heap))
+ s = format (s, "\n%U", format_mheap_trace, tm, verbose);
return s;
}
clib_warning ("unimp");
}
+void
+mheap_usage (void *heap, clib_mem_usage_t * usage)
+{
+ struct dlmallinfo mi = mspace_mallinfo (heap);
+
+ /* TODO: Fill in some more values */
+ usage->object_count = 0;
+ usage->bytes_total = mi.arena;
+ usage->bytes_overhead = 0;
+ usage->bytes_max = 0;
+ usage->bytes_used = mi.uordblks;
+ usage->bytes_free = mi.fordblks;
+ usage->bytes_free_reclaimed = 0;
+}
+
/* Call serial number for debugger breakpoints. */
uword clib_mem_validate_serial = 0;
clib_mem_trace (int enable)
{
mheap_trace_main_t *tm = &mheap_trace_main;
+ void *current_heap = clib_mem_get_heap ();
tm->enabled = enable;
- mheap_trace (clib_mem_get_heap (), enable);
+ mheap_trace (current_heap, enable);
+
+ if (enable)
+ tm->current_traced_mheap = current_heap;
+ else
+ tm->current_traced_mheap = 0;
+}
+
+int
+clib_mem_is_traced (void)
+{
+ return mspace_is_traced (clib_mem_get_heap ());
}
uword