76 lines
2.6 KiB
C
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 */
|