mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 06:58:22 +00:00
alloc: refactor
This commit is contained in:
@@ -230,6 +230,8 @@ int vionet_newdevice(viodevice_t *viodevice) {
|
|||||||
char name[10];
|
char name[10];
|
||||||
snprintf(name, 10, "vionet%d", netdev->id);
|
snprintf(name, 10, "vionet%d", netdev->id);
|
||||||
|
|
||||||
|
netdev->netdev.flags = NETDEV_FLAGS_UP | NETDEV_FLAGS_BROADCAST | NETDEV_FLAGS_RUNNING;
|
||||||
|
|
||||||
__assert(netdev_register((netdev_t *)netdev, name) == 0);
|
__assert(netdev_register((netdev_t *)netdev, name) == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+58
-36
@@ -4,28 +4,37 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <kernel/init.h>
|
#include <kernel/init.h>
|
||||||
|
|
||||||
// each allocation has the following structure:
|
#define DEBUG 1
|
||||||
// ptr: data capacity (allocsizes size)
|
|
||||||
// ptr + sizeof(size_t): current size
|
|
||||||
// ptr + sizeof(size_t) * 2: data
|
|
||||||
// ptr + datasize: poison value
|
|
||||||
|
|
||||||
#define USE_POISON 0
|
|
||||||
#define POISON_VALUE 0xdeadbeefbadc0ffel
|
#define POISON_VALUE 0xdeadbeefbadc0ffel
|
||||||
#define CACHE_COUNT 14
|
#define CACHE_COUNT 14
|
||||||
|
|
||||||
#define CAPACITY_SIZE(cache) cache->size - sizeof(size_t) * 2 - USE_POISON * sizeof(size_t)
|
#if DEBUG == 1
|
||||||
|
typedef struct {
|
||||||
|
size_t capacity;
|
||||||
|
size_t current_size;
|
||||||
|
size_t debug_address;
|
||||||
|
uint8_t data[];
|
||||||
|
} alloc_header_t;
|
||||||
|
#else
|
||||||
|
typedef struct {
|
||||||
|
size_t capacity;
|
||||||
|
size_t current_size;
|
||||||
|
uint8_t data[];
|
||||||
|
} alloc_header_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAPACITY_SIZE(cache) cache->size - sizeof(alloc_header_t) - DEBUG * sizeof(size_t);
|
||||||
|
|
||||||
static size_t allocsizes[CACHE_COUNT] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144};
|
static size_t allocsizes[CACHE_COUNT] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144};
|
||||||
static scache_t *caches[CACHE_COUNT + 5];
|
static scache_t *caches[CACHE_COUNT + 5];
|
||||||
|
|
||||||
static void initarea(scache_t *cache, void *obj, size_t size) {
|
static void initarea(scache_t *cache, void *obj, size_t size) {
|
||||||
size_t *ptr = obj;
|
alloc_header_t *hdr = obj;
|
||||||
*ptr = CAPACITY_SIZE(cache);
|
hdr->capacity = CAPACITY_SIZE(cache);
|
||||||
*(ptr + 1) = size;
|
hdr->current_size = size;
|
||||||
memset(ptr + 2, 0, *ptr);
|
memset(hdr->data, 0, hdr->capacity);
|
||||||
#if USE_POISON == 1
|
#if DEBUG == 1
|
||||||
*((size_t *)((uintptr_t)obj + cache->size - sizeof(size_t))) = POISON_VALUE;
|
*((size_t *)((uintptr_t)obj + cache->size - 1 * sizeof(size_t))) = POISON_VALUE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,61 +42,74 @@ static scache_t *getcachefromsize(size_t size) {
|
|||||||
if (unlikely(size <= 1))
|
if (unlikely(size <= 1))
|
||||||
return caches[0];
|
return caches[0];
|
||||||
|
|
||||||
|
if (unlikely(size > 262144))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
size_t i = 64 - __builtin_clzll(size - 1);
|
size_t i = 64 - __builtin_clzll(size - 1);
|
||||||
return caches[i];
|
return caches[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void *alloc(size_t size) {
|
void *alloc(size_t size) {
|
||||||
scache_t *cache = getcachefromsize(size);
|
scache_t *cache = getcachefromsize(size);
|
||||||
size_t *ret = slab_allocate(cache);
|
if (unlikely(cache == NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
alloc_header_t *ret = slab_allocate(cache);
|
||||||
if (unlikely(ret == NULL))
|
if (unlikely(ret == NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
initarea(cache, ret, size);
|
initarea(cache, ret, size);
|
||||||
#if USE_POISON == 1
|
#if DEBUG == 1
|
||||||
__assert(*ret == CAPACITY_SIZE(cache));
|
__assert(*(size_t *)((uintptr_t)ret + cache->size - sizeof(size_t)) == POISON_VALUE);
|
||||||
|
ret->debug_address = (size_t)__builtin_return_address(0);
|
||||||
#endif
|
#endif
|
||||||
return ret + 2;
|
return ret->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void *ptr) {
|
void free(void *ptr) {
|
||||||
slab_free(getcachefromsize(*((size_t *)ptr - 2)), (size_t *)ptr - 2);
|
alloc_header_t *header = container_of(ptr, alloc_header_t, data);
|
||||||
|
scache_t *cache = getcachefromsize(header->capacity);
|
||||||
|
#if DEBUG == 1
|
||||||
|
__assert(cache);
|
||||||
|
header->current_size = 0;
|
||||||
|
__assert(*(size_t *)((uintptr_t)header + cache->size - sizeof(size_t)) == POISON_VALUE);
|
||||||
|
#endif
|
||||||
|
slab_free(cache, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *realloc(void *ptr, size_t size) {
|
void *realloc(void *ptr, size_t size) {
|
||||||
size_t *start = ptr;
|
alloc_header_t *header = container_of(ptr, alloc_header_t, data);
|
||||||
start -= 2;
|
if (size <= header->capacity) {
|
||||||
size_t currentsize = *(start + 1);
|
header->current_size = size;
|
||||||
if (size <= currentsize) {
|
|
||||||
*(start + 1) = size;
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// grow
|
// grow
|
||||||
scache_t *oldcache = getcachefromsize(*start);
|
scache_t *old_cache = getcachefromsize(header->capacity);
|
||||||
scache_t *newcache = getcachefromsize(size);
|
scache_t *new_cache = getcachefromsize(size);
|
||||||
|
|
||||||
// same allocation
|
// same allocation
|
||||||
if (oldcache == newcache) {
|
if (old_cache == new_cache) {
|
||||||
size_t diff = size - currentsize;
|
size_t diff = size - header->current_size;
|
||||||
memset((void *)((uintptr_t)ptr + currentsize), 0, diff);
|
memset((void *)((uintptr_t)ptr + header->current_size), 0, diff);
|
||||||
*(start + 1) = size;
|
header->current_size = size;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// different allocation
|
// different allocation
|
||||||
size_t *new = slab_allocate(newcache);
|
alloc_header_t *new = slab_allocate(new_cache);
|
||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
initarea(newcache, new, size);
|
|
||||||
memcpy((new + 2), ptr, currentsize);
|
initarea(new_cache, new, size);
|
||||||
slab_free(oldcache, start);
|
memcpy(new->data, ptr, header->current_size);
|
||||||
return new + 2;
|
slab_free(old_cache, header);
|
||||||
|
return new->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void alloc_init() {
|
void alloc_init() {
|
||||||
for (int i = 0; i < CACHE_COUNT; ++i) {
|
for (int i = 0; i < CACHE_COUNT; ++i) {
|
||||||
caches[i + 5] = slab_newcache(allocsizes[i] + sizeof(size_t) * 2 + sizeof(size_t) * USE_POISON, 0, NULL, NULL);
|
caches[i + 5] = slab_newcache(allocsizes[i] + sizeof(alloc_header_t) + sizeof(size_t) * DEBUG, 0, NULL, NULL);
|
||||||
__assert(caches[i + 5]);
|
__assert(caches[i + 5]);
|
||||||
void *p = slab_allocate(caches[i + 5]);
|
void *p = slab_allocate(caches[i + 5]);
|
||||||
__assert(p);
|
__assert(p);
|
||||||
|
|||||||
Reference in New Issue
Block a user