never return if h_arena_malloc fails, call errx() or longjmp()

This commit is contained in:
Sven M. Hallberg 2015-10-30 21:23:45 +01:00
parent d5e79aa4cb
commit 9ef70f2f2d
2 changed files with 26 additions and 10 deletions

View file

@ -18,6 +18,7 @@
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <setjmp.h>
#include "hammer.h"
#include "internal.h"
@ -42,6 +43,8 @@ struct HArena_ {
size_t block_size;
size_t used;
size_t wasted;
jmp_buf *except;
};
HArena *h_new_arena(HAllocator* mm__, size_t block_size) {
@ -62,9 +65,26 @@ HArena *h_new_arena(HAllocator* mm__, size_t block_size) {
ret->used = 0;
ret->mm__ = mm__;
ret->wasted = sizeof(struct arena_link) + sizeof(struct HArena_) + block_size;
ret->except = NULL;
return ret;
}
void h_arena_set_except(HArena *arena, jmp_buf *except)
{
arena->except = except;
}
static void *alloc_block(HArena *arena, size_t size)
{
void *block = arena->mm__->alloc(arena->mm__, size);
if (!block) {
if (arena->except)
longjmp(*arena->except, 1);
h_platform_errx(1, "memory allocation failed (%uB requested)\n", (unsigned int)size);
}
return block;
}
void* h_arena_malloc(HArena *arena, size_t size) {
if (size <= arena->head->free) {
// fast path..
@ -79,22 +99,16 @@ void* h_arena_malloc(HArena *arena, size_t size) {
// This involves some annoying casting...
arena->used += size;
arena->wasted += sizeof(struct arena_link*);
void* link = arena->mm__->alloc(arena->mm__, size + sizeof(struct arena_link*));
if (!link) {
// TODO: error-reporting -- let user know that arena link couldn't be allocated
return NULL;
}
void* link = alloc_block(arena, size + sizeof(struct arena_link*));
assert(link != NULL);
memset(link, 0, size + sizeof(struct arena_link*));
*(struct arena_link**)link = arena->head->next;
arena->head->next = (struct arena_link*)link;
return (void*)(((uint8_t*)link) + sizeof(struct arena_link*));
} else {
// we just need to allocate an ordinary new block.
struct arena_link *link = (struct arena_link*)arena->mm__->alloc(arena->mm__, sizeof(struct arena_link) + arena->block_size);
if (!link) {
// TODO: error-reporting -- let user know that arena link couldn't be allocated
return NULL;
}
struct arena_link *link = alloc_block(arena, sizeof(struct arena_link) + arena->block_size);
assert(link != NULL);
memset(link, 0, sizeof(struct arena_link) + arena->block_size);
link->free = arena->block_size - size;
link->used = size;

View file

@ -18,6 +18,7 @@
#ifndef HAMMER_ALLOCATOR__H__
#define HAMMER_ALLOCATOR__H__
#include <sys/types.h>
#include <setjmp.h>
#ifdef __cplusplus
extern "C" {
@ -51,6 +52,7 @@ HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for def
void* h_arena_malloc(HArena *arena, size_t count) ATTR_MALLOC(2);
void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers.
void h_delete_arena(HArena *arena);
void h_arena_set_except(HArena *arena, jmp_buf *except);
typedef struct {
size_t used;