3 * @author Lunaixsky (zelong56@gmail.com)
4 * @brief A simplified cake(slab) allocator.
5 * P.s. I call it cake as slab sounds more 'ridge' to me. :)
9 * @copyright Copyright (c) 2022
13 #include <klibc/string.h>
14 #include <lunaix/mm/cake.h>
15 #include <lunaix/mm/pmm.h>
16 #include <lunaix/mm/vmm.h>
17 #include <lunaix/spike.h>
18 #include <lunaix/syslog.h>
22 #define SLAB_SIZE PG_SIZE
24 struct cake_pile master_pile;
26 struct llist_header piles = { .next = &piles, .prev = &piles };
29 __alloc_cake(unsigned int cake_pg)
31 uintptr_t pa = pmm_alloc_cpage(KERNEL_PID, cake_pg, 0);
32 return vmm_vmap(pa, cake_pg * PG_SIZE, PG_PREM_RW);
36 __new_cake(struct cake_pile* pile)
38 struct cake_s* cake = __alloc_cake(pile->pg_per_cake);
40 int max_piece = pile->pieces_per_cake;
43 (void*)((uintptr_t)(cake + 1) + max_piece * sizeof(piece_index_t));
46 piece_index_t* free_list = &cake->free_list;
47 for (size_t i = 0; i < max_piece - 1; i++) {
50 free_list[max_piece - 1] = EO_FREE_PIECE;
52 llist_append(&pile->free, &cake->cakes);
58 __init_pile(struct cake_pile* pile,
60 unsigned int piece_size,
61 unsigned int pg_per_cake)
63 *pile = (struct cake_pile){ .piece_size = piece_size,
66 (pg_per_cake * PG_SIZE) /
67 (piece_size + sizeof(piece_index_t)),
68 .pg_per_cake = pg_per_cake };
70 strncpy(&pile->pile_name, name, PILE_NAME_MAXLEN);
72 llist_init_head(&pile->free);
73 llist_init_head(&pile->full);
74 llist_init_head(&pile->partial);
75 llist_append(&piles, &pile->piles);
81 __init_pile(&master_pile, "master", sizeof(master_pile), 1);
85 cake_new_pile(char* name, unsigned int piece_size, unsigned int pg_per_cake)
87 struct cake_pile* pile = (struct cake_pile*)cake_grab(&master_pile);
89 __init_pile(pile, name, piece_size, pg_per_cake);
95 cake_grab(struct cake_pile* pile)
97 struct cake_s *pos, *n;
98 llist_for_each(pos, n, &pile->partial, cakes)
100 if (pos->next_free != EO_FREE_PIECE) {
105 if (llist_empty(&pile->free)) {
106 pos = __new_cake(pile);
108 pos = list_entry(pile->free.next, typeof(*pos), cakes);
112 piece_index_t found_index = pos->next_free;
113 pos->next_free = pos->free_list[found_index];
115 pile->alloced_pieces++;
117 llist_delete(&pos->cakes);
118 if (pos->next_free == EO_FREE_PIECE) {
119 llist_append(&pile->full, &pos->cakes);
121 llist_append(&pile->partial, &pos->cakes);
124 return (void*)((uintptr_t)pos->first_piece +
125 found_index * pile->piece_size);
129 cake_release(struct cake_pile* pile, void* area)
131 piece_index_t area_index;
132 struct cake_s *pos, *n;
133 struct llist_header* hdrs[2] = { &pile->full, &pile->partial };
135 for (size_t i = 0; i < 2; i++) {
136 llist_for_each(pos, n, hdrs[i], cakes)
138 if (pos->first_piece > area) {
142 (uintptr_t)(area - pos->first_piece) / pile->piece_size;
143 if (area_index < pile->pieces_per_cake) {
152 pos->free_list[area_index] = pos->next_free;
153 pos->next_free = area_index;
155 pile->alloced_pieces--;
158 if (!pos->used_pieces) {
159 llist_append(&pile->free, &pos->cakes);
161 llist_append(&pile->partial, &pos->cakes);
170 kprintf(KDEBUG "<name> <cake> <pg/c> <p/c> <alloced>\n");
172 struct cake_pile *pos, *n;
173 llist_for_each(pos, n, &piles, piles)
175 kprintf("%s %d %d %d %d\n",
179 pos->pieces_per_cake,
180 pos->alloced_pieces);