Add flag option to not align allocations
This commit is contained in:
@@ -1,15 +1,22 @@
|
||||
|
||||
#pragma once
|
||||
#ifndef ARENA_H
|
||||
#define ARENA_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h> // size_t
|
||||
#include <stddef.h>
|
||||
|
||||
// flags = 0 should be considered the default
|
||||
enum arena_flags {
|
||||
ARENA_GROW = 1 << 0,
|
||||
ARENA_DONTALIGN = 1 << 1,
|
||||
};
|
||||
|
||||
typedef struct arena {
|
||||
char *data;
|
||||
char* data;
|
||||
size_t size;
|
||||
size_t cap;
|
||||
bool grow;
|
||||
char flags;
|
||||
} arena_t;
|
||||
|
||||
/**
|
||||
@@ -32,7 +39,7 @@ int arena_delete(arena_t *a);
|
||||
*/
|
||||
static inline arena_t arena_attach(void *ptr, size_t size)
|
||||
{
|
||||
return (arena_t) { .data = ptr, .size = 0, .cap = size, .grow = false };
|
||||
return (arena_t) { .data = ptr, .size = 0, .cap = size, .flags = 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
6
include/knob.h
Normal file
6
include/knob.h
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define KNOB_MMAP_SIZE (1UL << 40UL)
|
||||
#define KNOB_ALIGNMENT (sizeof(char*))
|
||||
|
||||
39
src/arena.c
39
src/arena.c
@@ -1,5 +1,6 @@
|
||||
|
||||
#include "arena.h"
|
||||
#include "knob.h"
|
||||
|
||||
#include <errno.h> // errno
|
||||
#include <stdbool.h>
|
||||
@@ -8,9 +9,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ARENA_ALIGN (sizeof(void *))
|
||||
#define ARENA_GROW_FACTOR 2UL
|
||||
#define ARENA_OVERCOMMIT_SIZE (1UL << 40UL)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define arena_err(msg) \
|
||||
@@ -21,6 +19,10 @@
|
||||
|
||||
static bool arena_grow(struct arena *a, size_t min_size)
|
||||
{
|
||||
if (!(a->flags & ARENA_GROW)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t new_cap = a->cap * 2;
|
||||
while (new_cap < min_size) {
|
||||
new_cap *= 2;
|
||||
@@ -51,8 +53,7 @@ arena_t arena_new()
|
||||
goto sysconf_failed;
|
||||
}
|
||||
|
||||
void *p = mmap(NULL, ARENA_OVERCOMMIT_SIZE, PROT_NONE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
void *p = mmap(NULL, KNOB_MMAP_SIZE, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
arena_err("mmap");
|
||||
goto mmap_failed;
|
||||
@@ -64,10 +65,20 @@ arena_t arena_new()
|
||||
goto mprotect_failed;
|
||||
}
|
||||
|
||||
return arena_attach(p, size);
|
||||
|
||||
struct arena a = {
|
||||
.data = p,
|
||||
.size = 0,
|
||||
.cap = size,
|
||||
.flags = ARENA_GROW,
|
||||
};
|
||||
|
||||
return a;
|
||||
|
||||
mprotect_failed:
|
||||
munmap(p, ARENA_OVERCOMMIT_SIZE);
|
||||
ok = munmap(p, KNOB_MMAP_SIZE);
|
||||
if (ok == -1) {
|
||||
arena_err("munmap");
|
||||
}
|
||||
mmap_failed:
|
||||
sysconf_failed:
|
||||
return (arena_t) { 0 };
|
||||
@@ -75,14 +86,17 @@ sysconf_failed:
|
||||
|
||||
void* arena_alloc(arena_t *a, size_t size)
|
||||
{
|
||||
size = (size + ARENA_ALIGN - 1) & ~(ARENA_ALIGN - 1); // align
|
||||
// align
|
||||
if (!(a->flags & ARENA_DONTALIGN)) {
|
||||
size = (size + KNOB_ALIGNMENT - 1) & ~(KNOB_ALIGNMENT - 1);
|
||||
}
|
||||
|
||||
void *p = a->data + a->size;
|
||||
a->size += size;
|
||||
if (a->size > a->cap) {
|
||||
if (a->size + size > a->cap) {
|
||||
if (!arena_grow(a, a->size))
|
||||
return NULL;
|
||||
}
|
||||
a->size += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -97,6 +111,9 @@ void* arena_calloc(arena_t *a, size_t nmemb, size_t size)
|
||||
|
||||
int arena_delete(struct arena *a)
|
||||
{
|
||||
if (!(a->flags & ARENA_GROW)) {
|
||||
return -1;
|
||||
}
|
||||
int ok = munmap(a->data, a->cap);
|
||||
if (ok == -1) {
|
||||
arena_err("munmap");
|
||||
|
||||
Reference in New Issue
Block a user