Browse Source

Fixed splitting free list pointer problems revealed by checking code

main
Titouan Rigoudy 11 years ago
parent
commit
8e84ca9434
3 changed files with 34 additions and 30 deletions
  1. +13
    -6
      ya_freelist.c
  2. +3
    -2
      ya_freelist.h
  3. +18
    -22
      yamalloc.c

+ 13
- 6
ya_freelist.c View File

@ -92,13 +92,20 @@ intptr_t *fl_find(intptr_t min_size) {
return NULL; return NULL;
} }
/* Force split of free block [block_size] into [size, block_size - size]. */
void fl_split(intptr_t *block, intptr_t size) {
fl_set_next(block, block+size);
if (block == fl_end) {
fl_end = block+size;
/* Mends the free list after a free block has just been split into two blocks,
* block and new_next. */
void fl_mend_split(intptr_t *block, intptr_t *new_next) {
if (!new_next) {
return; // block was not split
}
intptr_t *old_next = fl_next(new_next);
fl_set_next(block, new_next);
fl_set_prev(new_next, block);
if (old_next) {
fl_set_prev(old_next, new_next);
} else {
fl_end = new_next;
} }
fl_set_prev(block+size, block);
} }
void fl_join_next(intptr_t *block) { void fl_join_next(intptr_t *block) {


+ 3
- 2
ya_freelist.h View File

@ -69,8 +69,9 @@ void fl_free(intptr_t *block);
* Returns NULL if no adequate block is found. Does not grow the heap. */ * Returns NULL if no adequate block is found. Does not grow the heap. */
intptr_t *fl_find(intptr_t min_size); intptr_t *fl_find(intptr_t min_size);
/* Force split of block [block_size] into [size, block_size - size]. */
void fl_split(intptr_t *block, intptr_t size);
/* Mends the free list after a free block has just been split into two blocks,
* block and new_next. */
void fl_mend_split(intptr_t *block, intptr_t *new_next);
void fl_join_prev(intptr_t *block); void fl_join_prev(intptr_t *block);


+ 18
- 22
yamalloc.c View File

@ -16,6 +16,18 @@
/* Function definitions */ /* Function definitions */
/*----------------------*/ /*----------------------*/
/* Splits block both at the block level and in the free list. */
void split(intptr_t *block, intptr_t size) {
fl_mend_split(block, block_split(block, size));
}
/* Coalesces block with neighbors if possible, both at the block level and in
* the free list. */
void join(intptr_t *block) {
fl_join(block);
block_join(block);
}
/* Allocates enough memory to store at least size bytes. /* Allocates enough memory to store at least size bytes.
* Returns a dword-aligned pointer to the memory or NULL in case of failure. */ * Returns a dword-aligned pointer to the memory or NULL in case of failure. */
void *malloc(size_t n_bytes) { void *malloc(size_t n_bytes) {
@ -32,10 +44,7 @@ void *malloc(size_t n_bytes) {
if (!block) { if (!block) {
block = heap_extend(n_bytes); block = heap_extend(n_bytes);
} }
if (block_split(block, size)) {
// block was indeed split, so splt it in the free list as well
fl_split(block, size);
}
split(block, size);
block_alloc(block); block_alloc(block);
fl_alloc(block); fl_alloc(block);
return block; return block;
@ -51,8 +60,7 @@ void free(void *ptr) {
} }
block_free(block); block_free(block);
fl_free(block); fl_free(block);
fl_join(block);
block_join(block);
join(block);
} }
/* Allocates enough memory to store an array of nmemb elements, /* Allocates enough memory to store an array of nmemb elements,
@ -100,31 +108,19 @@ void *realloc(void *ptr, size_t n_bytes) {
return block; return block;
} }
intptr_t *next = block + size; intptr_t *next = block + size;
if (next == heap_end ||
(!block_is_alloc(next) && next + block_size(next) == heap_end)) {
if (next == heap_end || next == fl_get_end()) {
// grow the heap and extend block // grow the heap and extend block
next = heap_extend(n_bytes); next = heap_extend(n_bytes);
fl_free(block);
fl_join_next(block);
block_join_next(block);
if (block_split(block, new_size)) {
fl_split(block, new_size);
}
block_alloc(block);
fl_alloc(block);
return block;
// then fall into next if clause which will use the newly extended
// heap to extend the block without moving it
} }
// try to use next free block // try to use next free block
if (next < heap_end) { if (next < heap_end) {
intptr_t next_size = block_size(next); intptr_t next_size = block_size(next);
if (!block_is_alloc(next) && new_size <= size + next_size) { if (!block_is_alloc(next) && new_size <= size + next_size) {
// try to split the next block at the right size // try to split the next block at the right size
if (block_split(next, new_size - size)) {
// split successful, must split in the free list too
fl_split(block, new_size);
}
split(next, new_size - size);
fl_alloc(next); // remove the next block from the free list fl_alloc(next); // remove the next block from the free list
fl_join_next(block);
block_join_next(block); // coalesce block_join_next(block); // coalesce
block_alloc(block); // mark block as allocated block_alloc(block); // mark block as allocated
return block; return block;


Loading…
Cancel
Save