PatchworkOS
69292a3
A non-POSIX operating system.
Theme:
Default
Round
Robot
Loading...
Searching...
No Matches
cache.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <
assert.h
>
4
#include <
stddef.h
>
5
#include <
stdint.h
>
6
7
#include <
kernel/cpu/cpu.h
>
8
#include <
kernel/sync/lock.h
>
9
#include <
sys/list.h
>
10
11
typedef
struct
cache
cache_t
;
12
13
/**
14
* @brief Object Cache
15
* @defgroup kernel_mem_cache Cache
16
* @ingroup kernel_mem
17
*
18
* A object cache using CPU local SLAB allocation to improve performance of frequently allocated and deallocated
19
* objects.
20
*
21
* ## Slab Allocation
22
*
23
* The object cache uses slab allocation to allocate memory, each slab consists of a buffer in the below format:
24
*
25
* <div style="text-align: center;">
26
* | Size | Description |
27
* | :------------------------------------ | :------------------ |
28
* | sizeof(cache_slab_t) | Slab metadata |
29
* | (N - 1) * sizeof(cache_bufctl_t) | Buffer control list |
30
* | ... | Padding |
31
* | N * step | Objects |
32
* </div>
33
*
34
* Where N is the number of objects that can fit in the slab given the object size and alignment and the step is the
35
* aligned size of the object.
36
*
37
* ### Buffer Control List
38
*
39
* The buffer control list is an alternative to a intrusive free list, which we cant use as we want free objects to
40
* remain in an initalized state.
41
*
42
* Each index in the buffer control list corresponds to an object in the slab, and contains the index of the next free
43
* object, with the last index in the buffer control list being `CACHE_BUFCTL_END`.
44
*
45
* When an object is allocated we say that the next free object is the object att the current first free objects index,
46
* and when we free an object we set its index in the buffer control list to the current first free object and then
47
* update the first free object to be the freed object.
48
*
49
* In short, the buffer control list acts as a LIFO free list for the objects in the slab.
50
*
51
* ### Minimize CPU Contention
52
*
53
* To minimize CPU contention, each CPU has its own active slab from which it allocates and deallocates objects. It will
54
* continue using its own slab until its empty, at which point it will try to acquire a new slab from the shared cache.
55
*
56
* ### Constructors and Destructors
57
*
58
* Initializing objects, as in setting up their inital state, takes time. To avoid paying this cost on every allocation,
59
* the cache supports optional constructor and destructor functions. Such that when an object is freed, it remains in
60
* its initalized state allowins us to reuse it without reinitialization.
61
*
62
* @see https://en.wikipedia.org/wiki/Slab_allocation for more information.
63
* @see https://www.kernel.org/doc/gorman/html/understand/understand011.html for an explanation of the Linux kernel slab
64
* allocator.
65
*
66
* @{
67
*/
68
69
#define CACHE_LIMIT 16
///< Maximum number of free slabs in a cache.
70
71
typedef
uint16_t
cache_bufctl_t
;
///< Buffer control type.
72
73
#define CACHE_BUFCTL_END (0)
///< End of buffer control list marker.
74
75
#define CACHE_LINE 64
///< Cache line size in bytes.
76
77
#define CACHE_SLAB_PAGES 64
///< Number of pages in a slab.
78
79
/**
80
* @brief Cache slab layout structure.
81
* @struct cache_slab_layout_t
82
*/
83
typedef
struct
84
{
85
uint32_t
start
;
86
uint32_t
step
;
87
uint32_t
stepShift
;
88
uint32_t
amount
;
89
}
cache_slab_layout_t
;
90
91
/**
92
* @brief Cache slab structure.
93
* @struct cache_slab_t
94
*/
95
typedef
struct
ALIGNED(CACHE_LINE)
96
{
97
list_entry_t
entry;
98
cpu_id_t
owner;
99
uint16_t
freeCount;
100
uint16_t
firstFree;
101
lock_t
lock
;
102
cache_t
*
cache
;
103
void
* objects;
104
cache_bufctl_t
bufctl[]
ALIGNED
(
CACHE_LINE
);
105
}
cache_slab_t
;
106
107
static_assert
(
sizeof
(
cache_slab_t
) <= 64,
"size of cache_slab_t is to large for a single cache line"
);
108
109
/**
110
* @brief Per-CPU cache context.
111
* @struct cache_cpu_t
112
*/
113
typedef
struct
ALIGNED(CACHE_LINE)
114
{
115
cache_slab_t
*
active
;
116
}
cache_cpu_t
;
117
118
/**
119
* @brief Cache structure.
120
* @struct cache_t
121
*/
122
typedef
struct
cache
123
{
124
const
char
*
name
;
125
size_t
size
;
126
size_t
alignment
;
127
cache_slab_layout_t
layout
;
128
void (*ctor)(
void
* obj);
129
void (*dtor)(
void
* obj);
130
lock_t
lock
;
131
list_t
free
;
132
list_t
partial
;
133
list_t
full
;
134
uint64_t
freeCount
;
135
cache_cpu_t
cpus[
CPU_MAX
];
136
}
cache_t
;
137
138
/**
139
* @brief Macro to create a cache initializer.
140
*
141
* @param _cache The name of the cache variable.
142
* @param _name The name of the cache, for debugging purposes.
143
* @param _size The size of each object in the cache.
144
* @param _alignment The alignment of each object in the cache.
145
* @param _ctor The constructor function for objects in the cache.
146
* @param _dtor The destructor function for objects in the cache.
147
*/
148
#define CACHE_CREATE(_cache, _name, _size, _alignment, _ctor, _dtor) \
149
{ \
150
.name = (_name), \
151
.size = (_size), \
152
.alignment = (_alignment), \
153
.layout = {0}, \
154
.ctor = (_ctor), \
155
.dtor = (_dtor), \
156
.lock = LOCK_CREATE(), \
157
.free = LIST_CREATE((_cache).free), \
158
.partial = LIST_CREATE((_cache).partial), \
159
.full = LIST_CREATE((_cache).full), \
160
.freeCount = 0, \
161
.cpus = {0}, \
162
}
163
164
/**
165
* @brief Allocate an object from the cache.
166
*
167
* The object will be constructed using the cache's constructor if one is provided.
168
*
169
* @param cache The cache to allocate from.
170
* @return Pointer to the allocated object, or `NULL` on failures.
171
*/
172
void
*
cache_alloc
(
cache_t
*
cache
);
173
174
/**
175
* @brief Free an object back to its cache.
176
*
177
* If the cache is full and a destructor is provided then the object will be destructed.
178
*
179
* @param obj The object to free.
180
*/
181
void
cache_free
(
void
* obj);
182
183
/** @} */
assert.h
cpu.h
cache
static cache_t cache
Definition
dentry.c:132
cpu_id_t
uint16_t cpu_id_t
Type used to identify a CPU.
Definition
cpu.h:65
CPU_MAX
#define CPU_MAX
Maximum number of CPUs supported.
Definition
cpu.h:50
cache_free
void cache_free(void *obj)
Free an object back to its cache.
Definition
cache.c:205
cache_bufctl_t
uint16_t cache_bufctl_t
Buffer control type.
Definition
cache.h:71
CACHE_LINE
#define CACHE_LINE
Cache line size in bytes.
Definition
cache.h:75
cache_alloc
void * cache_alloc(cache_t *cache)
Allocate an object from the cache.
Definition
cache.c:109
ALIGNED
#define ALIGNED(alignment)
GCC aligned attribute.
Definition
defs.h:23
lock
static lock_t lock
Definition
io.c:13
list.h
lock.h
active
static bool active
Definition
rcu.c:13
stddef.h
stdint.h
uint32_t
__UINT32_TYPE__ uint32_t
Definition
stdint.h:15
uint64_t
__UINT64_TYPE__ uint64_t
Definition
stdint.h:17
uint16_t
__UINT16_TYPE__ uint16_t
Definition
stdint.h:13
cache_cpu_t
Per-CPU cache context.
cache_slab_layout_t
Cache slab layout structure.
Definition
cache.h:84
cache_slab_layout_t::step
uint32_t step
Definition
cache.h:86
cache_slab_layout_t::stepShift
uint32_t stepShift
Definition
cache.h:87
cache_slab_layout_t::start
uint32_t start
Definition
cache.h:85
cache_slab_layout_t::amount
uint32_t amount
Definition
cache.h:88
cache_slab_t
Cache slab structure.
cache_t
Cache structure.
Definition
cache.h:123
cache_t::name
const char * name
Definition
cache.h:124
cache_t::free
list_t free
Definition
cache.h:131
cache_t::size
size_t size
Definition
cache.h:125
cache_t::layout
cache_slab_layout_t layout
Definition
cache.h:127
cache_t::lock
lock_t lock
Definition
cache.h:130
cache_t::freeCount
uint64_t freeCount
Definition
cache.h:134
cache_t::alignment
size_t alignment
Definition
cache.h:126
cache_t::full
list_t full
Definition
cache.h:133
cache_t::partial
list_t partial
Definition
cache.h:132
list_entry_t
A entry in a doubly linked list.
Definition
list.h:37
list_t
A doubly linked list.
Definition
list.h:46
lock_t
A simple ticket lock implementation.
Definition
lock.h:44
include
kernel
mem
cache.h
Generated on Thu Jan 15 2026 15:55:29 for PatchworkOS by
1.9.8