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