X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/c3f8598f7b2e540e4040955f313a7d05de715c99..f6ab9c9ababa2cf6e5c723b83ffb9362094054e8:/lunaix-os/kernel/mm/cake.c?ds=sidebyside diff --git a/lunaix-os/kernel/mm/cake.c b/lunaix-os/kernel/mm/cake.c index 2117286..2a70ab7 100644 --- a/lunaix-os/kernel/mm/cake.c +++ b/lunaix-os/kernel/mm/cake.c @@ -1,5 +1,5 @@ /** - * @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. :) @@ -19,7 +19,7 @@ LOG_MODULE("CAKE") -#define SLAB_SIZE PG_SIZE +#define CACHE_LINE_SIZE 128 struct cake_pile master_pile; @@ -28,8 +28,11 @@ struct llist_header piles = { .next = &piles, .prev = &piles }; 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(KERNEL_PID, cake_pg, 0); + if (!pa) { + return NULL; + } + return vmap(pa, cake_pg * PG_SIZE, PG_PREM_RW, 0); } struct cake_s* @@ -37,13 +40,19 @@ __new_cake(struct cake_pile* pile) { 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; + + assert(max_piece); - cake->first_piece = - (void*)((uintptr_t)(cake + 1) + max_piece * sizeof(piece_index_t)); + 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; } @@ -58,8 +67,22 @@ void __init_pile(struct cake_pile* pile, char* name, unsigned int piece_size, - unsigned int pg_per_cake) + unsigned int pg_per_cake, + int options) { + if (!pile) { + return; + } + + unsigned int offset = sizeof(long); + + // 默认每块儿蛋糕对齐到地址总线宽度 + 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, .pieces_per_cake = @@ -67,7 +90,12 @@ __init_pile(struct cake_pile* pile, (piece_size + sizeof(piece_index_t)), .pg_per_cake = pg_per_cake }; - strncpy(&pile->pile_name, name, PILE_NAME_MAXLEN); + unsigned int free_list_size = pile->pieces_per_cake * sizeof(piece_index_t); + + 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); llist_init_head(&pile->free); llist_init_head(&pile->full); @@ -78,37 +106,43 @@ __init_pile(struct cake_pile* pile, void cake_init() { - __init_pile(&master_pile, "master", sizeof(master_pile), 1); + __init_pile(&master_pile, "pinkamina", sizeof(master_pile), 1, 0); } struct cake_pile* -cake_new_pile(char* name, unsigned int piece_size, unsigned int pg_per_cake) +cake_new_pile(char* name, + unsigned int piece_size, + unsigned int pg_per_cake, + int options) { struct cake_pile* pile = (struct cake_pile*)cake_grab(&master_pile); - __init_pile(pile, name, piece_size, pg_per_cake); + __init_pile(pile, name, piece_size, pg_per_cake, options); 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++; @@ -121,14 +155,20 @@ found: 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; struct cake_s *pos, *n; struct llist_header* hdrs[2] = { &pile->full, &pile->partial }; @@ -138,9 +178,8 @@ cake_release(struct cake_pile* pile, void* area) if (pos->first_piece > area) { continue; } - area_index = - (uintptr_t)(area - pos->first_piece) / pile->piece_size; - if (area_index < pile->pieces_per_cake) { + piece_index = (ptr_t)(area - pos->first_piece) / pile->piece_size; + if (piece_index < pile->pieces_per_cake) { goto found; } } @@ -149,12 +188,12 @@ cake_release(struct cake_pile* pile, void* area) return 0; found: - pos->free_list[area_index] = pos->next_free; - pos->next_free = area_index; + pos->free_list[piece_index] = pos->next_free; + pos->next_free = piece_index; pos->used_pieces--; pile->alloced_pieces--; - llist_delete(pos); + llist_delete(&pos->cakes); if (!pos->used_pieces) { llist_append(&pile->free, &pos->cakes); } else { @@ -165,18 +204,7 @@ found: } void -cake_stats() +cake_ctor_zeroing(struct cake_pile* pile, void* piece) { - kprintf(KDEBUG "

\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