feat: better rtc framework which aims to remove single rtc restrictions.
[lunaix-os.git] / lunaix-os / kernel / mm / cake.c
index 21172865ceaf498509cfde033f0b89e949f56cbd..2a70ab76d823f7d09d6d62cbc08bc6e70f70372b 100644 (file)
@@ -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. :)
  * @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")
 
 
 LOG_MODULE("CAKE")
 
-#define SLAB_SIZE PG_SIZE
+#define CACHE_LINE_SIZE 128
 
 struct cake_pile master_pile;
 
 
 struct cake_pile master_pile;
 
@@ -28,8 +28,11 @@ struct llist_header piles = { .next = &piles, .prev = &piles };
 void*
 __alloc_cake(unsigned int cake_pg)
 {
 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*
 }
 
 struct cake_s*
@@ -37,13 +40,19 @@ __new_cake(struct cake_pile* pile)
 {
     struct cake_s* cake = __alloc_cake(pile->pg_per_cake);
 
 {
     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;
     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;
     }
     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,
 __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 =
     *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 };
 
                                   (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);
 
     llist_init_head(&pile->free);
     llist_init_head(&pile->full);
@@ -78,37 +106,43 @@ __init_pile(struct cake_pile* pile,
 void
 cake_init()
 {
 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*
 }
 
 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);
 
 {
     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;
 }
 
 
     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;
 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);
     }
 
         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++;
     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);
     }
 
         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)
 {
 }
 
 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 };
 
     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;
             }
             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;
             }
         }
                 goto found;
             }
         }
@@ -149,12 +188,12 @@ cake_release(struct cake_pile* pile, void* area)
     return 0;
 
 found:
     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--;
 
     pos->used_pieces--;
     pile->alloced_pieces--;
 
-    llist_delete(pos);
+    llist_delete(&pos->cakes);
     if (!pos->used_pieces) {
         llist_append(&pile->free, &pos->cakes);
     } else {
     if (!pos->used_pieces) {
         llist_append(&pile->free, &pos->cakes);
     } else {
@@ -165,18 +204,7 @@ found:
 }
 
 void
 }
 
 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
 }
\ No newline at end of file