karlos/include/slab.h

76 lines
2.6 KiB
C

#ifndef KARLOS_SLAB_H
#define KARLOS_SLAB_H
#include <paging.h>
#include <stddef.h>
#include <stdint.h>
// NOTE: currently, this slab allocator should only be used after we have initialized page table.
/// Per-cache descriptor: one cache per object kind
/// Usually this is allocated statically somewhere.
struct slab_cache {
size_t obj_size;
size_t obj_align;
size_t obj_align_shift;
size_t num_slots_per_slab;
struct slab *empty_slabs; // slabs with all slots free
struct slab *partial_slabs; // slabs with some free slots
struct slab *full_slabs; // slabs with no free slots
void (*constructor)(void *obj);
void (*destructor)(void *obj);
// guard against user forgetting to initialize the slab cache
uint64_t magic;
};
/// Per-slab descriptor.
/// Lives directly at the top of the page which it describes.
struct slab {
struct free_stack *free_stack; // stack of free slots in this page
size_t free_count; // how many slots are free right now
struct slab_cache *cache; // backwards link to the containing cache
struct slab *next; // link to next slab_page in cache list
uint64_t magic; // guard against objects outside of slab
};
/// Linking data structure.
struct free_stack {
uint64_t magic; // guard against buffer overflows
struct free_stack *next;
};
/// Initializes the cache, without allocating any memory.
/// `obj_size` must be > 0.
/// constructor and destructor may be `NULL`, in which case allocated objects are not initialized.
// if not specified, default alignment is 8 (suitable for most data structures).
void slab_cache_init(
struct slab_cache *cache,
size_t obj_size,
void (*constructor)(void *),
void (*destructor)(void *));
void slab_cache_init_with_align(
struct slab_cache *cache,
size_t obj_size,
size_t obj_align,
void (*constructor)(void*),
void (*destructor)(void*));
/// Allocates one element from the cache.
/// Returns `NULL` on memory exhaustion.
void *slab_cache_alloc(struct slab_cache *cache);
/// Frees an element previously allocated with `slab_cache_alloc`.
/// Does nothing if `obj` is `NULL`.
void slab_cache_free(void *obj);
/// Cleans up and returns to kernel all empty pages the cache currently holds.
/// Partial and full pages remain untouched.
void slab_cache_return_unused_mem(struct slab_cache *cache);
/// Cleans up and returns to kernel all empty pages the cache currently holds.
/// Panics if the cache is not empty.
void slab_cache_destroy(struct slab_cache *cache);
#endif /* KARLOS_SLAB_H */