Rewrite everything

This commit is contained in:
Ole Morud
2023-06-03 16:04:24 +02:00
parent f8c0db9937
commit c71788ba72
6 changed files with 64 additions and 101 deletions

View File

@@ -6,8 +6,8 @@ BUILD_DIR := build
BIN_DIR := lib BIN_DIR := lib
TEST_DIR := test TEST_DIR := test
OBJS := $(BUILD_DIR)/arena.o $(BUILD_DIR)/alloc_backend.o OBJS := $(BUILD_DIR)/arena.o
FPIC_OBJS := $(BUILD_DIR)/fpic/arena.o $(BUILD_DIR)/fpic/alloc_backend.o FPIC_OBJS := $(BUILD_DIR)/fpic/arena.o
static : $(BIN_DIR)/libarena.a static : $(BIN_DIR)/libarena.a

View File

@@ -1,9 +0,0 @@
#ifndef ALLOC_BACKEND_H
#define ALLOC_BACKEND_H
#include <stddef.h>
void* call_alloc_backend(size_t size);
#endif

View File

@@ -4,16 +4,17 @@
#include <stddef.h> // ptrdiff_t #include <stddef.h> // ptrdiff_t
typedef unsigned char byte_t;
typedef struct arena { typedef struct arena {
void *begin, size_t next, prev, cap;
*next, void* data;
*prev;
size_t cap;
} __attribute__((aligned(sizeof(void*)))) arena_t; } __attribute__((aligned(sizeof(void*)))) arena_t;
arena_t* arena_new(); arena_t arena_new();
void arena_reset(arena_t* a); void arena_reset(arena_t* a);
void* arena_alloc(arena_t* a, size_t len); void* arena_alloc(arena_t* a, size_t len);
void* arena_calloc(arena_t* a, size_t nmemb, size_t size);
void* arena_realloc_tail(arena_t* a, size_t len); void* arena_realloc_tail(arena_t* a, size_t len);
#endif #endif

View File

@@ -1,29 +0,0 @@
#include "alloc_backend.h"
#define _GNU_SOURCE
#include <sys/mman.h>
/*
* Separate function to make switching
* allocation backend easier
*
* must take size_t size as an argument
* must return NULL on failure
*/
void* call_alloc_backend(size_t size)
{
void* p = mmap(
NULL,
size,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE,
-1, /* man mmap(2): "[...], some implementations require fd to be
-1 if MAP_ANONYMOUS is specified [...]" */
0);
if (p == MAP_FAILED)
return NULL;
return p;
}

View File

@@ -1,77 +1,79 @@
#include "arena.h" #include "arena.h"
#include "alloc_backend.h"
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#define ARENA_SIZE ((size_t)(128 * sysconf(_SC_PAGE_SIZE))) #include <stdio.h>
typedef unsigned char byte; // (sizeof(intptr_t) isn't guaranteed to be the machine word size but on most
// compilers it is)
#define WORD_SIZE (sizeof(intptr_t))
/* #define ARENA_SIZE ((size_t)(1 * sysconf(_SC_PAGE_SIZE)))
* Allocates and returns new arena
*/ struct arena arena_new()
struct arena* arena_new()
{ {
size_t size = ARENA_SIZE; arena_t a = {
.next = 0,
.prev = 0,
.cap = ARENA_SIZE,
.data = malloc(ARENA_SIZE)
};
byte* p = call_alloc_backend(size); if (a.data == NULL)
exit(errno);
if (p == NULL)
return NULL;
arena_t* a = (arena_t*)p;
void* beg = p + sizeof(struct arena);
a->begin = beg;
a->next = beg;
a->prev = beg;
a->cap = size - sizeof(struct arena);
return a; return a;
} }
/* void _arena_realloc_or_panic(arena_t* a, size_t len)
* Frees all memory in arena {
*/ // TODO: gracefully recover.
// although unlikely to be recoverable in most use cases
a->data = realloc(a->data, len);
if (a->data == NULL)
exit(errno);
a->cap = len;
}
void arena_reset(struct arena* a) void arena_reset(struct arena* a)
{ {
a->next = a->begin; a->next = 0;
a->prev = a->begin; a->prev = 0;
} }
/*
* Allocate new memory using arena
*/
void* arena_alloc(struct arena* a, size_t len) void* arena_alloc(struct arena* a, size_t len)
{ {
void* p = a->next; // align len to machine word size
len = (len + WORD_SIZE - 1) & ~(WORD_SIZE - 1);
fprintf(stderr, "allocating %zu bytes\n", len);
if ((byte*)p + len > (byte*)(a->begin) + a->cap) { a->prev = a->next;
errno = ENOMEM; a->next += len;
return NULL;
if (a->next > a->cap)
_arena_realloc_or_panic(a, a->cap * 2);
return (byte_t*)(a->data) + a->prev;
} }
a->next = (byte*)(a->next) + len; void* arena_calloc(struct arena* a, size_t nmemb, size_t size)
a->prev = p; {
void* p = arena_alloc(a, nmemb * size);
memset((byte_t*)(a->data) + a->prev, 0, size);
return p; return p;
} }
/*
* Reallocate last block in arena
*/
void* arena_realloc_tail(struct arena* a, size_t len) void* arena_realloc_tail(struct arena* a, size_t len)
{ {
void* p = a->prev; a->next = a->prev;
if ((byte*)p + len > (byte*)(a->begin) + a->cap) { return arena_alloc(a, len);
errno = ENOMEM;
return NULL;
}
a->next = (byte*)p + len;
return a->prev;
} }

View File

@@ -8,25 +8,23 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static struct arena* default_arena = NULL; static struct arena default_arena = { 0 };
int main() int main()
{ {
default_arena = arena_new(); default_arena = arena_new();
if (default_arena == NULL) { printf("\nAttempt to do allocations of 1 byte, cap is %zu, ", default_arena.cap);
err(errno, "failed to allocate arena");
}
printf("\nAttempt to do `arena->cap` allocations of 1 byte"); size_t i;
for (i = 0; default_arena.next < default_arena.cap; i++) {
for (size_t i = 0; i < default_arena->cap; i++) { char* c = arena_alloc(&default_arena, 1);
char* c = arena_alloc(default_arena, 1);
*c = i & 0xff; *c = i & 0xff;
if (c == NULL) { if (c == NULL) {
err(EXIT_FAILURE, "failed to allocate memory"); err(EXIT_FAILURE, "failed to allocate memory");
} }
} }
printf("did %zu allocations", i);
printf("\n OK"); printf("\n OK");