Add test and remove code comments
This commit is contained in:
+3
-1
@@ -1,2 +1,4 @@
|
|||||||
test
|
test
|
||||||
test.exe
|
test.exe
|
||||||
|
test2
|
||||||
|
test2.exe
|
||||||
@@ -547,8 +547,12 @@ void *buddy_malloc(struct buddy_alloc *alloc, size_t len)
|
|||||||
void buddy_free(struct buddy_alloc *alloc,
|
void buddy_free(struct buddy_alloc *alloc,
|
||||||
size_t len, void *ptr)
|
size_t len, void *ptr)
|
||||||
{
|
{
|
||||||
if (ptr == NULL || len == 0) return;
|
if (ptr == NULL || len == 0)
|
||||||
if (len > MAX_BLOCK_SIZE) return;
|
return;
|
||||||
|
|
||||||
|
if (len > MAX_BLOCK_SIZE)
|
||||||
|
return;
|
||||||
|
|
||||||
len = normalize_len(len);
|
len = normalize_len(len);
|
||||||
|
|
||||||
if (!is_allocated(alloc, ptr, len))
|
if (!is_allocated(alloc, ptr, len))
|
||||||
@@ -571,83 +575,3 @@ void buddy_free(struct buddy_alloc *alloc,
|
|||||||
len <<= 1;
|
len <<= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
#define ANSI_COLOR_RED "\x1b[31m"
|
|
||||||
#define ANSI_COLOR_GREEN "\x1b[32m"
|
|
||||||
#define ANSI_COLOR_YELLOW "\x1b[33m"
|
|
||||||
#define ANSI_COLOR_BLUE "\x1b[34m"
|
|
||||||
#define ANSI_COLOR_MAGENTA "\x1b[35m"
|
|
||||||
#define ANSI_COLOR_CYAN "\x1b[36m"
|
|
||||||
#define ANSI_COLOR_RESET "\x1b[0m"
|
|
||||||
|
|
||||||
static const char *block_size_label(size_t len)
|
|
||||||
{
|
|
||||||
const char *label = "???";
|
|
||||||
switch (len) {
|
|
||||||
case 1<<12: label = "4K"; break;
|
|
||||||
case 1<<11: label = "2K"; break;
|
|
||||||
case 1<<10: label = "1K"; break;
|
|
||||||
case 1<<9 : label = "512B"; break;
|
|
||||||
case 1<<8 : label = "256B"; break;
|
|
||||||
}
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_lists(struct buddy_alloc *alloc)
|
|
||||||
{
|
|
||||||
for (int i = MIN_BLOCK_LOG2; i <= MAX_BLOCK_LOG2; i++) {
|
|
||||||
fprintf(stderr, "%s = {", block_size_label(1U<<i));
|
|
||||||
struct page *p = alloc->lists[i - MIN_BLOCK_LOG2];
|
|
||||||
while (p) {
|
|
||||||
assert((uintptr_t) p >= (uintptr_t) alloc->base);
|
|
||||||
fprintf(stderr, "%lu", (uintptr_t) p - (uintptr_t) alloc->base);
|
|
||||||
p = p->next;
|
|
||||||
if (p)
|
|
||||||
fprintf(stderr, ", ");
|
|
||||||
}
|
|
||||||
fprintf(stderr, "}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void buddy_dump(struct buddy_alloc *alloc, FILE *out)
|
|
||||||
{
|
|
||||||
fprintf(out, "\n");
|
|
||||||
|
|
||||||
for (int i = 0; i < alloc->num_info; i++) {
|
|
||||||
for (int j = 0; j < 32; j++) {
|
|
||||||
if (alloc->info[i].bits[0] & (1U << j))
|
|
||||||
fprintf(stderr, "1");
|
|
||||||
else
|
|
||||||
fprintf(stderr, "0");
|
|
||||||
}
|
|
||||||
fprintf(stderr, " ");
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
for (int i = 0; i < alloc->num_info; i++) {
|
|
||||||
char *page = alloc->base + i * MAX_BLOCK_SIZE;
|
|
||||||
for (int j = MAX_BLOCK_LOG2; j >= MIN_BLOCK_LOG2; j--) {
|
|
||||||
|
|
||||||
size_t len = 1U << j;
|
|
||||||
|
|
||||||
const char *label = block_size_label(len);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < MAX_BLOCK_SIZE / len; k++) {
|
|
||||||
|
|
||||||
char *ptr = page + k * len;
|
|
||||||
|
|
||||||
fprintf(out, "%-4lX ", (uintptr_t) ptr - (uintptr_t) alloc->base);
|
|
||||||
|
|
||||||
for (int q = 0; q < MAX_BLOCK_LOG2 - j; q++)
|
|
||||||
fprintf(out, " ");
|
|
||||||
|
|
||||||
if (is_allocated(alloc, ptr, len))
|
|
||||||
fprintf(out, ANSI_COLOR_GREEN "%s - allocated\n" ANSI_COLOR_RESET, label);
|
|
||||||
else
|
|
||||||
fprintf(out, "%s - free\n", label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define BUDDY_ALLOC_MAX_BLOCK_LOG2 12
|
#define BUDDY_ALLOC_MAX_BLOCK_LOG2 13
|
||||||
#define BUDDY_ALLOC_MIN_BLOCK_LOG2 8
|
#define BUDDY_ALLOC_MIN_BLOCK_LOG2 3
|
||||||
|
|
||||||
|
_Static_assert(BUDDY_ALLOC_MIN_BLOCK_LOG2 <= BUDDY_ALLOC_MAX_BLOCK_LOG2);
|
||||||
|
_Static_assert(BUDDY_ALLOC_MIN_BLOCK_LOG2 > 2);
|
||||||
|
|
||||||
#define BUDDY_ALLOC_NUM_LISTS (BUDDY_ALLOC_MAX_BLOCK_LOG2 - BUDDY_ALLOC_MIN_BLOCK_LOG2 + 1)
|
#define BUDDY_ALLOC_NUM_LISTS (BUDDY_ALLOC_MAX_BLOCK_LOG2 - BUDDY_ALLOC_MIN_BLOCK_LOG2 + 1)
|
||||||
|
|
||||||
/*
|
// To keep track of the allocation state of a page,
|
||||||
* To keep track of the allocation state of a page,
|
// we need one bit for each possible block that can
|
||||||
* we need one bit for each possible block that can
|
// be made out of it. For instance, if the page can
|
||||||
* be made out of it. For instance, if the page can
|
// only be allocated in its entirety, 1 bit is required.
|
||||||
* only be allocated in its entirety, 1 bit is required.
|
// If the blocks halfs can be allocated too, 3 bits
|
||||||
* If the blocks halfs can be allocated too, 3 bits
|
// are required: 1 for the page, 1 for the frist half
|
||||||
* are required: 1 for the page, 1 for the frist half
|
// and 1 for the second half. Allowing the allocation
|
||||||
* and 1 for the second half. Allowing the allocation
|
// of page quarters requires 4 more bits, for a total
|
||||||
* of page quarters requires 4 more bits, for a total
|
// of 7. In general, if we allow splitting a page N
|
||||||
* of 7. In general, if we allow splitting a page N
|
// times (N=0 means only the entire page can be allocated),
|
||||||
* times (N=0 means only the entire page can be allocated),
|
// then 2^(N+1)-1 bits are necessary.
|
||||||
* then 2^(N+1)-1 bits are necessary.
|
|
||||||
*/
|
|
||||||
#define BUDDY_ALLOC_BITS_PER_PAGE ((1U << (BUDDY_ALLOC_NUM_LISTS)) - 1)
|
#define BUDDY_ALLOC_BITS_PER_PAGE ((1U << (BUDDY_ALLOC_NUM_LISTS)) - 1)
|
||||||
#define BUDDY_ALLOC_WORDS_PER_PAGE ((BUDDY_ALLOC_BITS_PER_PAGE + 31) / 32)
|
#define BUDDY_ALLOC_WORDS_PER_PAGE ((BUDDY_ALLOC_BITS_PER_PAGE + 31) / 32)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
all:
|
all:
|
||||||
gcc test.c buddy.c -o test -Wall -Wextra -ggdb #-fsanitize=address,undefined
|
gcc test.c buddy.c -o test -Wall -Wextra -ggdb #-fsanitize=address,undefined
|
||||||
|
gcc test2.c buddy.c -o test2 -Wall -Wextra -ggdb
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "buddy.h"
|
||||||
|
|
||||||
|
#define NUM_PAGES 16
|
||||||
|
|
||||||
|
#define MIN_ALLOC_SIZE (1U << BUDDY_ALLOC_MIN_BLOCK_LOG2)
|
||||||
|
#define PAGE_SIZE (1U << BUDDY_ALLOC_MAX_BLOCK_LOG2)
|
||||||
|
#define POOL_SIZE (NUM_PAGES * PAGE_SIZE)
|
||||||
|
#define MAX_ALLOCS (POOL_SIZE / MIN_ALLOC_SIZE)
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
_Alignas(PAGE_SIZE) char mem[POOL_SIZE];
|
||||||
|
struct page_info info[NUM_PAGES];
|
||||||
|
struct buddy_alloc alloc = buddy_startup(mem, POOL_SIZE, info, NUM_PAGES);
|
||||||
|
|
||||||
|
void *allocs[MAX_ALLOCS];
|
||||||
|
|
||||||
|
size_t performed = 0;
|
||||||
|
for (size_t i = 0; i < MAX_ALLOCS; i++) {
|
||||||
|
void *ptr = buddy_malloc(&alloc, MIN_ALLOC_SIZE);
|
||||||
|
if (ptr == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
performed++;
|
||||||
|
|
||||||
|
allocs[i] = ptr;
|
||||||
|
|
||||||
|
*(size_t*) ptr = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (performed == MAX_ALLOCS) {
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_ALLOCS; i++) {
|
||||||
|
if (*(size_t*) allocs[i] != i)
|
||||||
|
fprintf(stderr, "%p allocated twice!\n", allocs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_ALLOCS; i++) {
|
||||||
|
buddy_free(&alloc, MIN_ALLOC_SIZE, allocs[MAX_ALLOCS-i-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
performed = 0;
|
||||||
|
for (size_t i = 0; i < MAX_ALLOCS; i++) {
|
||||||
|
void *ptr = buddy_malloc(&alloc, MIN_ALLOC_SIZE);
|
||||||
|
performed++;
|
||||||
|
|
||||||
|
allocs[i] = ptr;
|
||||||
|
|
||||||
|
*(size_t*) ptr = i + MAX_ALLOCS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_ALLOCS; i++) {
|
||||||
|
if (*(size_t*) allocs[i] != MAX_ALLOCS + i)
|
||||||
|
fprintf(stderr, "%p reallocation error!\n", allocs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "performed=%lu, expected=%u\n", performed, MAX_ALLOCS);
|
||||||
|
|
||||||
|
buddy_cleanup(&alloc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user