summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@pmikkelsen.com>2026-10-07 17:59:50 +0000
committerpeter <peter@pmikkelsen.com>2026-10-07 17:59:50 +0000
commit87a324b2e0c41ba294c43016cc38953dd1023688 (patch)
tree027f657b5cac3127ba10e8db648a367d7b93ca6b
parente123d8528e6ffb31d18c23af89b5dd6d74b22990 (diff)
For testing, move memory around sometimes [c9e361fa97].
FossilOrigin-Name: b78e635bff051ffacfbaab830b770c30aca3e775a2613d09b503ec784c2d49ab
-rw-r--r--src/lib/memory.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/src/lib/memory.c b/src/lib/memory.c
index 006c409..b61f844 100644
--- a/src/lib/memory.c
+++ b/src/lib/memory.c
@@ -438,14 +438,60 @@ compact(struct aplwc *aplwc)
}
}
+static void
+shuffle(struct aplwc *aplwc)
+{
+ struct chunk *c, *prev, *prev_prev;
+ size_t move;
+
+ compact(aplwc);
+
+ prev_prev = prev = NULL;
+ for(c = (struct chunk *)aplwc->data; c; prev_prev = prev, prev = c, c = next(c))
+ assert((next(c) == NULL) || (c->tag != CHUNK_TAG_FREE));
+
+ if(prev == NULL) /* No chunks */
+ return;
+
+ if(prev->tag != CHUNK_TAG_FREE){ /* No free space at the end */
+ if(grow(aplwc, HEADER_SIZE*8))
+ shuffle(aplwc);
+ return;
+ }
+
+ if(prev_prev == NULL) /* Only free space */
+ return;
+
+ assert(prev);
+ assert(prev->tag == CHUNK_TAG_FREE);
+ move = prev->size;
+ prev_prev->last = 1;
+ memmove(aplwc->data+move, aplwc->data, aplwc->size-move);
+
+ aplwc->data += move;
+ aplwc->size -= move;
+ fixrefs(aplwc, aplwc->data-move);
+
+ aplwc->data -= move;
+ aplwc->size += move;
+
+ c = (struct chunk *)aplwc->data;
+ c->stack = NULL;
+ c->tag = CHUNK_TAG_FREE;
+ c->size = move;
+ c->last = 0;
+}
+
static void *
alloc(struct aplwc *aplwc, size_t size, enum chunk_tag tag)
{
struct chunk *free, *new;
size_t pad;
-
int attempt;
+
+ FAILCASE((void)0, shuffle(aplwc));
+
pad = size % ALIGNMENT;
if(pad)
size += ALIGNMENT - pad;