malloc: Introduce common helper alloc_new_detail()

Introduce helper for finding temp space to hold an "allocation detail
struct" and use it in both alloc_add() and _malloc().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2015-09-28 22:20:27 -04:00
parent 41acaa8274
commit 7af8d120fb
2 changed files with 47 additions and 35 deletions

View File

@ -61,6 +61,16 @@ hlist_add_after(struct hlist_node *n, struct hlist_node *prev)
hlist_add(n, &prev->next);
}
static inline void
hlist_replace(struct hlist_node *old, struct hlist_node *new)
{
new->next = old->next;
if (new->next)
new->next->pprev = &new->next;
new->pprev = old->pprev;
*new->pprev = new;
}
#define hlist_for_each_entry(pos, head, member) \
for (pos = container_of((head)->first, typeof(*pos), member) \
; pos != container_of(NULL, typeof(*pos), member) \

View File

@ -57,8 +57,6 @@ alloc_new(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill)
void *newallocend = (void*)ALIGN_DOWN((u32)allocend - size, align);
if (newallocend >= dataend && newallocend <= allocend) {
// Found space - now reserve it.
if (!fill)
fill = newallocend;
fill->data = newallocend;
fill->dataend = newallocend + size;
fill->allocend = allocend;
@ -71,6 +69,28 @@ alloc_new(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill)
return NULL;
}
// Reserve space for a 'struct allocdetail_s' and fill
static struct allocdetail_s *
alloc_new_detail(struct allocdetail_s *temp)
{
struct allocdetail_s *detail = alloc_new(
&ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, &temp->detailinfo);
if (!detail) {
detail = alloc_new(&ZoneTmpLow, sizeof(*detail)
, MALLOC_MIN_ALIGN, &temp->detailinfo);
if (!detail) {
warn_noalloc();
return NULL;
}
}
// Fill final 'detail' allocation from data in 'temp'
memcpy(detail, temp, sizeof(*detail));
hlist_replace(&temp->detailinfo.node, &detail->detailinfo.node);
hlist_replace(&temp->datainfo.node, &detail->datainfo.node);
return detail;
}
// Add new memory to a zone
static void
alloc_add(struct zone_s *zone, void *start, void *end)
@ -85,29 +105,15 @@ alloc_add(struct zone_s *zone, void *start, void *end)
// Add space using temporary allocation info.
struct allocdetail_s tempdetail;
tempdetail.handle = MALLOC_DEFAULT_HANDLE;
tempdetail.datainfo.data = tempdetail.datainfo.dataend = start;
tempdetail.datainfo.allocend = end;
hlist_add(&tempdetail.datainfo.node, pprev);
// Allocate final allocation info.
struct allocdetail_s *detail = alloc_new(
&ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL);
if (!detail) {
detail = alloc_new(&ZoneTmpLow, sizeof(*detail)
, MALLOC_MIN_ALIGN, NULL);
if (!detail) {
hlist_del(&tempdetail.datainfo.node);
warn_noalloc();
return;
}
}
// Replace temp alloc space with final alloc space
pprev = tempdetail.datainfo.node.pprev;
hlist_del(&tempdetail.datainfo.node);
memcpy(&detail->datainfo, &tempdetail.datainfo, sizeof(detail->datainfo));
detail->handle = MALLOC_DEFAULT_HANDLE;
hlist_add(&detail->datainfo.node, pprev);
struct allocdetail_s *detail = alloc_new_detail(&tempdetail);
if (!detail)
hlist_del(&tempdetail.datainfo.node);
}
// Release space allocated with alloc_new()
@ -232,23 +238,19 @@ _malloc(struct zone_s *zone, u32 size, u32 align)
if (!size)
return NULL;
// Find and reserve space for bookkeeping.
struct allocdetail_s *detail = alloc_new(
&ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL);
if (!detail) {
detail = alloc_new(&ZoneTmpLow, sizeof(*detail)
, MALLOC_MIN_ALIGN, NULL);
if (!detail)
return NULL;
}
detail->handle = MALLOC_DEFAULT_HANDLE;
// Find and reserve space for main allocation
void *data = alloc_new(zone, size, align, &detail->datainfo);
struct allocdetail_s tempdetail;
tempdetail.handle = MALLOC_DEFAULT_HANDLE;
void *data = alloc_new(zone, size, align, &tempdetail.datainfo);
if (!CONFIG_MALLOC_UPPERMEMORY && !data && zone == &ZoneLow)
data = zonelow_expand(size, align, &detail->datainfo);
if (!data) {
alloc_free(&detail->detailinfo);
data = zonelow_expand(size, align, &tempdetail.datainfo);
if (!data)
return NULL;
// Find and reserve space for bookkeeping.
struct allocdetail_s *detail = alloc_new_detail(&tempdetail);
if (!detail) {
alloc_free(&tempdetail.datainfo);
return NULL;
}