commit 93a0b753f23a4823c90cc6bab76478b638c21ae0
parent 7915e540408259f295841cc47a2c545dc492e590
Author: sin <sin@2f30.org>
Date: Mon, 5 Aug 2013 11:22:53 +0100
When we realloc() split the unused space into a separate node
When we shrink the allocated region and there is enough space left
split it out and insert it into the free tree. We need to make sure
the new address continues to be aligned properly so we do not split
unless there is enough space to align the free space.
Diffstat:
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/lemoncake.c b/lemoncake.c
@@ -186,7 +186,7 @@ realloc(void *oldp, size_t siz)
{
struct node n, *res;
struct node *oldan, *newan;
- struct node *fn;
+ struct node *fn, *newfn;
if (lemon_init())
return NULL;
@@ -201,9 +201,31 @@ realloc(void *oldp, size_t siz)
n.buf = oldp;
res = RB_FIND(alloc_tree, &at, &n);
if (res) {
- /* If we were asked to shrink the allocated space
- * just re-use it */
- if (res->siz >= siz) {
+ if (res->siz == siz) {
+ unlock(&rblock);
+ st.nr_realloc++;
+ return res->buf;
+ }
+ if (res->siz > siz) {
+ size_t diff = res->siz - siz;
+ if (diff < ALIGN + siz) {
+ unlock(&rblock);
+ st.nr_realloc++;
+ st.nr_shrink_realloc++;
+ return res->buf;
+ }
+ newfn = alloc_object(sizeof(*newfn));
+ if (!newfn) {
+ unlock(&rblock);
+ return NULL;
+ }
+ res->siz = siz;
+ newfn->buf = res->buf + siz;
+ newfn->siz = diff;
+ newfn->siz -= (uintptr_t)align_pointer(ALIGN, newfn->buf);
+ newfn->siz += (uintptr_t)newfn->buf;
+ newfn->buf = align_pointer(ALIGN, newfn->buf);
+ RB_INSERT(free_tree, &ft, newfn);
unlock(&rblock);
st.nr_realloc++;
st.nr_shrink_realloc++;