5191a1af04ab889bcb851baaa295bf512fbff96c
[lunaix-os.git] / lunaix-os / kernel / mm / valloc.c
1 #include <klibc/string.h>
2 #include <lunaix/mm/cake.h>
3 #include <lunaix/mm/valloc.h>
4
5 #define CLASS_LEN(class) (sizeof(class) / sizeof(class[0]))
6
7 static char piles_names[][PILE_NAME_MAXLEN] = {
8     "valloc_8",   "valloc_16",  "valloc_32", "valloc_64", "valloc_128",
9     "valloc_256", "valloc_512", "valloc_1k", "valloc_2k", "valloc_4k"
10 };
11
12 static char piles_names_dma[][PILE_NAME_MAXLEN] = {
13     "valloc_dma_128", "valloc_dma_256", "valloc_dma_512",
14     "valloc_dma_1k",  "valloc_dma_2k",  "valloc_dma_4k"
15 };
16
17 static struct cake_pile* piles[CLASS_LEN(piles_names)];
18 static struct cake_pile* piles_dma[CLASS_LEN(piles_names_dma)];
19
20 void
21 valloc_init()
22 {
23     for (size_t i = 0; i < CLASS_LEN(piles_names); i++) {
24         int size = 1 << (i + 3);
25         piles[i] = cake_new_pile(&piles_names[i], size, size > 1024 ? 4 : 1, 0);
26     }
27
28     // DMA 内存保证128字节对齐
29     for (size_t i = 0; i < CLASS_LEN(piles_names_dma); i++) {
30         int size = 1 << (i + 7);
31         piles_dma[i] = cake_new_pile(
32           &piles_names_dma[i], size, size > 1024 ? 4 : 1, PILE_CACHELINE);
33     }
34 }
35
36 void*
37 __valloc(unsigned int size, struct cake_pile** segregate_list, size_t len)
38 {
39     size_t i = 0;
40     for (; i < len; i++) {
41         if (segregate_list[i]->piece_size >= size) {
42             goto found_class;
43         }
44     }
45
46     return NULL;
47
48 found_class:
49     return cake_grab(segregate_list[i]);
50 }
51
52 void
53 __vfree(void* ptr, struct cake_pile** segregate_list, size_t len)
54 {
55     size_t i = 0;
56     for (; i < len; i++) {
57         if (cake_release(segregate_list[i], ptr)) {
58             return;
59         }
60     }
61 }
62
63 void*
64 valloc(unsigned int size)
65 {
66     return __valloc(size, &piles, CLASS_LEN(piles_names));
67 }
68
69 void*
70 vzalloc(unsigned int size)
71 {
72     void* ptr = __valloc(size, &piles, CLASS_LEN(piles_names));
73     memset(ptr, 0, size);
74     return ptr;
75 }
76
77 void*
78 vcalloc(unsigned int size, unsigned int count)
79 {
80     unsigned int alloc_size;
81     if (__builtin_umul_overflow(size, count, &alloc_size)) {
82         return 0;
83     }
84
85     void* ptr = __valloc(alloc_size, &piles, CLASS_LEN(piles_names));
86     memset(ptr, 0, alloc_size);
87     return ptr;
88 }
89
90 void
91 vfree(void* ptr)
92 {
93     __vfree(ptr, &piles, CLASS_LEN(piles_names));
94 }
95
96 void*
97 valloc_dma(unsigned int size)
98 {
99     return __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma));
100 }
101
102 void*
103 vzalloc_dma(unsigned int size)
104 {
105     void* ptr = __valloc(size, &piles_dma, CLASS_LEN(piles_names_dma));
106     memset(ptr, 0, size);
107     return ptr;
108 }
109
110 void
111 vfree_dma(void* ptr)
112 {
113     __vfree(ptr, &piles_dma, CLASS_LEN(piles_names_dma));
114 }