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