slab: simple test for custom alignment and unaligned size
This commit is contained in:
parent
d256e462f8
commit
c8533c8387
4 changed files with 88 additions and 8 deletions
6
Makefile
6
Makefile
|
|
@ -105,6 +105,12 @@ build/tests/test_tlsf: tests/test_tlsf.c $(TEST_TLSF_DEPS) build/tests
|
|||
@"$(CC)" $(CFLAGS) -c -o $@.o $< $(CPPFLAGS)
|
||||
@"$(CC)" -o $@ $@.o $(TEST_TLSF_DEPS)
|
||||
|
||||
TEST_SLAB_DEPS=build/src/test.o build/src/x86_64/address.o build/src/slab.o
|
||||
build/tests/test_slab: tests/test_slab.c $(TEST_SLAB_DEPS) build/tests
|
||||
@printf "CC %s\n" $@
|
||||
@"$(CC)" $(CFLAGS) -c -o $@.o $< $(CPPFLAGS)
|
||||
@"$(CC)" -o $@ $@.o $(TEST_SLAB_DEPS)
|
||||
|
||||
build/tests:
|
||||
mkdir -p $@
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
/// Usually this is allocated statically somewhere.
|
||||
struct slab_cache {
|
||||
size_t obj_size;
|
||||
size_t obj_size_align8;
|
||||
size_t obj_align;
|
||||
size_t obj_align_shift;
|
||||
size_t num_slots_per_slab;
|
||||
|
|
|
|||
15
src/slab.c
15
src/slab.c
|
|
@ -23,7 +23,8 @@ void slab_cache_init_with_align(
|
|||
ASSERT(obj_align > 0);
|
||||
ASSERT(IS_POWER_OF_2(obj_align));
|
||||
|
||||
cache->obj_size = obj_size,
|
||||
cache->obj_size = obj_size;
|
||||
cache->obj_size_align8 = ROUND_UP_8(obj_size);
|
||||
cache->obj_align = obj_align;
|
||||
size_t obj_align_shift = LOG2(obj_align);
|
||||
cache->obj_align_shift = obj_align_shift;
|
||||
|
|
@ -69,18 +70,17 @@ bool slab_cache_new_slab(struct slab_cache *cache) {
|
|||
|
||||
// build the free-slot stack in the bytes after the header
|
||||
raw += sizeof(struct slab);
|
||||
size_t obj_size_align8 = ROUND_UP_8(cache->obj_size);
|
||||
struct free_stack *head = NULL;
|
||||
|
||||
for (size_t i = 0; i < cache->num_slots_per_slab; i++) {
|
||||
raw = (uint8_t*)ROUND_UP(raw, cache->obj_align_shift);
|
||||
uint8_t *end_of_obj = raw + obj_size_align8 + sizeof(struct free_stack);
|
||||
uint8_t *end_of_obj = raw + cache->obj_size_align8 + sizeof(struct free_stack);
|
||||
ASSERT(end_of_obj < page_end);
|
||||
|
||||
if (cache->constructor) {
|
||||
cache->constructor(raw);
|
||||
}
|
||||
raw += obj_size_align8;
|
||||
raw += cache->obj_size_align8;
|
||||
struct free_stack *stack = (struct free_stack *)raw;
|
||||
stack->magic = SLOT_MAGIC_FREE;
|
||||
stack->next = head;
|
||||
|
|
@ -111,7 +111,7 @@ static void *slab_obj_alloc(struct slab *slab) {
|
|||
// move to beginning of object
|
||||
ASSERT(free->magic == SLOT_MAGIC_FREE);
|
||||
free->magic = SLOT_MAGIC_OCCUPIED;
|
||||
return (char*)free - slab->cache->obj_size;
|
||||
return (char*)free - slab->cache->obj_size_align8;
|
||||
}
|
||||
|
||||
bool slab_allocation_asserted;
|
||||
|
|
@ -195,7 +195,7 @@ static void slab_obj_free(struct slab *slab, void *obj) {
|
|||
ASSERT(slab->free_count < slab->cache->num_slots_per_slab);
|
||||
ASSERT(PAGE_BASE(obj) == (void*)slab);
|
||||
|
||||
struct free_stack *node = (struct free_stack *)((char*)obj + slab->cache->obj_size);
|
||||
struct free_stack *node = (struct free_stack *)((char*)obj + slab->cache->obj_size_align8);
|
||||
|
||||
// check if `obj` is actually a valid object pointer
|
||||
ASSERT((char*)node + sizeof(struct free_stack) <= (char*)slab + PAGE_SIZE);
|
||||
|
|
@ -219,11 +219,10 @@ static void slab_cache_return_slab_to_kernel(
|
|||
uint8_t * const page_start = raw;
|
||||
uint8_t * const page_end = page_start + PG_SIZE;
|
||||
raw += sizeof(struct slab);
|
||||
size_t obj_size_align8 = ROUND_UP_8(cache->obj_size);
|
||||
|
||||
for (size_t i = 0; i < cache->num_slots_per_slab; i++) {
|
||||
raw = (uint8_t*)ROUND_UP(raw, cache->obj_align_shift);
|
||||
uint8_t *end_of_obj = raw + obj_size_align8 + sizeof(struct free_stack);
|
||||
uint8_t *end_of_obj = raw + cache->obj_size_align8 + sizeof(struct free_stack);
|
||||
ASSERT(end_of_obj < page_end);
|
||||
if (cache->destructor) {
|
||||
cache->destructor(raw);
|
||||
|
|
|
|||
74
tests/test_slab.c
Normal file
74
tests/test_slab.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#define _POSIX_C_SOURCE 200112L
|
||||
#include <stdlib.h>
|
||||
#include "slab.h"
|
||||
#include "test.h"
|
||||
#include "address.h"
|
||||
#include "ram.h"
|
||||
#include "string.h"
|
||||
|
||||
extern uint64_t identity_mapping_start;
|
||||
|
||||
bool ram_alloc_frame(struct ppn *ppn_out, enum frame_size size) {
|
||||
TEST_ASSERT(size == RAM_PAGE_NORMAL);
|
||||
void *addr;
|
||||
TEST_ASSERT(posix_memalign(&addr, 4096, 4096) == 0);
|
||||
*ppn_out = ppn_from_aligned_pa(pa_from_value((uint64_t)addr));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ram_free(struct ppn ppn) {
|
||||
free(ppn_to_pointer(ppn));
|
||||
}
|
||||
|
||||
size_t num_ctor_calls = 0;
|
||||
size_t num_dtor_calls = 0;
|
||||
|
||||
void constructor(void *obj) {
|
||||
TEST_ASSERT(((uint64_t)obj & 0x3f) == 0);
|
||||
uint8_t *p = obj;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
p[i] = i;
|
||||
}
|
||||
num_ctor_calls++;
|
||||
}
|
||||
|
||||
void destructor(void *obj) {
|
||||
TEST_ASSERT(((uint64_t)obj & 0x3f) == 0);
|
||||
num_dtor_calls++;
|
||||
}
|
||||
|
||||
int main() {
|
||||
identity_mapping_start = 0;
|
||||
struct slab_cache cache;
|
||||
TEST_SHOULD_PANIC(slab_cache_alloc(&cache));
|
||||
slab_cache_init_with_align(&cache, 100, 64, constructor, destructor);
|
||||
|
||||
uint8_t *ptr0 = slab_cache_alloc(&cache);
|
||||
TEST_ASSERT(ptr0 != NULL);
|
||||
TEST_ASSERT(((uint64_t)ptr0 & 0x3f) == 0);
|
||||
|
||||
uint8_t *ptr1 = slab_cache_alloc(&cache);
|
||||
TEST_ASSERT(ptr1 != NULL);
|
||||
TEST_ASSERT(((uint64_t)ptr1 & 0x3f) == 0);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
TEST_ASSERT(ptr0[i] == i);
|
||||
TEST_ASSERT(ptr1[i] == i);
|
||||
}
|
||||
|
||||
memset(ptr0, 42, 100);
|
||||
memset(ptr1, 43, 100);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
TEST_ASSERT(ptr0[i] == 42);
|
||||
TEST_ASSERT(ptr1[i] == 43);
|
||||
}
|
||||
|
||||
slab_cache_free(ptr0);
|
||||
slab_cache_free(ptr1);
|
||||
slab_cache_destroy(&cache);
|
||||
|
||||
TEST_ASSERT(num_ctor_calls > 0 && num_ctor_calls == num_dtor_calls);
|
||||
}
|
||||
|
||||
// TODO test where we write past object and then expect panic on free
|
||||
Loading…
Add table
Reference in a new issue