Browse Source

Added freelist functionality, not tested yet though

main
Titouan Rigoudy 11 years ago
parent
commit
cb2a1fe04e
4 changed files with 148 additions and 39 deletions
  1. +1
    -1
      Makefile
  2. +109
    -0
      ya_freelist.c
  3. +34
    -13
      ya_freelist.h
  4. +4
    -25
      yamalloc.c

+ 1
- 1
Makefile View File

@ -10,7 +10,7 @@ test: yatest
%.o: %.c
$(CC) -c $^ $(CPPFLAGS) $(CFLAGS)
yatest: yatest.o yamalloc.o ya_block.o
yatest: yatest.o yamalloc.o ya_freelist.o ya_block.o
$(CC) -o $@ $^ $(CFLAGS)
clean:


+ 109
- 0
ya_freelist.c View File

@ -0,0 +1,109 @@
/*
* Yet Another Malloc
* ya_freelist.c
*/
/* Block layout:
*
* -2 -1 0 size-4 size-3
* +------+------+-------- - - - - - - - --------+------+------+
* | prev | size | data... | size | next |
* +------+------+-------- - - - - - - - --------+------+------+
*
*/
/*----------*/
/* Includes */
/*----------*/
#include <stdio.h>
#include "ya_freelist.h"
#include "ya_block.h"
/*---------*/
/* Globals */
/*---------*/
intptr_t *fl_start = NULL; // sorted increasing
intptr_t *fl_end = NULL; // sorted decreasing
/*-----------*/
/* Functions */
/*-----------*/
#ifdef YA_DEBUG
void fl_debug_print() {
for (intptr_t *block = fl_start; block != NULL; block = fl_next(block)) {
printf("Free block %p:%ld\n", block, block_size(block));
}
}
#endif
/* Splices the allocated block out of the free list. */
void fl_alloc(intptr_t *block) {
intptr_t size = block_size(block);
intptr_t *prev = fl_prev(block);
intptr_t *next = fl_next(block);
fl_set_prev(block, NULL);
fl_set_next(block, NULL);
if (prev) {
fl_set_next(prev, next);
} else {
fl_start = next;
}
if (next) {
fl_set_prev(next, prev);
} else {
fl_end = prev;
}
}
/* Adds the freed block to the appropriate in the free list, which is kept
* in sorted increasing order. */
void fl_free(intptr_t *block) {
intptr_t *next;
for (next = fl_start; next && block < next; next = fl_next(next)) {
// *whistle*
}
if (next == fl_start) {
// preprend block to the free list
fl_set_prev(block, NULL);
fl_set_next(block, fl_start);
fl_set_prev(fl_start, block);
fl_start = block;
return;
}
if (!next) {
// append block to the free list
fl_set_prev(block, fl_end);
fl_set_next(block, NULL);
fl_set_next(fl_end, block);
fl_end = block;
return;
}
// splice the block in the middle of the list
intptr_t *prev = fl_prev(next);
fl_set_prev(block, prev);
fl_set_next(block, next);
fl_set_prev(next, block);
fl_set_next(prev, block);
}
/* Returns the first block in the free list at min_size words long.
* Returns NULL if no adequate block is found. Does not grow the heap. */
intptr_t *fl_find(intptr_t min_size) {
for (intptr_t *block = fl_start; block != NULL; block = fl_next(block)) {
if (min_size <= block_size(block)) {
return block;
}
}
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);
fl_set_prev(block+size, block);
}

+ 34
- 13
ya_freelist.h View File

@ -12,28 +12,49 @@
#include <stdint.h> // for intptr_t
/*------------*/
/* Data types */
/*------------*/
#include "ya_block.h"
struct fl {
intptr_t *block;
struct fl *prev;
struct fl *next;
};
/*---------*/
/* Inlines */
/*---------*/
static inline intptr_t *fl_prev(intptr_t *block) {
return (intptr_t *) block[-2];
}
static inline intptr_t *fl_next(intptr_t *block) {
return (intptr_t *) block[block_size(block)-3];
}
static inline void fl_set_prev(intptr_t *block, intptr_t *prev) {
block[-2] = (intptr_t) prev;
}
static inline void fl_set_next(intptr_t *block, intptr_t *next) {
block[block_size(block)-3] = (intptr_t) next;
}
/*--------------*/
/* Declarations */
/*--------------*/
struct fl *fl_find(intptr_t min_size);
#ifdef YA_DEBUG
void fl_debug_print();
#endif
/* Splices the allocated block out of the free list. */
void fl_alloc(intptr_t *block);
void fl_split(struct fl *fl);
/* Adds the freed block to the start of the free list. */
void fl_free(intptr_t *block);
void fl_join_prev(struct fl *fl);
/* Returns the first block in the free list at min_size words long.
* Returns NULL if no adequate block is found. Does not grow the heap. */
intptr_t *fl_find(intptr_t min_size);
void fl_join_next(struct fl *fl);
/* Force split of block [block_size] into [size, block_size - size]. */
void fl_split(intptr_t *block, intptr_t size);
void fl_join(struct fl *fl);
/* Joins are unnecessary because the pointers will still be ok after a join. */
#endif

+ 4
- 25
yamalloc.c View File

@ -3,38 +3,14 @@
* yamalloc.c
*/
/*---------------------*/
/* Feature test macros */
/*---------------------*/
#define _DEFAULT_SOURCE // for sbrk
/*----------*/
/* Includes */
/*----------*/
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include "yamalloc.h"
#include "ya_debug.h"
#include "ya_block.h"
/*-----------*/
/* Constants */
/*-----------*/
/*--------*/
/* Macros */
/*--------*/
/*--------------------*/
/* Local declarations */
/*--------------------*/
#include "ya_freelist.h"
/*----------------------*/
/* Function definitions */
@ -43,7 +19,10 @@
#ifdef YA_DEBUG
/* Print all blocks in the heap */
void ya_print_blocks() {
ya_debug("All blocks:\n");
block_print_range(heap_start, heap_end);
ya_debug("Free blocks:\n");
fl_debug_print();
}
#endif


Loading…
Cancel
Save