aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/list.h10
-rw-r--r--src/malloc.c72
2 files changed, 47 insertions, 35 deletions
diff --git a/src/list.h b/src/list.h
index de656b9..94512e3 100644
--- a/src/list.h
+++ b/src/list.h
@@ -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) \
diff --git a/src/malloc.c b/src/malloc.c
index db451ce..c41a0cb 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -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;
}