HelenOS sources
This source file includes following definitions.
- malloc_init
- _check_sizes
- cache_for_size
- mem_alloc
- mem_realloc
- mem_free
- malloc
- free
- realloc
#include <stdalign.h>
#include <stddef.h>
#include <stdlib.h>
#include <align.h>
#include <bitops.h>
#include <mm/slab.h>
#include <memw.h>
#include <main/main.h>
#include <macros.h>
#define SLAB_MIN_MALLOC_W 4
#define SLAB_MAX_MALLOC_W 22
static slab_cache_t *malloc_caches[SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1];
static const char *malloc_names[] = {
"malloc-16",
"malloc-32",
"malloc-64",
"malloc-128",
"malloc-256",
"malloc-512",
"malloc-1K",
"malloc-2K",
"malloc-4K",
"malloc-8K",
"malloc-16K",
"malloc-32K",
"malloc-64K",
"malloc-128K",
"malloc-256K",
"malloc-512K",
"malloc-1M",
"malloc-2M",
"malloc-4M"
};
void malloc_init(void)
{
size_t i;
size_t size;
for (i = 0, size = (1 << SLAB_MIN_MALLOC_W);
i < (SLAB_MAX_MALLOC_W - SLAB_MIN_MALLOC_W + 1);
i++, size <<= 1) {
malloc_caches[i] = slab_cache_create(malloc_names[i], size, 0,
NULL, NULL, SLAB_CACHE_MAGDEFERRED);
}
}
static void _check_sizes(size_t *alignment, size_t *size)
{
assert(size);
assert(alignment);
if (*size == 0)
*size = 1;
assert(ispwr2(*alignment));
assert(*alignment <= PAGE_SIZE);
if (*alignment < alignof(max_align_t))
*alignment = alignof(max_align_t);
*size = ALIGN_UP(*size, *alignment);
if (*size < (1 << SLAB_MIN_MALLOC_W))
*size = (1 << SLAB_MIN_MALLOC_W);
}
static slab_cache_t *cache_for_size(size_t size)
{
assert(size > 0);
assert(size <= (1 << SLAB_MAX_MALLOC_W));
size_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
assert(idx < sizeof(malloc_caches) / sizeof(malloc_caches[0]));
slab_cache_t *cache = malloc_caches[idx];
assert(cache != NULL);
return cache;
}
static void *mem_alloc(size_t, size_t) __attribute__((malloc));
static void *mem_alloc(size_t alignment, size_t size)
{
_check_sizes(&alignment, &size);
if (size > (1 << SLAB_MAX_MALLOC_W)) {
assert(size <= (1 << SLAB_MAX_MALLOC_W));
}
return slab_alloc(cache_for_size(size), FRAME_ATOMIC);
}
static void *mem_realloc(void *old_ptr, size_t alignment, size_t old_size,
size_t new_size)
{
assert(old_ptr);
_check_sizes(&alignment, &old_size);
_check_sizes(&alignment, &new_size);
assert(new_size <= (1 << SLAB_MAX_MALLOC_W));
slab_cache_t *old_cache = cache_for_size(old_size);
slab_cache_t *new_cache = cache_for_size(new_size);
if (old_cache == new_cache)
return old_ptr;
void *new_ptr = slab_alloc(new_cache, FRAME_ATOMIC);
if (!new_ptr)
return NULL;
memcpy(new_ptr, old_ptr, min(old_size, new_size));
slab_free(old_cache, old_ptr);
return new_ptr;
}
static void mem_free(void *ptr, size_t alignment, size_t size)
{
if (!ptr)
return;
_check_sizes(&alignment, &size);
if (size > (1 << SLAB_MAX_MALLOC_W)) {
assert(size <= (1 << SLAB_MAX_MALLOC_W));
}
return slab_free(cache_for_size(size), ptr);
}
static const size_t _offset = ALIGN_UP(sizeof(size_t), alignof(max_align_t));
void *malloc(size_t size)
{
if (size + _offset < size)
return NULL;
void *obj = mem_alloc(alignof(max_align_t), size + _offset) + _offset;
((size_t *) obj)[-1] = size;
return obj;
}
void free(void *obj)
{
size_t size = ((size_t *) obj)[-1];
mem_free(obj - _offset, alignof(max_align_t), size + _offset);
}
void *realloc(void *old_obj, size_t new_size)
{
if (new_size == 0)
new_size = 1;
if (!old_obj)
return malloc(new_size);
size_t old_size = ((size_t *) old_obj)[-1];
void *new_obj = mem_realloc(old_obj - _offset, alignof(max_align_t),
old_size + _offset, new_size + _offset) + _offset;
if (!new_obj)
return NULL;
((size_t *) new_obj)[-1] = new_size;
return new_obj;
}
HelenOS homepage, sources at GitHub