[dpdk-dev] [PATCH 03/41] eal: make malloc heap a doubly-linked list
Burakov, Anatoly
anatoly.burakov at intel.com
Tue Mar 20 10:39:45 CET 2018
On 19-Mar-18 5:33 PM, Olivier Matz wrote:
> On Sat, Mar 03, 2018 at 01:45:51PM +0000, Anatoly Burakov wrote:
>> As we are preparing for dynamic memory allocation, we need to be
>> able to handle holes in our malloc heap, hence we're switching to
>> doubly linked list, and prepare infrastructure to support it.
>>
>> Since our heap is now aware where are our first and last elements,
>> there is no longer any need to have a dummy element at the end of
>> each heap, so get rid of that as well. Instead, let insert/remove/
>> join/split operations handle end-of-list conditions automatically.
>>
>> Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
>> ---
>> lib/librte_eal/common/include/rte_malloc_heap.h | 6 +
>> lib/librte_eal/common/malloc_elem.c | 200 +++++++++++++++++++-----
>> lib/librte_eal/common/malloc_elem.h | 14 +-
>> lib/librte_eal/common/malloc_heap.c | 8 +-
>> 4 files changed, 179 insertions(+), 49 deletions(-)
>>
>> diff --git a/lib/librte_eal/common/include/rte_malloc_heap.h b/lib/librte_eal/common/include/rte_malloc_heap.h
>> index ba99ed9..9ec4b62 100644
>> --- a/lib/librte_eal/common/include/rte_malloc_heap.h
>> +++ b/lib/librte_eal/common/include/rte_malloc_heap.h
>> @@ -13,12 +13,18 @@
>> /* Number of free lists per heap, grouped by size. */
>> #define RTE_HEAP_NUM_FREELISTS 13
>>
>> +/* dummy definition, for pointers */
>> +struct malloc_elem;
>> +
>> /**
>> * Structure to hold malloc heap
>> */
>> struct malloc_heap {
>> rte_spinlock_t lock;
>> LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS];
>> + struct malloc_elem *first;
>> + struct malloc_elem *last;
>> +
>> unsigned alloc_count;
>> size_t total_size;
>> } __rte_cache_aligned;
>> diff --git a/lib/librte_eal/common/malloc_elem.c b/lib/librte_eal/common/malloc_elem.c
>> index ea041e2..eb41200 100644
>> --- a/lib/librte_eal/common/malloc_elem.c
>> +++ b/lib/librte_eal/common/malloc_elem.c
>> @@ -31,6 +31,7 @@ malloc_elem_init(struct malloc_elem *elem,
>> elem->heap = heap;
>> elem->ms = ms;
>> elem->prev = NULL;
>> + elem->next = NULL;
>> memset(&elem->free_list, 0, sizeof(elem->free_list));
>> elem->state = ELEM_FREE;
>> elem->size = size;
>> @@ -39,15 +40,56 @@ malloc_elem_init(struct malloc_elem *elem,
>> set_trailer(elem);
>> }
>>
>> -/*
>> - * Initialize 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_insert(struct malloc_elem *elem)
>> {
>> - malloc_elem_init(elem, prev->heap, prev->ms, 0);
>> - elem->prev = prev;
>> - elem->state = ELEM_BUSY; /* mark busy so its never merged */
>> + struct malloc_elem *prev_elem, *next_elem;
>> + struct malloc_heap *heap = elem->heap;
>> +
>> + if (heap->first == NULL && heap->last == NULL) {
>> + /* if empty heap */
>> + heap->first = elem;
>> + heap->last = elem;
>> + prev_elem = NULL;
>> + next_elem = NULL;
>> + } else if (elem < heap->first) {
>> + /* if lower than start */
>> + prev_elem = NULL;
>> + next_elem = heap->first;
>> + heap->first = elem;
>> + } else if (elem > heap->last) {
>> + /* if higher than end */
>> + prev_elem = heap->last;
>> + next_elem = NULL;
>> + heap->last = elem;
>> + } else {
>> + /* the new memory is somewhere inbetween start and end */
>> + uint64_t dist_from_start, dist_from_end;
>> +
>> + dist_from_end = RTE_PTR_DIFF(heap->last, elem);
>> + dist_from_start = RTE_PTR_DIFF(elem, heap->first);
>> +
>> + /* check which is closer, and find closest list entries */
>> + if (dist_from_start < dist_from_end) {
>> + prev_elem = heap->first;
>> + while (prev_elem->next < elem)
>> + prev_elem = prev_elem->next;
>> + next_elem = prev_elem->next;
>> + } else {
>> + next_elem = heap->last;
>> + while (next_elem->prev > elem)
>> + next_elem = next_elem->prev;
>> + prev_elem = next_elem->prev;
>> + }
>> + }
>> +
>> + /* insert new element */
>> + elem->prev = prev_elem;
>> + elem->next = next_elem;
>> + if (prev_elem)
>> + prev_elem->next = elem;
>> + if (next_elem)
>> + next_elem->prev = elem;
>> }
>
> Would it be possible here to use a TAILQ? If yes, it could be
> easier to read.
>
Hi Olivier,
I think it would be a bit hard to make TAILQ's work with pad elements
without making the code unreadable :) I am inclined to leave it as is.
--
Thanks,
Anatoly
More information about the dev
mailing list