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