PatchworkOS  69292a3
A non-POSIX operating system.
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
11typedef 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
71typedef 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 */
90
91/**
92 * @brief Cache slab structure.
93 * @struct cache_slab_t
94 */
95typedef 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;
106
107static_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 */
113typedef struct ALIGNED(CACHE_LINE)
114{
117
118/**
119 * @brief Cache structure.
120 * @struct cache_t
121 */
122typedef struct cache
123{
124 const char* name;
125 size_t size;
126 size_t alignment;
128 void (*ctor)(void* obj);
129 void (*dtor)(void* obj);
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 */
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 */
181void cache_free(void* obj);
182
183/** @} */
static cache_t cache
Definition dentry.c:132
uint16_t cpu_id_t
Type used to identify a CPU.
Definition cpu.h:65
#define CPU_MAX
Maximum number of CPUs supported.
Definition cpu.h:50
void cache_free(void *obj)
Free an object back to its cache.
Definition cache.c:205
uint16_t cache_bufctl_t
Buffer control type.
Definition cache.h:71
#define CACHE_LINE
Cache line size in bytes.
Definition cache.h:75
void * cache_alloc(cache_t *cache)
Allocate an object from the cache.
Definition cache.c:109
#define ALIGNED(alignment)
GCC aligned attribute.
Definition defs.h:23
static lock_t lock
Definition io.c:13
static bool active
Definition rcu.c:13
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
Per-CPU cache context.
Cache slab layout structure.
Definition cache.h:84
uint32_t step
Definition cache.h:86
uint32_t stepShift
Definition cache.h:87
uint32_t start
Definition cache.h:85
uint32_t amount
Definition cache.h:88
Cache slab structure.
Cache structure.
Definition cache.h:123
const char * name
Definition cache.h:124
list_t free
Definition cache.h:131
size_t size
Definition cache.h:125
cache_slab_layout_t layout
Definition cache.h:127
lock_t lock
Definition cache.h:130
uint64_t freeCount
Definition cache.h:134
size_t alignment
Definition cache.h:126
list_t full
Definition cache.h:133
list_t partial
Definition cache.h:132
A entry in a doubly linked list.
Definition list.h:37
A doubly linked list.
Definition list.h:46
A simple ticket lock implementation.
Definition lock.h:44