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