diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-07-10 11:31:46 +0800 |
| commit | e90b72ec3082588b296956730bd2930cf8d5d671 (patch) | |
| tree | 36ff6916af9b4176ea5a9662219d11e721f0b691 /mm/slab.h | |
| parent | 1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff) | |
| download | lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz | |
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'mm/slab.h')
| -rw-r--r-- | mm/slab.h | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/mm/slab.h b/mm/slab.h new file mode 100644 index 0000000..909ee62 --- /dev/null +++ b/mm/slab.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +#pragma once + +/* + * SLUB Allocator — module-private header + * + * SLUB = Simple List of Unfull Blocks. + * Metadata lives in Page descriptors (no per-page Slab header). + * Free object list is embedded inside the objects themselves. + * Per-CPU "active page" eliminates lock contention on the fast path. + * + * Reference: docs/specs/slab.md + */ + +#include <lume/types.h> +#include <lume/config.h> +#include <lume/page.h> +#include <lume/list.h> +#include <kernel/sync/spinlock.h> + +/* Size classes: 8, 16, 32, 64, 128, 256, 512, 1024, 2048 */ +inline constexpr int kNumSizeClasses = 9; +inline constexpr uint32 kSizeClasses[kNumSizeClasses] = { + 8, 16, 32, 64, 128, 256, 512, 1024, 2048 +}; + +/* Per-CPU active slab page pointer */ +struct PerCpuSlab { + Page* active; // Currently used slab page (nullptr if none) +}; + +/* + * KmemCache — manages a pool of fixed-size objects. + * + * Lock contract: + * lock_ protects partial_ list only. + * Per-CPU cpu_slab_ access requires interrupts disabled. + * PMM calls happen outside lock_ to avoid lock ordering issues. + */ +class KmemCache { +public: + KmemCache() = default; + + // Explicit init (Placement New / BSS pattern) + void init(const char* name, uint32 obj_size, uint32 obj_align); + + // Allocate one object. Returns nullptr on OOM. + void* alloc(); + + // Free one object back to its owning page. + void free(void* obj); + + const char* name() const { return name_; } + uint32 obj_size() const { return obj_size_; } + +private: + // Get a partially-filled page from the partial list (lock must be held) + Page* get_partial(); + + // Put a page onto the partial list (lock must be held) + void put_partial(Page* page); + + // Remove a page from the partial list (lock must be held) + void remove_partial(Page* page); + + // Allocate a new page from PMM and format it as a slab + Page* new_slab(); + + Spinlock lock_; // Protects partial_ only + list_node partial_; // Partially-filled slab pages + + PerCpuSlab cpu_slab_[kMaxCpus]; // Per-CPU active page + + const char* name_ = "uninit"; + uint32 obj_size_ = 0; // Aligned object size (bytes) + uint32 obj_align_ = 0; // Alignment requirement + uint32 objs_per_slab_ = 0; // Objects per 4KB page +}; + +/* Global size-class caches */ +extern KmemCache g_size_caches[kNumSizeClasses]; |
