Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
slab.c
Go to the documentation of this file.
1#include "slab.h"
2#include <type.h>
3
4#include <libk/serial.h>
5#include <str.h>
6
7#include <hal/cpu/paging.h>
8#include <spinlock.h>
9#include <str.h>
11#include <memory/memory_utils.h>
12
13#define MAX_FREED_VADDRS 512
14
15#define DEFAULT_SLAB_ADDR 0xFFFFFF8080000000
17
19
21static size_t freed_vaddr_count = 0;
22
35
43
44void vxCreateSlabCache(struct slab_cache** cache, const char* name,
45 const size_t obj_size, size_t alignment,
46 const uintptr_t virt_addr) {
48 LOG_INFO("SLAB", "created new slab cache '%s' at phys 0x%x", name,
49 phys_addr);
50 uintptr_t vaddr = virt_addr;
51
52 if (virt_addr == 0) {
53 vaddr = get_default_slab_addr();
54 }
55
56 // TODO: map to current active page table
58 0b11);
59 *cache = (struct slab_cache*) vaddr;
60 memset(*cache, 0, sizeof(struct slab_cache));
61
62 if (virt_addr > 0) {
63 (*cache)->default_virt_addr = false;
64 } else {
65 (*cache)->default_virt_addr = true;
66 }
67
68 strcpy((*cache)->name, name);
69 (*cache)->phys_addr = phys_addr;
70 (*cache)->current_virt_addr = vaddr + BLOCK_SIZE;
71 (*cache)->obj_size = obj_size;
72 (*cache)->alignment = alignment;
73
74 size_t actual_size = obj_size;
75 if (actual_size < sizeof(void*)) {
76 actual_size = sizeof(void*);
77 }
78 if (alignment > 0) {
79 actual_size = ALIGN_UP(actual_size, alignment);
80 }
81 (*cache)->actual_obj_size = actual_size;
82
83 (*cache)->slab_size = BLOCK_SIZE; // 4KB for now
84 (*cache)->slabs_full = 0;
85 (*cache)->slabs_partial = 0;
86 (*cache)->slabs_free = 0;
87 (*cache)->total_slabs = 0;
88 (*cache)->total_objects = 0;
89 (*cache)->free_objects = 0;
90 (*cache)->lock = (spinlock_t){0};
91}
92
94 if (cache == NULL) {
95 LOG_ERROR("SLAB", "slab cache is NULL");
96 return NULL;
97 }
98
99 spin_acquire(&cache->lock);
100
101 // // Check if there is a partial slab available
102 struct slab* slab = cache->slabs_partial;
103 if (slab == NULL) {
104 // No partial slab, check for a free slab
105 slab = cache->slabs_free;
106 if (slab == NULL) {
107 // No free slab, create a new one
109 uintptr_t vaddr = cache->current_virt_addr;
110
111 if (cache->default_virt_addr) {
112 vaddr = get_default_slab_addr();
113 } else {
114 cache->current_virt_addr += BLOCK_SIZE;
115 }
116
118 (uintptr_t) phys_addr, 0b11);
119
120 cache->total_slabs++;
121 slab = (struct slab*) vaddr;
123
124 memset(slab, 0, sizeof(struct slab));
125 slab->magic = 0xDEADBEEF;
126 slab->next = cache->slabs_free;
127 slab->first_obj = (void*) ((uintptr_t) slab
128 + sizeof(struct slab));
129
131 (cache->slab_size - sizeof(struct slab))
135
136 // Initialize the free list
138 for (size_t i = 0; i < slab->total_objects - 1; i++) {
139 *(void**) obj =
140 (void*) (obj + cache->actual_obj_size);
141 obj += cache->actual_obj_size;
142 }
143 *(void**) obj = NULL; // Last object points to NULL
144 cache->slabs_free = slab;
145 } // Move slab from free to partial
146 cache->slabs_free = slab->next;
147 slab->next = cache->slabs_partial;
148 cache->slabs_partial = slab;
149
150 } // Allocate object from slab
151 void* obj = slab->free_list;
152 if (obj == NULL) {
153 LOG_ERROR("SLAB",
154 "slab '%s' has no free objects but in partial list!",
155 cache->name);
156 spin_release(&cache->lock);
157 return NULL; // Should not happen
158 }
159 slab->free_list = *(void**) obj;
161 cache->free_objects--;
162 cache->total_objects++;
163 if (slab->free_objects == 0) {
164 // Move slab from partial to full
165 cache->slabs_partial = slab->next;
166 slab->next = cache->slabs_full;
167 cache->slabs_full = slab;
168 }
169
170 spin_release(&cache->lock);
171 return obj;
172}
173
175 if (cache == NULL || *cache == NULL) {
176 return;
177 }
178
179 spin_acquire(&(*cache)->lock);
180
181 struct slab* slab = (*cache)->slabs_full;
182 while (slab) {
183 struct slab* next = slab->next;
184 if (slab->phys_addr)
185 vxPhysBaseFree((void*) slab->phys_addr, 1);
187 (uintptr_t) slab);
188
189 if ((*cache)->default_virt_addr)
191
192 slab = next;
193 }
194
195 slab = (*cache)->slabs_partial;
196 while (slab) {
197 struct slab* next = slab->next;
198 if (slab->phys_addr)
199 vxPhysBaseFree((void*) slab->phys_addr, 1);
201 (uintptr_t) slab);
202
203 if ((*cache)->default_virt_addr)
205
206 slab = next;
207 }
208
209 slab = (*cache)->slabs_free;
210 while (slab) {
211 struct slab* next = slab->next;
212 if (slab->phys_addr)
213 vxPhysBaseFree((void*) slab->phys_addr, 1);
215 (uintptr_t) slab);
216
217 if ((*cache)->default_virt_addr)
219
220 slab = next;
221 }
222
223 uintptr_t phys_addr = (*cache)->phys_addr;
224
225 spin_release(&(*cache)->lock);
226
228 vxPhysBaseFree((void*) phys_addr, 1);
230
231 // Finally, free the cache itself
232 *cache = NULL;
233}
234
235void slab_free(struct slab_cache* cache, void* obj) {
236 if (cache == NULL || obj == NULL) {
237 return;
238 }
239
240 spin_acquire(&cache->lock);
241
242 // Find the slab containing the object
243 struct slab* slab = cache->slabs_full;
244 struct slab* prev = NULL;
245 while (slab) {
246 if ((uintptr_t) obj >= (uintptr_t) slab->first_obj
247 && (uintptr_t) obj
250 * cache->actual_obj_size) {
251 break;
252 }
253 prev = slab;
254 slab = slab->next;
255 }
256
257 if (slab == NULL) {
258 slab = cache->slabs_partial;
259 prev = NULL;
260 while (slab) {
261 if ((uintptr_t) obj >= (uintptr_t) slab->first_obj
262 && (uintptr_t) obj
265 * cache->actual_obj_size) {
266 break;
267 }
268 prev = slab;
269 slab = slab->next;
270 }
271 }
272
273 if (slab == NULL) {
274 spin_release(&cache->lock);
275 return;
276 }
277
278 // Free the object
279 *(void**) obj = slab->free_list;
280 slab->free_list = obj;
282 cache->free_objects++;
283 cache->total_objects--;
284
285 if (slab->free_objects == 1) {
286 // Move slab from full to partial
287 if (prev) {
288 prev->next = slab->next;
289 } else {
290 cache->slabs_full = slab->next;
291 }
292 slab->next = cache->slabs_partial;
293 cache->slabs_partial = slab;
294 } else if (slab->free_objects == slab->total_objects) {
295 // Move slab from partial to free
296 if (prev) {
297 prev->next = slab->next;
298 } else {
299 cache->slabs_partial = slab->next;
300 }
301 slab->next = cache->slabs_free;
302 cache->slabs_free = slab;
303 }
304
305 spin_release(&cache->lock);
306}
kstring name
Definition dentry.h:5
struct cdev * next
Definition dev.h:4
volatile uint64_t addr
Definition e1000.hpp:0
static size_t freed_vaddr_count
Definition kalloc.c:53
static freed_t freed_vaddrs[512]
Definition kalloc.c:52
#define MAX_FREED_VADDRS
Definition kalloc.c:14
#define ALIGN_UP(x, align)
Definition memory_utils.h:6
page_t paging_get_highest_page_map(void)
Definition paging.c:463
void paging_unmap_page(page_t page_dir, uint64_t virt)
Definition paging.c:360
void vxMmap(page_t page_dir, uint64_t virt, uint64_t phys, uint64_t flags)
Definition paging.c:223
void * phys_base_alloc(uint64_t block)
void vxPhysBaseFree(void *ptr, uint64_t size)
#define BLOCK_SIZE
struct process_node cache
Definition process.h:10
struct process * prev
Definition process.h:19
#define LOG_ERROR(mod, fmt,...)
Definition serial.h:25
#define LOG_INFO(mod, fmt,...)
Definition serial.h:20
void * vxSlabAlloc(struct slab_cache *cache)
Definition slab.c:93
void slab_cache_destroy(struct slab_cache **cache)
Definition slab.c:174
static uintptr_t last_slab_addr
Definition slab.c:16
static void push_freed_vaddr(uintptr_t vaddr)
Definition slab.c:36
void slab_free(struct slab_cache *cache, void *obj)
Definition slab.c:235
#define DEFAULT_SLAB_ADDR
Definition slab.c:15
static uintptr_t get_default_slab_addr()
Definition slab.c:23
static spinlock_t slab_global_lock
Definition slab.c:18
void vxCreateSlabCache(struct slab_cache **cache, const char *name, const size_t obj_size, size_t alignment, const uintptr_t virt_addr)
Definition slab.c:44
size_t alignment
Definition slab.h:4
size_t obj_size
Definition slab.h:2
size_t actual_obj_size
Definition slab.h:3
uintptr_t phys_addr
Definition slab.h:6
void spin_acquire(spinlock_t *lock)
Definition spinlock.c:8
void spin_release(spinlock_t *lock)
Definition spinlock.c:19
void strcpy(char *dest, const char *src)
void memset(void *ptr, int value, size_t num)
Definition slab.h:8
void * first_obj
Definition slab.h:11
uintptr_t phys_addr
Definition slab.h:15
size_t total_objects
Definition slab.h:13
size_t free_objects
Definition slab.h:14
void * free_list
Definition slab.h:12
uint32_t magic
Definition slab.h:9
struct slab * next
Definition slab.h:10
#define NULL
Definition type.h:76
unsigned long uintptr_t
Definition type.h:73