Compare commits
6 Commits
v0.1.0-alp
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| e087e699c5 | |||
| 217a73f2e9 | |||
| 64ad489b90 | |||
| 9f41a1bd7f | |||
| 62612f8348 | |||
| 85e660b8db |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -18,4 +18,6 @@ include/config.h*
|
|||||||
missing
|
missing
|
||||||
stamp-h1
|
stamp-h1
|
||||||
.deps
|
.deps
|
||||||
tests/test_bitmapalloc
|
tests/test_bitmapalloc
|
||||||
|
tests/test_buddyalloc
|
||||||
|
tests/test_listalloc
|
||||||
@@ -1 +1,2 @@
|
|||||||
nobase_include_HEADERS = libmalloc/bitmap_alloc.h libmalloc/memmap.h libmalloc/common.h
|
nobase_include_HEADERS = libmalloc/bitmap_alloc.h libmalloc/buddy_alloc.h \
|
||||||
|
libmalloc/list_alloc.h libmalloc/memmap.h libmalloc/common.h
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _LIBMALLOC_BUDDYALLOC_H
|
#ifndef _LIBMALLOC_BITMAPALLOC_H
|
||||||
#define _LIBMALLOC_BUDDYALLOC_H
|
#define _LIBMALLOC_BITMAPALLOC_H
|
||||||
|
|
||||||
#include "memmap.h"
|
#include "memmap.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|||||||
55
include/libmalloc/buddy_alloc.h
Normal file
55
include/libmalloc/buddy_alloc.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef _LIBMALLOC_BUDDYALLOC_H
|
||||||
|
#define _LIBMALLOC_BUDDYALLOC_H
|
||||||
|
|
||||||
|
#include "memmap.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
typedef struct buddy_block_t
|
||||||
|
{
|
||||||
|
struct buddy_block_t *linkb;
|
||||||
|
|
||||||
|
struct buddy_block_t *linkf;
|
||||||
|
|
||||||
|
unsigned long kval;
|
||||||
|
|
||||||
|
unsigned long tag;
|
||||||
|
|
||||||
|
} buddy_block_t;
|
||||||
|
|
||||||
|
typedef struct buddy_descriptor_t
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief An array of `buddy_block_t` structs serving as the heads of the
|
||||||
|
* lists of available blocks. avail[k] serves as the head of the list of
|
||||||
|
* blocks of size 2^k.
|
||||||
|
*/
|
||||||
|
buddy_block_t *avail;
|
||||||
|
|
||||||
|
buddy_block_t *block_map;
|
||||||
|
|
||||||
|
unsigned long block_map_size;
|
||||||
|
|
||||||
|
unsigned long max_kval;
|
||||||
|
|
||||||
|
unsigned long block_size;
|
||||||
|
|
||||||
|
unsigned long offset;
|
||||||
|
|
||||||
|
unsigned long free_block_count;
|
||||||
|
|
||||||
|
int (*mmap)(void *location, unsigned long size);
|
||||||
|
|
||||||
|
} buddy_descriptor_t;
|
||||||
|
|
||||||
|
unsigned long buddy_map_size(const memory_map_t *map, unsigned long block_size);
|
||||||
|
|
||||||
|
unsigned long buddy_reserve(buddy_descriptor_t *heap, unsigned long size);
|
||||||
|
|
||||||
|
unsigned long buddy_free(buddy_descriptor_t *heap, unsigned long location);
|
||||||
|
|
||||||
|
unsigned long buddy_free_size(buddy_descriptor_t *heap, unsigned long size,
|
||||||
|
unsigned long location);
|
||||||
|
|
||||||
|
int buddy_alloc_init(buddy_descriptor_t *heap, memory_map_t *map);
|
||||||
|
|
||||||
|
#endif
|
||||||
27
include/libmalloc/list_alloc.h
Normal file
27
include/libmalloc/list_alloc.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _LIBMALLOC_LISTALLOC_H
|
||||||
|
#define _LIBMALLOC_LISTALLOC_H
|
||||||
|
|
||||||
|
#include "memmap.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
typedef struct list_block_t
|
||||||
|
{
|
||||||
|
unsigned long free;
|
||||||
|
unsigned long size;
|
||||||
|
struct list_block_t *prev;
|
||||||
|
struct list_block_t *next;
|
||||||
|
} list_block_t;
|
||||||
|
|
||||||
|
typedef struct list_alloc_descriptor_t
|
||||||
|
{
|
||||||
|
list_block_t head;
|
||||||
|
list_block_t *current_block;
|
||||||
|
} list_alloc_descriptor_t;
|
||||||
|
|
||||||
|
void *list_alloc_reserve(list_alloc_descriptor_t *heap, unsigned long size);
|
||||||
|
|
||||||
|
void list_alloc_free(list_alloc_descriptor_t *heap, void *p);
|
||||||
|
|
||||||
|
int list_alloc_init(list_alloc_descriptor_t *heap, memory_map_t *map);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
lib_LIBRARIES = libmalloc.a
|
lib_LIBRARIES = libmalloc.a
|
||||||
libmalloc_a_SOURCES = bitmap_alloc.c memmap.c
|
libmalloc_a_SOURCES = buddy_alloc.c bitmap_alloc.c list_alloc.c memmap.c
|
||||||
|
|
||||||
libmalloc_a_CFLAGS = -I$(prefix)/include
|
libmalloc_a_CFLAGS = -I$(prefix)/include
|
||||||
163
src/buddy_alloc.c
Normal file
163
src/buddy_alloc.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#include "libmalloc/buddy_alloc.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define BLOCK_RESERVED 0
|
||||||
|
#define BLOCK_FREE 1
|
||||||
|
|
||||||
|
static unsigned long compute_memory_size(const memory_map_t *map)
|
||||||
|
{
|
||||||
|
// Find the last available region in the memory map.
|
||||||
|
int map_index = map->size - 1;
|
||||||
|
while(map->array[map_index].type != M_AVAILABLE)
|
||||||
|
{
|
||||||
|
map_index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map->array[map_index].location + map->array[map_index].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_block(buddy_descriptor_t *heap, unsigned long index,
|
||||||
|
unsigned long k)
|
||||||
|
{
|
||||||
|
heap->free_block_count += 1UL << k;
|
||||||
|
while(k < heap->max_kval)
|
||||||
|
{
|
||||||
|
unsigned long buddy_index = index ^ (1UL << k);
|
||||||
|
if(heap->block_map[buddy_index].tag != BLOCK_FREE
|
||||||
|
|| heap->block_map[buddy_index].kval != k)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
heap->block_map[buddy_index].linkb->linkf = heap->block_map[buddy_index].linkf;
|
||||||
|
heap->block_map[buddy_index].linkf->linkb = heap->block_map[buddy_index].linkb;
|
||||||
|
heap->block_map[buddy_index].tag = BLOCK_RESERVED;
|
||||||
|
k++;
|
||||||
|
if(buddy_index < index)
|
||||||
|
{
|
||||||
|
index = buddy_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
heap->block_map[index].tag = BLOCK_FREE;
|
||||||
|
buddy_block_t *p = heap->avail[k].linkf;
|
||||||
|
heap->block_map[index].linkf = p;
|
||||||
|
heap->block_map[index].linkb = &heap->avail[k];
|
||||||
|
p->linkb = &heap->block_map[index];
|
||||||
|
heap->avail[k].linkf = &heap->block_map[index];
|
||||||
|
heap->block_map[index].kval = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long buddy_map_size(const memory_map_t *map, unsigned long block_size)
|
||||||
|
{
|
||||||
|
unsigned long memory_size = compute_memory_size(map);
|
||||||
|
return 1UL << llog2(sizeof(buddy_block_t) * memory_size / block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long buddy_reserve(buddy_descriptor_t *heap, unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long k = llog2((size - 1) / heap->block_size + 1);
|
||||||
|
for(unsigned long j = k; j <= heap->max_kval; j++)
|
||||||
|
{
|
||||||
|
if(heap->avail[j].linkf != &heap->avail[j])
|
||||||
|
{
|
||||||
|
buddy_block_t *block = heap->avail[j].linkb;
|
||||||
|
heap->avail[j].linkb = block->linkb;
|
||||||
|
heap->avail[j].linkb->linkf = &heap->avail[j];
|
||||||
|
block->tag = BLOCK_RESERVED;
|
||||||
|
while(j > k)
|
||||||
|
{
|
||||||
|
j--;
|
||||||
|
buddy_block_t *buddy = block + (1UL << j);
|
||||||
|
buddy->tag = BLOCK_FREE;
|
||||||
|
buddy->kval = j;
|
||||||
|
block->kval = j;
|
||||||
|
buddy->linkb = &heap->avail[j];
|
||||||
|
buddy->linkf = &heap->avail[j];
|
||||||
|
heap->avail[j].linkb = buddy;
|
||||||
|
heap->avail[j].linkf = buddy;
|
||||||
|
}
|
||||||
|
unsigned long index = block - heap->block_map;
|
||||||
|
heap->free_block_count -= 1UL << k;
|
||||||
|
return (unsigned long)heap->offset + index * heap->block_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long buddy_free(buddy_descriptor_t *heap, unsigned long location)
|
||||||
|
{
|
||||||
|
unsigned long index = (location - (unsigned long)heap->offset) / heap->block_size;
|
||||||
|
unsigned long k = llog2((heap->block_size * (1UL << heap->block_map[index].kval)) / heap->block_size);
|
||||||
|
insert_block(heap, index, k);
|
||||||
|
return (1UL << k) * heap->block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long buddy_free_size(buddy_descriptor_t *heap, unsigned long location,
|
||||||
|
unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned long index = (location - (unsigned long)heap->offset) / heap->block_size;
|
||||||
|
unsigned long k = llog2(size / heap->block_size);
|
||||||
|
insert_block(heap, index, k);
|
||||||
|
return (1UL << k) * heap->block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buddy_alloc_init(buddy_descriptor_t *heap, memory_map_t *map)
|
||||||
|
{
|
||||||
|
heap->block_map_size = buddy_map_size(map, heap->block_size);
|
||||||
|
heap->max_kval = llog2(heap->block_map_size / sizeof(buddy_block_t));
|
||||||
|
heap->free_block_count = 0;
|
||||||
|
for(int i = 0; i <= heap->max_kval; i++)
|
||||||
|
{
|
||||||
|
heap->avail[i].linkf = &heap->avail[i];
|
||||||
|
heap->avail[i].linkb = &heap->avail[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(heap->block_map == (buddy_block_t*)0)
|
||||||
|
{
|
||||||
|
int map_index = 0;
|
||||||
|
while(map->array[map_index].type != M_AVAILABLE
|
||||||
|
|| map->array[map_index].size < heap->block_map_size)
|
||||||
|
{
|
||||||
|
map_index++;
|
||||||
|
if(map_index >= map->size)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heap->block_map = (buddy_block_t*)(heap->offset + map->array[map_index].location);
|
||||||
|
memmap_insert_region(map, map->array[map_index].location, heap->block_map_size, M_UNAVAILABLE);
|
||||||
|
if(heap->mmap && heap->mmap(heap->block_map, heap->block_map_size))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < heap->block_map_size / sizeof(buddy_block_t); i++)
|
||||||
|
{
|
||||||
|
heap->block_map[i].tag = BLOCK_RESERVED;
|
||||||
|
heap->block_map[i].kval = 0;
|
||||||
|
heap->block_map[i].linkf = 0;
|
||||||
|
heap->block_map[i].linkb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < map->size; i++)
|
||||||
|
{
|
||||||
|
if(map->array[i].type != M_AVAILABLE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long location = (map->array[i].location + heap->block_size - 1);
|
||||||
|
location -= location % heap->block_size;
|
||||||
|
unsigned long region_end = map->array[i].location + map->array[i].size;
|
||||||
|
while(location + heap->block_size <= region_end)
|
||||||
|
{
|
||||||
|
unsigned long index = location / heap->block_size;
|
||||||
|
unsigned long k = 0;
|
||||||
|
insert_block(heap, index, k);
|
||||||
|
location += heap->block_size;
|
||||||
|
heap->free_block_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
129
src/list_alloc.c
Normal file
129
src/list_alloc.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "libmalloc/list_alloc.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define MIN_BLOCK_SIZE (4 * sizeof(list_block_t))
|
||||||
|
|
||||||
|
static list_block_t *block_end_ptr(list_block_t *p)
|
||||||
|
{
|
||||||
|
return (list_block_t*)((void*)p + p->size - sizeof(list_block_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static list_block_t *block_start_ptr(list_block_t *p)
|
||||||
|
{
|
||||||
|
return (list_block_t*)((void*)p - p->size + sizeof(list_block_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_block_tag(list_block_t *p, unsigned long free)
|
||||||
|
{
|
||||||
|
p->free = free;
|
||||||
|
block_end_ptr(p)->free = free;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_block_size(list_block_t *p, unsigned long size)
|
||||||
|
{
|
||||||
|
p->size = size;
|
||||||
|
block_end_ptr(p)->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_block_next(list_block_t *p, list_block_t *next)
|
||||||
|
{
|
||||||
|
p->next = next;
|
||||||
|
block_end_ptr(p)->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_block_prev(list_block_t *p, list_block_t *prev)
|
||||||
|
{
|
||||||
|
p->prev = prev;
|
||||||
|
block_end_ptr(p)->prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_block(list_block_t *p, unsigned long tag, unsigned long size,
|
||||||
|
list_block_t *next, list_block_t *prev)
|
||||||
|
{
|
||||||
|
set_block_size(p, size);
|
||||||
|
set_block_tag(p, tag);
|
||||||
|
set_block_next(p, next);
|
||||||
|
set_block_prev(p, prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *list_alloc_reserve(list_alloc_descriptor_t *heap, unsigned long size)
|
||||||
|
{
|
||||||
|
size += sizeof(unsigned long) - 1;
|
||||||
|
size -= size % sizeof(unsigned long);
|
||||||
|
list_block_t *p = heap->current_block;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(p->size >= (size + 2 * sizeof(list_block_t) + MIN_BLOCK_SIZE))
|
||||||
|
{
|
||||||
|
unsigned long new_size = p->size - size - (2 * sizeof(list_block_t));
|
||||||
|
list_block_t *new_block = (void*)p + new_size;
|
||||||
|
set_block(new_block, 0, size + 2 * sizeof(list_block_t), 0, 0);
|
||||||
|
set_block_tag(p, 1);
|
||||||
|
set_block_size(p, new_size);
|
||||||
|
heap->current_block = p;
|
||||||
|
return (void*)new_block + sizeof(list_block_t);
|
||||||
|
}
|
||||||
|
else if(p->size >= (size + 2 * sizeof(list_block_t)))
|
||||||
|
{
|
||||||
|
set_block_next(p->prev, p->next);
|
||||||
|
set_block_prev(p->next, p->prev);
|
||||||
|
heap->current_block = p->next;
|
||||||
|
set_block(p, 0, p->size, 0, 0);
|
||||||
|
return (void*)p + sizeof(list_block_t);
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
} while(p != heap->current_block);
|
||||||
|
return NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_alloc_free(list_alloc_descriptor_t *heap, void *p)
|
||||||
|
{
|
||||||
|
list_block_t *block = (list_block_t*)(p - sizeof(list_block_t));
|
||||||
|
|
||||||
|
list_block_t *lhs = block_start_ptr(block - 1);
|
||||||
|
if(lhs->free == 1)
|
||||||
|
{
|
||||||
|
set_block_next(lhs->prev, lhs->next);
|
||||||
|
set_block_prev(lhs->next, lhs->prev);
|
||||||
|
unsigned long new_size = block->size + lhs->size;
|
||||||
|
block = (void*)block - lhs->size;
|
||||||
|
block->size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_block_t *rhs = (block_end_ptr(block) + 1);
|
||||||
|
if(rhs->free == 1)
|
||||||
|
{
|
||||||
|
set_block_next(rhs->prev, rhs->next);
|
||||||
|
set_block_prev(rhs->next, rhs->prev);
|
||||||
|
block->size += rhs->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_block(block, 1, block->size, &heap->head, heap->head.prev);
|
||||||
|
set_block_next(heap->head.prev, block);
|
||||||
|
set_block_prev(&heap->head, block);
|
||||||
|
heap->current_block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_alloc_init(list_alloc_descriptor_t *heap, memory_map_t *map)
|
||||||
|
{
|
||||||
|
heap->head.free = 0;
|
||||||
|
heap->head.size = sizeof(heap->head);
|
||||||
|
heap->head.prev = &heap->head;
|
||||||
|
heap->head.next = &heap->head;
|
||||||
|
heap->current_block = &heap->head;
|
||||||
|
for(int i = 0; i < map->size; i++)
|
||||||
|
{
|
||||||
|
if(map->array[i].type != M_AVAILABLE
|
||||||
|
|| map->array[i].size < MIN_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list_block_t *new_block = ((list_block_t*)map->array[i].location) + 1;
|
||||||
|
set_block(new_block, 1, map->array[i].size - sizeof(list_block_t) * 2, &heap->head, heap->head.prev);
|
||||||
|
set_block_next(heap->head.prev, new_block);
|
||||||
|
set_block_prev(&heap->head, new_block);
|
||||||
|
(new_block - 1)->free = 0;
|
||||||
|
(block_end_ptr(new_block) + 1)->free = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
if BUILD_TESTS
|
if BUILD_TESTS
|
||||||
noinst_PROGRAMS = test_bitmapalloc
|
noinst_PROGRAMS = test_bitmapalloc test_buddyalloc test_listalloc
|
||||||
|
|
||||||
test_bitmapalloc_SOURCES = test_bitmapalloc.c
|
test_bitmapalloc_SOURCES = test_bitmapalloc.c
|
||||||
test_bitmapalloc_LDADD = ../src/libmalloc.a
|
test_bitmapalloc_LDADD = ../src/libmalloc.a
|
||||||
|
|
||||||
|
test_buddyalloc_SOURCES = test_buddyalloc.c
|
||||||
|
test_buddyalloc_LDADD = ../src/libmalloc.a
|
||||||
|
|
||||||
|
test_listalloc_SOURCES = test_listalloc.c
|
||||||
|
test_listalloc_LDADD = ../src/libmalloc.a
|
||||||
endif
|
endif
|
||||||
@@ -78,11 +78,12 @@ void test_heap(unsigned long size, unsigned long block_size, unsigned long bits,
|
|||||||
.cache = heap_cache,
|
.cache = heap_cache,
|
||||||
.cache_capacity = cache_capacity,
|
.cache_capacity = cache_capacity,
|
||||||
.block_bits = bits,
|
.block_bits = bits,
|
||||||
.offset = (unsigned long)heap_data
|
.offset = (unsigned long)heap_data,
|
||||||
|
.mmap = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
memmap_insert_region(&memory_map, 0, size, M_AVAILABLE);
|
memmap_insert_region(&memory_map, 0, size, M_AVAILABLE);
|
||||||
int status = initialize_heap(&heap, &memory_map, NULL);
|
int status = initialize_heap(&heap, &memory_map);
|
||||||
assert(!(!status != !result));
|
assert(!(!status != !result));
|
||||||
if(status)
|
if(status)
|
||||||
{
|
{
|
||||||
|
|||||||
102
tests/test_buddyalloc.c
Normal file
102
tests/test_buddyalloc.c
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#include "libmalloc/buddy_alloc.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct memblock_t
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long location;
|
||||||
|
} memblock_t;
|
||||||
|
|
||||||
|
void print_heap(FILE *file, buddy_descriptor_t *heap)
|
||||||
|
{
|
||||||
|
unsigned long count = 1UL << heap->max_kval;
|
||||||
|
fprintf(file, "heap {\n");
|
||||||
|
fprintf(file, "\t.block_size = %lu\n", heap->block_size);
|
||||||
|
fprintf(file, "\t.max_kval = %lu\n", heap->max_kval);
|
||||||
|
fprintf(file, "\t.offset = %lu\n", heap->offset);
|
||||||
|
fprintf(file, "\t.block_map = {\n");
|
||||||
|
for(unsigned int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
unsigned long linkf_diff = heap->block_map[i].linkf - heap->block_map;
|
||||||
|
unsigned long linkb_diff = heap->block_map[i].linkb - heap->block_map;
|
||||||
|
fprintf(file, "\t\t%u: {.tag = %s, .kval = %lu, .linkf = %li, .linkb = %li}\n",
|
||||||
|
i,
|
||||||
|
heap->block_map[i].tag ? "BLOCK_FREE" : "BLOCK_RESERVED",
|
||||||
|
heap->block_map[i].kval,
|
||||||
|
linkf_diff < count ? linkf_diff : -1,
|
||||||
|
linkb_diff < count ? linkb_diff : -1);
|
||||||
|
}
|
||||||
|
fprintf(file, "\t}\n");
|
||||||
|
fprintf(file, "\t.avail = {\n");
|
||||||
|
for(unsigned int i = 0; i <= heap->max_kval; i++)
|
||||||
|
{
|
||||||
|
fprintf(file, "\t\t%u: {.linkf = %lu, .linkb = %lu}\n",
|
||||||
|
i,
|
||||||
|
heap->avail[i].linkf - heap->block_map,
|
||||||
|
heap->avail[i].linkb - heap->block_map);
|
||||||
|
}
|
||||||
|
fprintf(file, "\t}\n}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned long mem_size;
|
||||||
|
unsigned long block_size;
|
||||||
|
sscanf(argv[1], "%lu", &mem_size);
|
||||||
|
sscanf(argv[2], "%lu", &block_size);
|
||||||
|
|
||||||
|
FILE *out = fopen("debug_output.txt", "w");
|
||||||
|
if(out == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open debug output.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_map_t memory_map = {
|
||||||
|
.array = malloc(sizeof(memory_region_t) * 16),
|
||||||
|
.capacity = 16,
|
||||||
|
.size = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
buddy_descriptor_t heap = {
|
||||||
|
.avail = malloc(sizeof(buddy_block_t) * 20),
|
||||||
|
.block_map = malloc(buddy_map_size(&memory_map, block_size)),
|
||||||
|
.block_size = block_size,
|
||||||
|
.mmap = NULL,
|
||||||
|
.offset = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
memmap_insert_region(&memory_map, 0, mem_size, M_AVAILABLE);
|
||||||
|
if(buddy_alloc_init(&heap, &memory_map))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to initialize buddy allocator.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_heap(out, &heap);
|
||||||
|
|
||||||
|
memblock_t *blocks = calloc(mem_size / block_size, sizeof(memblock_t));
|
||||||
|
|
||||||
|
for(int i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
int index = rand() % (mem_size / block_size);
|
||||||
|
if(blocks[index].size == 0)
|
||||||
|
{
|
||||||
|
blocks[index].size = 1;
|
||||||
|
blocks[index].location = buddy_reserve(&heap, 1);
|
||||||
|
fprintf(out, "RESERVED %lu\n", blocks[index].location / heap.block_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buddy_free(&heap, blocks[index].location);
|
||||||
|
blocks[index].size = 0;
|
||||||
|
fprintf(out, "FREED %lu\n", blocks[index].location / heap.block_size);
|
||||||
|
}
|
||||||
|
print_heap(out, &heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
print_heap(out, &heap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
109
tests/test_listalloc.c
Normal file
109
tests/test_listalloc.c
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#include "libmalloc/list_alloc.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
typedef struct memblock_t
|
||||||
|
{
|
||||||
|
unsigned long size;
|
||||||
|
void *p;
|
||||||
|
} memblock_t;
|
||||||
|
|
||||||
|
void check_block_list(void *heap, unsigned long heap_size, memblock_t *blocks, unsigned long count)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
if (blocks[j].size > 0)
|
||||||
|
{
|
||||||
|
assert(blocks[j].p >= heap);
|
||||||
|
assert(blocks[j].p + blocks[j].size <= heap + heap_size);
|
||||||
|
for (int k = j + 1; k < count; k++)
|
||||||
|
{
|
||||||
|
if (blocks[k].size > 0)
|
||||||
|
{
|
||||||
|
// printf("j = (%p, %lu), k = (%p, %lu)\n", blocks[j].p, blocks[j].size, blocks[k].p, blocks[k].size);
|
||||||
|
assert(blocks[k].p < blocks[j].p || blocks[k].p >= blocks[j].p + blocks[j].size);
|
||||||
|
assert(blocks[j].p < blocks[k].p || blocks[j].p >= blocks[k].p + blocks[k].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
unsigned int max_block_count = 0;
|
||||||
|
unsigned int heap_size = 0;
|
||||||
|
unsigned int passes = 0;
|
||||||
|
|
||||||
|
char c;
|
||||||
|
while((c = getopt(argc, argv, "m:b:c:")) != -1)
|
||||||
|
{
|
||||||
|
if(c == 'm')
|
||||||
|
{
|
||||||
|
sscanf(optarg, "%i", &heap_size);
|
||||||
|
heap_size *= 1024;
|
||||||
|
}
|
||||||
|
else if(c == 'b')
|
||||||
|
{
|
||||||
|
sscanf(optarg, "%i", &max_block_count);
|
||||||
|
}
|
||||||
|
else if(c == 'c')
|
||||||
|
{
|
||||||
|
sscanf(optarg, "%i", &passes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Running test with %i byte heap, %i blocks, %i passes.\n",
|
||||||
|
heap_size, max_block_count, passes);
|
||||||
|
|
||||||
|
void *heap = malloc(heap_size);
|
||||||
|
memory_map_t map = {
|
||||||
|
.array = malloc(sizeof(unsigned long) * 16),
|
||||||
|
.capacity = 16,
|
||||||
|
.size = 0
|
||||||
|
};
|
||||||
|
memmap_insert_region(&map, heap, heap_size, M_AVAILABLE);
|
||||||
|
|
||||||
|
list_alloc_descriptor_t desc;
|
||||||
|
list_alloc_init(&desc, &map);
|
||||||
|
memblock_t *blocks = calloc(max_block_count, sizeof(memblock_t));
|
||||||
|
|
||||||
|
for(int i = 0; i < passes; i++)
|
||||||
|
{
|
||||||
|
int index = rand() % max_block_count;
|
||||||
|
if(blocks[index].size == 0)
|
||||||
|
{
|
||||||
|
unsigned long size = rand() % 65536 + 1;
|
||||||
|
blocks[index].p = list_alloc_reserve(&desc, size);
|
||||||
|
//printf("Reserved %lu bytes.\n", size);
|
||||||
|
if(blocks[index].p != NOMEM)
|
||||||
|
{
|
||||||
|
blocks[index].size = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Out of memory trying to reserve %lu bytes\n", size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list_alloc_free(&desc, blocks[index].p);
|
||||||
|
//printf("Freed %p\n", blocks[index].p);
|
||||||
|
blocks[index].size = 0;
|
||||||
|
}
|
||||||
|
check_block_list(heap, heap_size, blocks, max_block_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < max_block_count; i++)
|
||||||
|
{
|
||||||
|
if(blocks[i].size != 0)
|
||||||
|
{
|
||||||
|
list_alloc_free(&desc, blocks[i].p);
|
||||||
|
blocks[i].size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user