AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
slab.c
Go to the documentation of this file.
1
18
19#include <core/system.h>
20#include <core/panic.h>
21#include <core/string.h>
22
23#include <ds/queue.h>
24#include <mm/buddy.h>
25#include <mm/mm.h>
26#include <mm/pmap.h>
27#include <mm/vm.h>
28
30struct slab {
31 struct slab *next, *prev; /* the type's slabs of this size that have free objects */
33 void *free; /* its free objects, linked through their first word */
34 uint32_t size; /* the size of its objects */
35 uint32_t used; /* how many of them are in use */
36};
37
38/* the objects start after the header, aligned as kmalloc()'s are */
39#define SLAB_HEADER ((sizeof(struct slab) + 15) & ~(size_t) 15)
40#define SLAB_PAGES (ARCH_SLAB_SIZE / PAGE_SIZE)
41
43static size_t slab_first_free;
44
45size_t slab_used; /* bytes of the slabs' pages, for /proc/meminfo */
46
49static int slab_class(size_t size)
50{
51 int class = 0;
52
53 while (((size_t) SLAB_MIN << class) < size)
54 ++class;
55
56 return class;
57}
58
62static struct slab *slab_page_alloc(void)
63{
64 size_t i = slab_first_free;
65
66 while (i < SLAB_PAGES && (slab_map[i / 8] & (1 << (i % 8))))
67 ++i;
68
69 if (i >= SLAB_PAGES)
70 return NULL;
71
72 vaddr_t vaddr = ARCH_SLAB_BASE + i * PAGE_SIZE;
73 struct vm_page *vm_page = mm_page_alloc();
74
75 if (!vm_page)
76 return NULL;
77
78 if (pmap_add(kvm_space.pmap, vaddr, vm_page->paddr, VM_KRW)) {
80 return NULL;
81 }
82
83 slab_map[i / 8] |= 1 << (i % 8);
84 slab_first_free = i + 1;
86
87 return (struct slab *) vaddr;
88}
89
91static void slab_page_free(struct slab *slab)
92{
93 vaddr_t vaddr = (vaddr_t) slab;
94 size_t i = (vaddr - ARCH_SLAB_BASE) / PAGE_SIZE;
96
97 pmap_remove(kvm_space.pmap, vaddr, vaddr + PAGE_SIZE);
100
101 slab_map[i / 8] &= ~(1 << (i % 8));
102
103 if (i < slab_first_free)
104 slab_first_free = i;
105}
106
108static void slab_unlink(struct slab **list, struct slab *slab)
109{
110 if (slab->prev)
111 slab->prev->next = slab->next;
112 else
113 *list = slab->next;
114
115 if (slab->next)
116 slab->next->prev = slab->prev;
117
118 slab->next = slab->prev = NULL;
119}
120
122static void slab_link(struct slab **list, struct slab *slab)
123{
124 slab->prev = NULL;
125 slab->next = *list;
126
127 if (*list)
128 (*list)->prev = slab;
129
130 *list = slab;
131}
132
142void *slab_alloc(size_t size, struct malloc_type *type)
143{
144 int class = slab_class(size);
145 struct slab **list = &type->slabs[class];
146 struct slab *slab = *list;
147
148 if (!slab) {
149 if (!(slab = slab_page_alloc()))
150 return NULL;
151
152 slab->type = type;
153 slab->size = SLAB_MIN << class;
154 slab->used = 0;
155 slab->free = NULL;
156
157 /* every object free, the first one at the head of the list */
158 for (size_t off = PAGE_SIZE - slab->size; off >= SLAB_HEADER; off -= slab->size) {
159 void **obj = (void **) ((char *) slab + off);
160 *obj = slab->free;
161 slab->free = obj;
162 }
163
165 }
166
167 void **obj = slab->free;
168 slab->free = *obj;
169 slab->used++;
170
171 /* the slab is full now: it leaves the list */
172 if (!slab->free)
174
175 type->nr++;
176 type->total += slab->size;
177
178 return obj;
179}
180
187int slab_owns(void *ptr)
188{
189 uintptr_t addr = (uintptr_t) ptr;
190 return addr >= ARCH_SLAB_BASE && addr < ARCH_SLAB_BASE + ARCH_SLAB_SIZE;
191}
192
199void slab_free(void *ptr)
200{
201 struct slab *slab = (struct slab *) PAGE_ALIGN((uintptr_t) ptr);
202 struct malloc_type *type = slab->type;
203 struct slab **list = &type->slabs[slab_class(slab->size)];
204
205 int was_full = !slab->free;
206
207 *(void **) ptr = slab->free;
208 slab->free = ptr;
209 slab->used--;
210
211 type->nr--;
212 type->total -= slab->size;
213
214 if (!slab->used) {
215 if (!was_full)
217
219 } else if (was_full) {
221 }
222}
#define PAGE_SIZE
Definition system.h:7
uint64_t paddr_t
Definition mm.h:39
#define ARCH_SLAB_SIZE
Definition mm.h:18
#define ARCH_SLAB_BASE
Definition mm.h:17
uint64_t vaddr_t
Definition mm.h:40
#define PAGE_ALIGN(ptr)
Definition mm.h:9
struct vm_page * mm_page_alloc(void)
Allocates a free page of physical memory.
Definition mm.c:78
void mm_page_dealloc(paddr_t paddr)
Frees a page of physical memory, back to the zone it came from.
Definition mm.c:103
void slab_free(void *ptr)
Frees an object of a slab.
Definition slab.c:199
int slab_owns(void *ptr)
Says whether an object is a slab's, for kfree().
Definition slab.c:187
void * slab_alloc(size_t size, struct malloc_type *type)
Allocates a small object, from a slab of its malloc type and size class, making a new slab if none ha...
Definition slab.c:142
#define SLAB_MIN
Definition kvmem.h:7
int pmap_add(struct pmap *pmap, vaddr_t va, paddr_t pa, uint32_t flags)
Maps a page in an address space, replacing what was mapped there.
Definition pmap.c:307
paddr_t arch_page_get_mapping(struct pmap *pmap, vaddr_t vaddr)
Finds the page mapped at a virtual address of an address space.
Definition pmap.c:431
void pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva)
Unmaps the pages of a range of an address space, and flushes them from the TLBs that may have them.
Definition pmap.c:337
static void slab_unlink(struct slab **list, struct slab *slab)
Takes slab off a list of slabs with free objects.
Definition slab.c:108
static int slab_class(size_t size)
Returns the size class for objects of size bytes: the smallest power of two from SLAB_MIN that holds ...
Definition slab.c:49
static void slab_link(struct slab **list, struct slab *slab)
Puts slab at the head of a list of slabs with free objects.
Definition slab.c:122
static void slab_page_free(struct slab *slab)
Unmaps a slab's page, and gives it back to the buddy allocator.
Definition slab.c:91
static size_t slab_first_free
Definition slab.c:43
size_t slab_used
Definition slab.c:45
static struct slab * slab_page_alloc(void)
Maps a page of memory at a free page of the slab region, for a new slab.
Definition slab.c:62
#define SLAB_PAGES
Definition slab.c:40
#define SLAB_HEADER
Definition slab.c:39
static uint8_t slab_map[SLAB_PAGES/8]
Definition slab.c:42
#define NULL
Definition stddef.h:27
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
unsigned int uint32_t
Definition stddef.h:22
unsigned char uint8_t
Definition stddef.h:20
A list: its first and last nodes, and how many there are.
Definition list.h:37
A malloc type: what an allocation is for, which /proc/kvmem counts by.
Definition kvmem.h:14
struct slab * slabs[SLAB_CLASSES]
Definition kvmem.h:22
size_t total
Definition kvmem.h:18
size_t nr
Definition kvmem.h:17
A slab's header, at the start of its page.
Definition slab.c:30
uint32_t size
Definition slab.c:34
struct slab * prev
Definition slab.c:31
uint32_t used
Definition slab.c:35
void * free
Definition slab.c:33
struct malloc_type * type
Definition slab.c:32
struct slab * next
Definition slab.c:31
A page of physical memory (pages[] has one for every page of RAM).
Definition vm.h:150
paddr_t paddr
its physical address
Definition vm.h:151
struct pmap * pmap
its page tables (the architecture's)
Definition vm.h:27
struct vm_space kvm_space
Definition vmm.c:17
#define VM_KRW
kernel read/write
Definition vm.h:49