1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#include <mos/lib/structures/list.hpp>
6#include <mos/lib/sync/spinlock.hpp>
7#include <mos/string.hpp>
8#include <mos/string_view.hpp>
9#include <mos/type_utils.hpp>
10#include <stddef.h>
11
12/**
13 * @brief initialise the slab allocator
14 *
15 */
16void slab_init();
17
18/**
19 * @brief Allocate a block of memory from the slab allocator.
20 *
21 * @param size
22 * @return void*
23 */
24void *slab_alloc(size_t size);
25
26/**
27 * @brief Allocate a block of memory from the slab allocator and zero it.
28 *
29 * @param nmemb
30 * @param size
31 * @return void*
32 */
33void *slab_calloc(size_t nmemb, size_t size);
34
35/**
36 * @brief Reallocate a block of memory from the slab allocator.
37 *
38 * @param addr
39 * @param size
40 * @return void*
41 */
42void *slab_realloc(void *addr, size_t size);
43
44/**
45 * @brief Free a block of memory from the slab allocator.
46 *
47 * @param addr
48 */
49void slab_free(const void *addr);
50
51struct slab_t
52{
53 as_linked_list;
54 spinlock_t lock = SPINLOCK_INIT;
55 ptr_t first_free = 0;
56 size_t ent_size = 0;
57 size_t nobjs = 0;
58 mos::string_view name = "<unnamed>";
59 mos::string_view type_name = "<T>";
60};
61
62void slab_register(slab_t *slab);
63void *kmemcache_alloc(slab_t *slab);
64void kmemcache_free(slab_t *slab, const void *addr);
65
66namespace mos
67{
68 template<typename T>
69 struct Slab : public slab_t
70 {
71 constexpr Slab(mos::string_view name = T::type_name, size_t size = sizeof(T), mos::string_view type_name = mos::getTypeName<T>())
72 {
73 this->name = name;
74 this->type_name = type_name;
75 this->ent_size = size;
76 }
77
78 ~Slab() = default;
79
80 template<typename... Args>
81 T *create(Args &&...args)
82 {
83 if (!registered)
84 slab_register(this), registered = true;
85
86 const auto ptr = kmemcache_alloc(this);
87 new (ptr) T(std::forward<Args>(args)...);
88 return static_cast<T *>(ptr);
89 }
90
91 size_t size()
92 {
93 return ent_size;
94 }
95
96 private:
97 bool registered = false;
98 };
99} // namespace mos
100