Esempio n. 1
0
/*
 * initialise a dummy malloc_elem header for the end-of-memseg marker
 */
void
malloc_elem_mkend(struct malloc_elem *elem, struct malloc_elem *prev)
{
	malloc_elem_init(elem, prev->heap, prev->ms, 0);
	elem->prev = prev;
	elem->state = ELEM_BUSY; /* mark busy so its never merged */
}
Esempio n. 2
0
/*
 * split an existing element into two smaller elements at the given
 * split_pt parameter.
 */
static void
split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)
{
	struct malloc_elem *next_elem = RTE_PTR_ADD(elem, elem->size);
	const size_t old_elem_size = (uintptr_t)split_pt - (uintptr_t)elem;
	const size_t new_elem_size = elem->size - old_elem_size;

	malloc_elem_init(split_pt, elem->heap, elem->ms, new_elem_size);
	split_pt->prev = elem;
	next_elem->prev = split_pt;
	elem->size = old_elem_size;
	set_trailer(elem);
}
Esempio n. 3
0
/*
 * Expand the heap with a memseg.
 * This reserves the zone and sets a dummy malloc_elem header at the end
 * to prevent overflow. The rest of the zone is added to free list as a single
 * large free block
 */
static void
malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)
{
	/* allocate the memory block headers, one at end, one at start */
	struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr;
	struct malloc_elem *end_elem = RTE_PTR_ADD(ms->addr,
			ms->len - MALLOC_ELEM_OVERHEAD);
	end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);
	const size_t elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;

	malloc_elem_init(start_elem, heap, ms, elem_size);
	malloc_elem_mkend(end_elem, start_elem);
	malloc_elem_free_list_insert(start_elem);

	heap->total_size += elem_size;
}
Esempio n. 4
0
/*
 * Expand the heap with a memory area.
 */
static struct malloc_elem *
malloc_heap_add_memory(struct malloc_heap *heap, struct rte_memseg_list *msl,
		void *start, size_t len)
{
	struct malloc_elem *elem = start;

	malloc_elem_init(elem, heap, msl, len);

	malloc_elem_insert(elem);

	elem = malloc_elem_join_adjacent_free(elem);

	malloc_elem_free_list_insert(elem);

	return elem;
}
Esempio n. 5
0
/*
 * reserve an extra memory zone and make it available for use by a particular
 * heap. This reserves the zone and sets a dummy malloc_elem header at the end
 * to prevent overflow. The rest of the zone is added to free list as a single
 * large free block
 */
static int
malloc_heap_add_memzone(struct malloc_heap *heap, size_t size, unsigned align)
{
	const unsigned mz_flags = 0;
	const size_t block_size = get_malloc_memzone_size();
	/* ensure the data we want to allocate will fit in the memzone */
	const size_t min_size = size + align + MALLOC_ELEM_OVERHEAD * 2;
	const struct rte_memzone *mz = NULL;
	struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config;
	unsigned numa_socket = heap - mcfg->malloc_heaps;

	size_t mz_size = min_size;
	if (mz_size < block_size)
		mz_size = block_size;

	char mz_name[RTE_MEMZONE_NAMESIZE];
	snprintf(mz_name, sizeof(mz_name), "MALLOC_S%u_HEAP_%u",
		     numa_socket, heap->mz_count++);

	/* try getting a block. if we fail and we don't need as big a block
	 * as given in the config, we can shrink our request and try again
	 */
	do {
		mz = rte_memzone_reserve(mz_name, mz_size, numa_socket,
					 mz_flags);
		if (mz == NULL)
			mz_size /= 2;
	} while (mz == NULL && mz_size > min_size);
	if (mz == NULL)
		return -1;

	/* allocate the memory block headers, one at end, one at start */
	struct malloc_elem *start_elem = (struct malloc_elem *)mz->addr;
	struct malloc_elem *end_elem = RTE_PTR_ADD(mz->addr,
			mz_size - MALLOC_ELEM_OVERHEAD);
	end_elem = RTE_PTR_ALIGN_FLOOR(end_elem, RTE_CACHE_LINE_SIZE);

	const unsigned elem_size = (uintptr_t)end_elem - (uintptr_t)start_elem;
	malloc_elem_init(start_elem, heap, mz, elem_size);
	malloc_elem_mkend(end_elem, start_elem);
	malloc_elem_free_list_insert(start_elem);

	/* increase heap total size by size of new memzone */
	heap->total_size+=mz_size - MALLOC_ELEM_OVERHEAD;
	return 0;
}