summaryrefslogtreecommitdiff
path: root/magic_buddy
diff options
context:
space:
mode:
Diffstat (limited to 'magic_buddy')
-rw-r--r--magic_buddy/magic_buddy.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/magic_buddy/magic_buddy.c b/magic_buddy/magic_buddy.c
index 6f9851b..f3dac00 100644
--- a/magic_buddy/magic_buddy.c
+++ b/magic_buddy/magic_buddy.c
@@ -78,6 +78,7 @@ static void *_allocate(size_t logsize, struct buddy *state) {
memset(block, 0, sizeof(struct free_block));
return block;
}
+ if (logsize == state->root_logsize) return 0;
struct free_block *parent = _allocate(logsize + 1, state);
struct free_block *buddy = buddy_of(parent, logsize, state);
@@ -298,6 +299,7 @@ int shrink_buddy(size_t new_size, struct buddy *state) {
// along the lhs path, until the root itself is free.
size_t logsize = size2log(new_size, 0);
+ if ((1 << logsize) <= sizeof(struct free_block)) return 0;
// First, just check whether we'll be able to do it:
size_t virtual_root_logsize = state->root_logsize;
@@ -313,10 +315,14 @@ int shrink_buddy(size_t new_size, struct buddy *state) {
// It's possible! So go through and actually free the rhs children.
while (state->root_logsize > logsize) {
- if (isfree(state->base, state->root_logsize, state)) break;
- struct free_block *rhs_child
- = rhs_child_of(state->base, virtual_root_logsize, state);
- memset(rhs_child, 0, sizeof(struct free_block));
+ if (isfree(state->base, state->root_logsize, state)) {
+ pop(state->base);
+ push(state->base, state->root_logsize - 1, state);
+ } else {
+ struct free_block *rhs_child
+ = rhs_child_of(state->base, state->root_logsize, state);
+ memset(rhs_child, 0, sizeof(struct free_block));
+ }
state->root_logsize--;
}
state->root_logsize = logsize;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback