/**
- * @file valloc.c
+ * @file cake.c
* @author Lunaixsky (zelong56@gmail.com)
* @brief A simplified cake(slab) allocator.
* P.s. I call it cake as slab sounds more 'ridge' to me. :)
void*
__alloc_cake(unsigned int cake_pg)
{
- uintptr_t pa = pmm_alloc_cpage(KERNEL_PID, cake_pg, 0);
- return vmm_vmap(pa, cake_pg * PG_SIZE, PG_PREM_RW);
+ ptr_t pa = (ptr_t)pmm_alloc_cpage(cake_pg, 0);
+ if (!pa) {
+ return NULL;
+ }
+ return vmap(pa, cake_pg * PG_SIZE, PG_PREM_RW, 0);
}
struct cake_s*
{
struct cake_s* cake = __alloc_cake(pile->pg_per_cake);
- int max_piece = pile->pieces_per_cake;
+ if (!cake) {
+ return NULL;
+ }
+
+ u32_t max_piece = pile->pieces_per_cake;
- cake->first_piece = (void*)((uintptr_t)cake + pile->offset);
+ assert(max_piece);
+
+ cake->first_piece = (void*)((ptr_t)cake + pile->offset);
cake->next_free = 0;
+ pile->cakes_count++;
- piece_index_t* free_list = &cake->free_list;
+ piece_index_t* free_list = cake->free_list;
for (size_t i = 0; i < max_piece - 1; i++) {
free_list[i] = i + 1;
}
unsigned int pg_per_cake,
int options)
{
+ if (!pile) {
+ return;
+ }
+
unsigned int offset = sizeof(long);
// 默认每块儿蛋糕对齐到地址总线宽度
- if ((options & PILE_CACHELINE)) {
+ if ((options & PILE_ALIGN_CACHE)) {
// 对齐到128字节缓存行大小,主要用于DMA
offset = CACHE_LINE_SIZE;
}
piece_size = ROUNDUP(piece_size, offset);
*pile = (struct cake_pile){ .piece_size = piece_size,
- .cakes_count = 1,
+ .cakes_count = 0,
.pieces_per_cake =
(pg_per_cake * PG_SIZE) /
(piece_size + sizeof(piece_index_t)),
.pg_per_cake = pg_per_cake };
- unsigned int overhead_size =
- sizeof(struct cake_s) + pile->pieces_per_cake * sizeof(piece_index_t);
+ unsigned int free_list_size = pile->pieces_per_cake * sizeof(piece_index_t);
- pile->offset = ROUNDUP(overhead_size, offset);
+ pile->offset = ROUNDUP(sizeof(struct cake_s) + free_list_size, offset);
+ pile->pieces_per_cake -= ICEIL((pile->offset - free_list_size), piece_size);
- strncpy(&pile->pile_name, name, PILE_NAME_MAXLEN);
+ strncpy(pile->pile_name, name, PILE_NAME_MAXLEN);
llist_init_head(&pile->free);
llist_init_head(&pile->full);
return pile;
}
+void
+cake_set_constructor(struct cake_pile* pile, pile_cb ctor)
+{
+ pile->ctor = ctor;
+}
+
void*
cake_grab(struct cake_pile* pile)
{
struct cake_s *pos, *n;
- llist_for_each(pos, n, &pile->partial, cakes)
- {
- if (pos->next_free != EO_FREE_PIECE) {
- goto found;
- }
- }
-
- if (llist_empty(&pile->free)) {
+ if (!llist_empty(&pile->partial)) {
+ pos = list_entry(pile->partial.next, typeof(*pos), cakes);
+ } else if (llist_empty(&pile->free)) {
pos = __new_cake(pile);
} else {
pos = list_entry(pile->free.next, typeof(*pos), cakes);
}
-found:
+ if (!pos)
+ return NULL;
+
piece_index_t found_index = pos->next_free;
pos->next_free = pos->free_list[found_index];
pos->used_pieces++;
pile->alloced_pieces++;
llist_delete(&pos->cakes);
- if (pos->next_free == EO_FREE_PIECE) {
+ if (pos->free_list[pos->next_free] == EO_FREE_PIECE) {
llist_append(&pile->full, &pos->cakes);
} else {
llist_append(&pile->partial, &pos->cakes);
}
- return (void*)((uintptr_t)pos->first_piece +
- found_index * pile->piece_size);
+ void* ptr =
+ (void*)((ptr_t)pos->first_piece + found_index * pile->piece_size);
+
+ if (pile->ctor) {
+ pile->ctor(pile, ptr);
+ }
+
+ return ptr;
}
int
cake_release(struct cake_pile* pile, void* area)
{
- piece_index_t area_index;
+ piece_index_t piece_index;
+ size_t dsize = 0;
struct cake_s *pos, *n;
struct llist_header* hdrs[2] = { &pile->full, &pile->partial };
if (pos->first_piece > area) {
continue;
}
- area_index =
- (uintptr_t)(area - pos->first_piece) / pile->piece_size;
- if (area_index < pile->pieces_per_cake) {
+ dsize = (ptr_t)(area - pos->first_piece);
+ piece_index = dsize / pile->piece_size;
+ if (piece_index < pile->pieces_per_cake) {
goto found;
}
}
return 0;
found:
- pos->free_list[area_index] = pos->next_free;
- pos->next_free = area_index;
+ assert(!(dsize % pile->piece_size));
+ pos->free_list[piece_index] = pos->next_free;
+ pos->next_free = piece_index;
+
+ assert_msg(pos->free_list[piece_index] != pos->next_free, "double free");
+
pos->used_pieces--;
pile->alloced_pieces--;
- llist_delete(pos);
+ llist_delete(&pos->cakes);
if (!pos->used_pieces) {
llist_append(&pile->free, &pos->cakes);
} else {
llist_append(&pile->partial, &pos->cakes);
}
+ *((unsigned int*)area) = DEADCAKE_MARK;
+
return 1;
}
void
-cake_stats()
+cake_ctor_zeroing(struct cake_pile* pile, void* piece)
{
- kprintf(KDEBUG "<name> <cake> <pg/c> <p/c> <alloced>\n");
-
- struct cake_pile *pos, *n;
- llist_for_each(pos, n, &piles, piles)
- {
- kprintf("%s %d %d %d %d\n",
- pos->pile_name,
- pos->cakes_count,
- pos->pg_per_cake,
- pos->pieces_per_cake,
- pos->alloced_pieces);
- }
+ memset(piece, 0, pile->piece_size);
}
\ No newline at end of file