aboutsummaryrefslogtreecommitdiffstats
path: root/com32/lib/free.c
diff options
context:
space:
mode:
Diffstat (limited to 'com32/lib/free.c')
-rw-r--r--com32/lib/free.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/com32/lib/free.c b/com32/lib/free.c
index f8a2e1f4..a91ad8ef 100644
--- a/com32/lib/free.c
+++ b/com32/lib/free.c
@@ -79,6 +79,43 @@ void free(void *ptr)
/* Here we could insert code to return memory to the system. */
}
+/*
+ * This is used to insert a block which is not previously on the
+ * free list. Only the a.size field of the arena header is assumed
+ * to be valid.
+ */
+void __inject_free_block(struct free_arena_header *ah)
+{
+ struct free_arena_header *nah;
+ size_t a_end = (size_t) ah + ARENA_SIZE_GET(ah->a.attrs);
+ size_t n_end;
+
+ for (nah = __malloc_head.a.next; ARENA_TYPE_GET(nah->a.attrs) != ARENA_TYPE_HEAD;
+ nah = nah->a.next) {
+ n_end = (size_t) nah + ARENA_SIZE_GET(nah->a.attrs);
+
+ /* Is nah entirely beyond this block? */
+ if ((size_t) nah >= a_end)
+ break;
+
+ /* Is this block entirely beyond nah? */
+ if ((size_t) ah >= n_end)
+ continue;
+
+ /* Otherwise we have some sort of overlap - reject this block */
+ return;
+ }
+
+ /* Now, nah should point to the successor block */
+ ah->a.next = nah;
+ ah->a.prev = nah->a.prev;
+ nah->a.prev = ah;
+ ah->a.prev->a.next = ah;
+
+ __free_block(ah);
+}
+
+
void __free_tagged(void *tag) {
struct free_arena_header *fp, *nfp;