#include "malloc_elem.h"
#include "malloc_heap.h"
-#define MIN_DATA_SIZE (RTE_CACHE_LINE_SIZE)
-
/*
* Initialize a general malloc_elem header structure
*/
split_elem(elem, hide_end);
malloc_elem_free_list_insert(hide_end);
- } else if (len_after >= MALLOC_ELEM_HEADER_LEN) {
- /* shrink current element */
- elem->size -= len_after;
- memset(hide_end, 0, sizeof(*hide_end));
-
- /* copy next element's data to our pad */
- memcpy(hide_end, next, sizeof(*hide_end));
-
- /* pad next element */
- next->state = ELEM_PAD;
- next->pad = len_after;
- next->size -= len_after;
-
- /* next element busy, would've been merged otherwise */
- hide_end->pad = len_after;
- hide_end->size += len_after;
-
- /* adjust pointers to point to our new pad */
- if (next->next)
- next->next->prev = hide_end;
- elem->next = hide_end;
} else if (len_after > 0) {
RTE_LOG(ERR, EAL, "Unaligned element, heap is probably corrupt\n");
return;
malloc_elem_free_list_insert(prev);
} else if (len_before > 0) {
- /*
- * unlike with elements after current, here we don't
- * need to pad elements, but rather just increase the
- * size of previous element, copy the old header and set
- * up trailer.
- */
- void *trailer = RTE_PTR_ADD(prev,
- prev->size - MALLOC_ELEM_TRAILER_LEN);
-
- memcpy(hide_start, elem, sizeof(*elem));
- hide_start->size = len;
-
- prev->size += len_before;
- set_trailer(prev);
-
- /* update pointers */
- prev->next = hide_start;
- if (next)
- next->prev = hide_start;
-
- /* erase old trailer */
- memset(trailer, 0, MALLOC_ELEM_TRAILER_LEN);
- /* erase old header */
- memset(elem, 0, sizeof(*elem));
-
- elem = hide_start;
+ RTE_LOG(ERR, EAL, "Unaligned element, heap is probably corrupt\n");
+ return;
}
}
void *start, *aligned_start, *end, *aligned_end;
size_t len, aligned_len, page_sz;
struct rte_memseg_list *msl;
- unsigned int i, n_segs;
+ unsigned int i, n_segs, before_space, after_space;
int ret;
if (!malloc_elem_cookies_ok(elem) || elem->state != ELEM_BUSY)
if (n_segs == 0)
goto free_unlock;
+ /* We're not done yet. We also have to check if by freeing space we will
+ * be leaving free elements that are too small to store new elements.
+ * Check if we have enough space in the beginning and at the end, or if
+ * start/end are exactly page aligned.
+ */
+ before_space = RTE_PTR_DIFF(aligned_start, elem);
+ after_space = RTE_PTR_DIFF(end, aligned_end);
+ if (before_space != 0 &&
+ before_space < MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* There is not enough space before start, but we may be able to
+ * move the start forward by one page.
+ */
+ if (n_segs == 1)
+ goto free_unlock;
+
+ /* move start */
+ aligned_start = RTE_PTR_ADD(aligned_start, page_sz);
+ aligned_len -= page_sz;
+ n_segs--;
+ }
+ if (after_space != 0 && after_space <
+ MALLOC_ELEM_OVERHEAD + MIN_DATA_SIZE) {
+ /* There is not enough space after end, but we may be able to
+ * move the end backwards by one page.
+ */
+ if (n_segs == 1)
+ goto free_unlock;
+
+ /* move end */
+ aligned_end = RTE_PTR_SUB(aligned_end, page_sz);
+ aligned_len -= page_sz;
+ n_segs--;
+ }
+
+ /* now we can finally free us some pages */
+
rte_rwlock_write_lock(&mcfg->memory_hotplug_lock);
/*