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>
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(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 @@
         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 @@
     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 @@
 
     // 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 @@
     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;
     }