1 #include "slab.h"
2 #include <common/compiler.h>
3 
4 struct slab kmalloc_cache_group[16] =
5     {
6         {32, 0, 0, NULL, NULL, NULL, NULL},
7         {64, 0, 0, NULL, NULL, NULL, NULL},
8         {128, 0, 0, NULL, NULL, NULL, NULL},
9         {256, 0, 0, NULL, NULL, NULL, NULL},
10         {512, 0, 0, NULL, NULL, NULL, NULL},
11         {1024, 0, 0, NULL, NULL, NULL, NULL}, // 1KB
12         {2048, 0, 0, NULL, NULL, NULL, NULL},
13         {4096, 0, 0, NULL, NULL, NULL, NULL}, // 4KB
14         {8192, 0, 0, NULL, NULL, NULL, NULL},
15         {16384, 0, 0, NULL, NULL, NULL, NULL},
16         {32768, 0, 0, NULL, NULL, NULL, NULL},
17         {65536, 0, 0, NULL, NULL, NULL, NULL},
18         {131072, 0, 0, NULL, NULL, NULL, NULL}, // 128KB
19         {262144, 0, 0, NULL, NULL, NULL, NULL},
20         {524288, 0, 0, NULL, NULL, NULL, NULL},
21         {1048576, 0, 0, NULL, NULL, NULL, NULL}, // 1MB
22 };
23 
24 /**
25  * @brief 创建一个内存池
26  *
27  * @param size 内存池容量大小
28  * @param constructor 构造函数
29  * @param destructor 析构函数
30  * @param arg 参数
31  * @return struct slab* 构建好的内存池对象
32  */
slab_create(ul size,void * (* constructor)(void * vaddr,ul arg),void * (* destructor)(void * vaddr,ul arg),ul arg)33 struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg)
34 {
35     struct slab *slab_pool = (struct slab *)kmalloc(sizeof(struct slab), 0);
36 
37     // BUG
38     if (slab_pool == NULL)
39     {
40         kBUG("slab_create()->kmalloc()->slab == NULL");
41         return NULL;
42     }
43 
44     memset(slab_pool, 0, sizeof(struct slab));
45 
46     slab_pool->size = SIZEOF_LONG_ALIGN(size);
47     slab_pool->count_total_using = 0;
48     slab_pool->count_total_free = 0;
49     // 直接分配cache_pool_entry结构体,避免每次访问都要检测是否为NULL,提升效率
50     slab_pool->cache_pool_entry = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
51 
52     // BUG
53     if (slab_pool->cache_pool_entry == NULL)
54     {
55         kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
56         kfree(slab_pool);
57         return NULL;
58     }
59     memset(slab_pool->cache_pool_entry, 0, sizeof(struct slab_obj));
60 
61     // dma内存池设置为空
62     slab_pool->cache_dma_pool_entry = NULL;
63 
64     // 设置构造及析构函数
65     slab_pool->constructor = constructor;
66     slab_pool->destructor = destructor;
67 
68     list_init(&slab_pool->cache_pool_entry->list);
69 
70     // 分配属于内存池的内存页
71     slab_pool->cache_pool_entry->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
72 
73     // BUG
74     if (slab_pool->cache_pool_entry->page == NULL)
75     {
76         kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
77         kfree(slab_pool->cache_pool_entry);
78         kfree(slab_pool);
79         return NULL;
80     }
81 
82     // page_init(slab_pool->cache_pool_entry->page, PAGE_KERNEL);
83 
84     slab_pool->cache_pool_entry->count_using = 0;
85     slab_pool->cache_pool_entry->count_free = PAGE_2M_SIZE / slab_pool->size;
86 
87     slab_pool->count_total_free = slab_pool->cache_pool_entry->count_free;
88 
89     slab_pool->cache_pool_entry->vaddr = phys_2_virt(slab_pool->cache_pool_entry->page->addr_phys);
90 
91     // bitmap有多少有效位
92     slab_pool->cache_pool_entry->bmp_count = slab_pool->cache_pool_entry->count_free;
93 
94     // 计算位图所占的空间 占用多少byte(按unsigned long大小的上边缘对齐)
95     slab_pool->cache_pool_entry->bmp_len = ((slab_pool->cache_pool_entry->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
96     // 初始化位图
97     slab_pool->cache_pool_entry->bmp = (ul *)kmalloc(slab_pool->cache_pool_entry->bmp_len, 0);
98 
99     // BUG
100     if (slab_pool->cache_pool_entry->bmp == NULL)
101     {
102         kBUG("slab_create()->kmalloc()->slab->cache_pool_entry == NULL");
103         free_pages(slab_pool->cache_pool_entry->page, 1);
104         kfree(slab_pool->cache_pool_entry);
105         kfree(slab_pool);
106         return NULL;
107     }
108     // 将位图清空
109     memset(slab_pool->cache_pool_entry->bmp, 0, slab_pool->cache_pool_entry->bmp_len);
110 
111     return slab_pool;
112 }
113 
114 /**
115  * @brief 销毁内存池
116  * 只有当slab是空的时候才能销毁
117  * @param slab_pool 要销毁的内存池
118  * @return ul
119  *
120  */
slab_destroy(struct slab * slab_pool)121 ul slab_destroy(struct slab *slab_pool)
122 {
123     struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
124     if (slab_pool->count_total_using)
125     {
126         kBUG("slab_cache->count_total_using != 0");
127         return ESLAB_NOTNULL;
128     }
129 
130     struct slab_obj *tmp_slab_obj = NULL;
131     while (!list_empty(&slab_obj_ptr->list))
132     {
133         tmp_slab_obj = slab_obj_ptr;
134         // 获取下一个slab_obj的起始地址
135         slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
136 
137         list_del(&tmp_slab_obj->list);
138 
139         kfree(tmp_slab_obj->bmp);
140 
141         page_clean(tmp_slab_obj->page);
142 
143         free_pages(tmp_slab_obj->page, 1);
144 
145         kfree(tmp_slab_obj);
146     }
147 
148     kfree(slab_obj_ptr->bmp);
149     page_clean(slab_obj_ptr->page);
150     free_pages(slab_obj_ptr->page, 1);
151     kfree(slab_obj_ptr);
152     kfree(slab_pool);
153     return 0;
154 }
155 
156 /**
157  * @brief 分配SLAB内存池中的内存对象
158  *
159  * @param slab_pool slab内存池
160  * @param arg 传递给内存对象构造函数的参数
161  * @return void* 内存空间的虚拟地址
162  */
slab_malloc(struct slab * slab_pool,ul arg)163 void *slab_malloc(struct slab *slab_pool, ul arg)
164 {
165     struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
166     struct slab_obj *tmp_slab_obj = NULL;
167 
168     // slab内存池中已经没有空闲的内存对象,进行扩容
169     if (slab_pool->count_total_free == 0)
170     {
171         tmp_slab_obj = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
172 
173         // BUG
174         if (tmp_slab_obj == NULL)
175         {
176             kBUG("slab_malloc()->kmalloc()->slab->tmp_slab_obj == NULL");
177             return NULL;
178         }
179 
180         memset(tmp_slab_obj, 0, sizeof(struct slab_obj));
181         list_init(&tmp_slab_obj->list);
182 
183         tmp_slab_obj->page = alloc_pages(ZONE_NORMAL, 1, PAGE_KERNEL);
184 
185         // BUG
186         if (tmp_slab_obj->page == NULL)
187         {
188             kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->page == NULL");
189             kfree(tmp_slab_obj);
190             return NULL;
191         }
192 
193         tmp_slab_obj->count_using = 0;
194         tmp_slab_obj->count_free = PAGE_2M_SIZE / slab_pool->size;
195         tmp_slab_obj->vaddr = phys_2_virt(tmp_slab_obj->page->addr_phys);
196         tmp_slab_obj->bmp_count = tmp_slab_obj->count_free;
197         // 计算位图所占的空间 占用多少byte(按unsigned long大小的上边缘对齐)
198         tmp_slab_obj->bmp_len = ((tmp_slab_obj->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
199         tmp_slab_obj->bmp = (ul *)kmalloc(tmp_slab_obj->bmp_len, 0);
200 
201         // BUG
202         if (tmp_slab_obj->bmp == NULL)
203         {
204             kBUG("slab_malloc()->kmalloc()=>tmp_slab_obj->bmp == NULL");
205             free_pages(tmp_slab_obj->page, 1);
206             kfree(tmp_slab_obj);
207             return NULL;
208         }
209 
210         memset(tmp_slab_obj->bmp, 0, tmp_slab_obj->bmp_len);
211 
212         list_add(&slab_pool->cache_pool_entry->list, &tmp_slab_obj->list);
213 
214         slab_pool->count_total_free += tmp_slab_obj->count_free;
215 
216         slab_obj_ptr = tmp_slab_obj;
217     }
218 
219     // 扩容完毕或无需扩容,开始分配内存对象
220     int tmp_md;
221     do
222     {
223         if (slab_obj_ptr->count_free == 0)
224         {
225             slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
226             continue;
227         }
228 
229         for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
230         {
231             // 当前bmp对应的内存对象都已经被分配
232             if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
233             {
234                 i += 63;
235                 continue;
236             }
237 
238             // 第i个内存对象是空闲的
239             tmp_md = i % 64;
240             if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << tmp_md)) == 0)
241             {
242                 // 置位bmp
243                 *(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << tmp_md);
244 
245                 // 更新当前slab对象的计数器
246                 ++(slab_obj_ptr->count_using);
247                 --(slab_obj_ptr->count_free);
248                 // 更新slab内存池的计数器
249                 ++(slab_pool->count_total_using);
250                 --(slab_pool->count_total_free);
251 
252                 if (slab_pool->constructor != NULL)
253                 {
254                     // 返回内存对象指针(要求构造函数返回内存对象指针)
255                     return slab_pool->constructor((char *)slab_obj_ptr->vaddr + slab_pool->size * i, arg);
256                 }
257                 // 返回内存对象指针
258                 else
259                     return (void *)((char *)slab_obj_ptr->vaddr + slab_pool->size * i);
260             }
261         }
262 
263     } while (slab_obj_ptr != slab_pool->cache_pool_entry);
264 
265     // should not be here
266 
267     kBUG("slab_malloc() ERROR: can't malloc");
268 
269     // 释放内存
270     if (tmp_slab_obj != NULL)
271     {
272         list_del(&tmp_slab_obj->list);
273         kfree(tmp_slab_obj->bmp);
274         page_clean(tmp_slab_obj->page);
275         free_pages(tmp_slab_obj->page, 1);
276         kfree(tmp_slab_obj);
277     }
278     return NULL;
279 }
280 
281 /**
282  * @brief 回收slab内存池中的对象
283  *
284  * @param slab_pool 对应的内存池
285  * @param addr 内存对象的虚拟地址
286  * @param arg 传递给虚构函数的参数
287  * @return ul
288  */
slab_free(struct slab * slab_pool,void * addr,ul arg)289 ul slab_free(struct slab *slab_pool, void *addr, ul arg)
290 {
291     struct slab_obj *slab_obj_ptr = slab_pool->cache_pool_entry;
292 
293     do
294     {
295         // 虚拟地址不在当前内存池对象的管理范围内
296         if (!(slab_obj_ptr->vaddr <= addr && addr <= (slab_obj_ptr->vaddr + PAGE_2M_SIZE)))
297         {
298             slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
299         }
300         else
301         {
302 
303             // 计算出给定内存对象是第几个
304             int index = (addr - slab_obj_ptr->vaddr) / slab_pool->size;
305 
306             // 复位位图中对应的位
307             *(slab_obj_ptr->bmp + (index >> 6)) ^= (1UL << index % 64);
308 
309             ++(slab_obj_ptr->count_free);
310             --(slab_obj_ptr->count_using);
311 
312             ++(slab_pool->count_total_free);
313             --(slab_pool->count_total_using);
314 
315             // 有对应的析构函数,调用析构函数
316             if (slab_pool->destructor != NULL)
317                 slab_pool->destructor((char *)slab_obj_ptr->vaddr + slab_pool->size * index, arg);
318 
319             // 当前内存对象池的正在使用的内存对象为0,且内存池的空闲对象大于当前对象池的2倍,则销毁当前对象池,以减轻系统内存压力
320             if ((slab_obj_ptr->count_using == 0) && ((slab_pool->count_total_free >> 1) >= slab_obj_ptr->count_free) && (slab_obj_ptr != slab_pool->cache_pool_entry))
321             {
322 
323                 list_del(&slab_obj_ptr->list);
324                 slab_pool->count_total_free -= slab_obj_ptr->count_free;
325 
326                 kfree(slab_obj_ptr->bmp);
327                 page_clean(slab_obj_ptr->page);
328                 free_pages(slab_obj_ptr->page, 1);
329 
330                 kfree(slab_obj_ptr);
331             }
332         }
333 
334         return 0;
335     } while (slab_obj_ptr != slab_pool->cache_pool_entry);
336 
337     kwarn("slab_free(): address not in current slab");
338     return ENOT_IN_SLAB;
339 }
340 
341 /**
342  * @brief 初始化内存池组
343  * 在初始化通用内存管理单元期间,尚无内存空间分配函数,需要我们手动为SLAB内存池指定存储空间
344  * @return ul
345  */
slab_init()346 ul slab_init()
347 {
348     kinfo("Initializing SLAB...");
349     // 将slab的内存池空间放置在mms的后方
350     ul tmp_addr = memory_management_struct.end_of_struct;
351     for (int i = 0; i < 16; ++i)
352     {
353         io_mfence();
354         spin_init(&kmalloc_cache_group[i].lock);
355         // 将slab内存池对象的空间放置在mms的后面,并且预留4个unsigned long 的空间以防止内存越界
356         kmalloc_cache_group[i].cache_pool_entry = (struct slab_obj *)memory_management_struct.end_of_struct;
357 
358         memory_management_struct.end_of_struct += sizeof(struct slab_obj) + (sizeof(ul) << 2);
359 
360         list_init(&kmalloc_cache_group[i].cache_pool_entry->list);
361 
362         // 初始化内存池对象
363         kmalloc_cache_group[i].cache_pool_entry->count_using = 0;
364         kmalloc_cache_group[i].cache_pool_entry->count_free = PAGE_2M_SIZE / kmalloc_cache_group[i].size;
365         kmalloc_cache_group[i].cache_pool_entry->bmp_len = (((kmalloc_cache_group[i].cache_pool_entry->count_free + sizeof(ul) * 8 - 1) >> 6) << 3);
366         kmalloc_cache_group[i].cache_pool_entry->bmp_count = kmalloc_cache_group[i].cache_pool_entry->count_free;
367 
368         // 在slab对象后方放置bmp
369         kmalloc_cache_group[i].cache_pool_entry->bmp = (ul *)memory_management_struct.end_of_struct;
370 
371         // bmp后方预留4个unsigned long的空间防止内存越界,且按照8byte进行对齐
372         memory_management_struct.end_of_struct = (ul)(memory_management_struct.end_of_struct + kmalloc_cache_group[i].cache_pool_entry->bmp_len + (sizeof(ul) << 2)) & (~(sizeof(ul) - 1));
373         io_mfence();
374         // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
375         memset(kmalloc_cache_group[i].cache_pool_entry->bmp, 0xff, kmalloc_cache_group[i].cache_pool_entry->bmp_len);
376         for (int j = 0; j < kmalloc_cache_group[i].cache_pool_entry->bmp_count; ++j)
377             *(kmalloc_cache_group[i].cache_pool_entry->bmp + (j >> 6)) ^= 1UL << (j % 64);
378 
379         kmalloc_cache_group[i].count_total_using = 0;
380         kmalloc_cache_group[i].count_total_free = kmalloc_cache_group[i].cache_pool_entry->count_free;
381         io_mfence();
382     }
383 
384     struct Page *page = NULL;
385 
386     // 将上面初始化内存池组时,所占用的内存页进行初始化
387     ul tmp_page_mms_end = virt_2_phys(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT;
388 
389     ul page_num = 0;
390     for (int i = PAGE_2M_ALIGN(virt_2_phys(tmp_addr)) >> PAGE_2M_SHIFT; i <= tmp_page_mms_end; ++i)
391     {
392 
393         page = memory_management_struct.pages_struct + i;
394         page_num = page->addr_phys >> PAGE_2M_SHIFT;
395         *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
396         ++page->zone->count_pages_using;
397         io_mfence();
398         --page->zone->count_pages_free;
399         page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
400     }
401     io_mfence();
402 
403     // 为slab内存池对象分配内存空间
404     ul *virt = NULL;
405     for (int i = 0; i < 16; ++i)
406     {
407         // 获取一个新的空页并添加到空页表,然后返回其虚拟地址
408         virt = (ul *)((memory_management_struct.end_of_struct + PAGE_2M_SIZE * i + PAGE_2M_SIZE - 1) & PAGE_2M_MASK);
409 
410         page = Virt_To_2M_Page(virt);
411 
412         page_num = page->addr_phys >> PAGE_2M_SHIFT;
413 
414         *(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
415 
416         ++page->zone->count_pages_using;
417         io_mfence(); // 该位置必须加一个mfence,否则O3优化运行时会报错
418         --page->zone->count_pages_free;
419         page_init(page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
420 
421         kmalloc_cache_group[i].cache_pool_entry->page = page;
422 
423         kmalloc_cache_group[i].cache_pool_entry->vaddr = virt;
424     }
425 
426     kinfo("SLAB initialized successfully!");
427 
428     return 0;
429 }
430 
431 /**
432  * @brief 在kmalloc中创建slab_obj的函数(与slab_malloc()中的类似)
433  *
434  * @param size
435  * @return struct slab_obj* 创建好的slab_obj
436  */
437 
kmalloc_create_slab_obj(ul size)438 struct slab_obj *kmalloc_create_slab_obj(ul size)
439 {
440     struct Page *page = alloc_pages(ZONE_NORMAL, 1, 0);
441 
442     // BUG
443     if (page == NULL)
444     {
445         kBUG("kmalloc_create()->alloc_pages()=>page == NULL");
446         return NULL;
447     }
448 
449     page_init(page, PAGE_KERNEL);
450 
451     ul *vaddr = NULL;
452     ul struct_size = 0;
453     struct slab_obj *slab_obj_ptr;
454 
455     // 根据size大小,选择不同的分支来处理
456     // 之所以选择512byte为分界点,是因为,此时bmp大小刚好为512byte。显而易见,选择过小的话会导致kmalloc函数与当前函数反复互相调用,最终导致栈溢出
457     switch (size)
458     {
459     // ============ 对于size<=512byte的内存池对象,将slab_obj结构体和bmp放置在物理页的内部 ========
460     // 由于这些对象的特征是,bmp占的空间大,而内存块的空间小,这样做的目的是避免再去申请一块内存来存储bmp,减少浪费。
461     case 32:
462     case 64:
463     case 128:
464     case 256:
465     case 512:
466         vaddr = phys_2_virt(page->addr_phys);
467         // slab_obj结构体的大小 (本身的大小+bmp的大小)
468         struct_size = sizeof(struct slab_obj) + PAGE_2M_SIZE / size / 8;
469         // 将slab_obj放置到物理页的末尾
470         slab_obj_ptr = (struct slab_obj *)((unsigned char *)vaddr + PAGE_2M_SIZE - struct_size);
471         slab_obj_ptr->bmp = (void *)slab_obj_ptr + sizeof(struct slab_obj);
472 
473         slab_obj_ptr->count_free = (PAGE_2M_SIZE - struct_size) / size;
474         slab_obj_ptr->count_using = 0;
475         slab_obj_ptr->bmp_count = slab_obj_ptr->count_free;
476         slab_obj_ptr->vaddr = vaddr;
477         slab_obj_ptr->page = page;
478 
479         list_init(&slab_obj_ptr->list);
480 
481         slab_obj_ptr->bmp_len = ((slab_obj_ptr->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
482 
483         // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
484         memset(slab_obj_ptr->bmp, 0xff, slab_obj_ptr->bmp_len);
485 
486         for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
487             *(slab_obj_ptr->bmp + (i >> 6)) ^= 1UL << (i % 64);
488 
489         break;
490     // ================= 较大的size时,slab_obj和bmp不再放置于当前物理页内部 ============
491     // 因为在这种情况下,bmp很短,继续放置在当前物理页内部则会造成可分配的对象少,加剧了内存空间的浪费
492     case 1024: // 1KB
493     case 2048:
494     case 4096: // 4KB
495     case 8192:
496     case 16384:
497     case 32768:
498     case 65536:
499     case 131072: // 128KB
500     case 262144:
501     case 524288:
502     case 1048576: // 1MB
503         slab_obj_ptr = (struct slab_obj *)kmalloc(sizeof(struct slab_obj), 0);
504 
505         slab_obj_ptr->count_free = PAGE_2M_SIZE / size;
506         slab_obj_ptr->count_using = 0;
507         slab_obj_ptr->bmp_count = slab_obj_ptr->count_free;
508 
509         slab_obj_ptr->bmp_len = ((slab_obj_ptr->bmp_count + sizeof(ul) * 8 - 1) >> 6) << 3;
510 
511         slab_obj_ptr->bmp = (ul *)kmalloc(slab_obj_ptr->bmp_len, 0);
512 
513         // @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
514         memset(slab_obj_ptr->bmp, 0xff, slab_obj_ptr->bmp_len);
515         for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
516             *(slab_obj_ptr->bmp + (i >> 6)) ^= 1UL << (i % 64);
517 
518         slab_obj_ptr->vaddr = phys_2_virt(page->addr_phys);
519         slab_obj_ptr->page = page;
520         list_init(&slab_obj_ptr->list);
521         break;
522     // size 错误
523     default:
524         kerror("kamlloc_create(): Wrong size%d", size);
525         free_pages(page, 1);
526         return NULL;
527         break;
528     }
529 
530     return slab_obj_ptr;
531 }
532 
533 /**
534  * @brief 通用内存分配函数
535  *
536  * @param size 要分配的内存大小
537  * @param gfp 内存的flag
538  * @return void* 内核内存虚拟地址
539  */
kmalloc(unsigned long size,gfp_t gfp)540 void *kmalloc(unsigned long size, gfp_t gfp)
541 {
542     void *result = NULL;
543     if (size > 1048576)
544     {
545         kwarn("kmalloc(): Can't alloc such memory: %ld bytes, because it is too large.", size);
546         return NULL;
547     }
548     int index;
549     for (int i = 0; i < 16; ++i)
550     {
551         if (kmalloc_cache_group[i].size >= size)
552         {
553             index = i;
554             break;
555         }
556     }
557     // 对当前内存池加锁
558     spin_lock(&kmalloc_cache_group[index].lock);
559 
560     struct slab_obj *slab_obj_ptr = kmalloc_cache_group[index].cache_pool_entry;
561 
562     // 内存池没有可用的内存对象,需要进行扩容
563     if (unlikely(kmalloc_cache_group[index].count_total_free == 0))
564     {
565         // 创建slab_obj
566         slab_obj_ptr = kmalloc_create_slab_obj(kmalloc_cache_group[index].size);
567 
568         // BUG
569         if (unlikely(slab_obj_ptr == NULL))
570         {
571             kBUG("kmalloc()->kmalloc_create_slab_obj()=>slab == NULL");
572             goto failed;
573         }
574 
575         kmalloc_cache_group[index].count_total_free += slab_obj_ptr->count_free;
576         list_add(&kmalloc_cache_group[index].cache_pool_entry->list, &slab_obj_ptr->list);
577     }
578     else // 内存对象充足
579     {
580         do
581         {
582             // 跳转到下一个内存池对象
583             if (slab_obj_ptr->count_free == 0)
584                 slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
585             else
586                 break;
587         } while (slab_obj_ptr != kmalloc_cache_group[index].cache_pool_entry);
588     }
589     // 寻找一块可用的内存对象
590     int md;
591     for (int i = 0; i < slab_obj_ptr->bmp_count; ++i)
592     {
593 
594         // 当前bmp全部被使用
595         if (*(slab_obj_ptr->bmp + (i >> 6)) == 0xffffffffffffffffUL)
596         {
597             i += 63;
598             continue;
599         }
600         md = i % 64;
601         // 找到相应的内存对象
602         if ((*(slab_obj_ptr->bmp + (i >> 6)) & (1UL << md)) == 0)
603         {
604             *(slab_obj_ptr->bmp + (i >> 6)) |= (1UL << md);
605             ++(slab_obj_ptr->count_using);
606             --(slab_obj_ptr->count_free);
607 
608             --kmalloc_cache_group[index].count_total_free;
609             ++kmalloc_cache_group[index].count_total_using;
610             // 放锁
611             spin_unlock(&kmalloc_cache_group[index].lock);
612             // 返回内存对象
613             result = (void *)((char *)slab_obj_ptr->vaddr + kmalloc_cache_group[index].size * i);
614             goto done;
615         }
616     }
617     goto failed;
618 done:;
619     if (gfp & __GFP_ZERO)
620         memset(result, 0, size);
621     return result;
622 failed:;
623     spin_unlock(&kmalloc_cache_group[index].lock);
624     kerror("kmalloc(): Cannot alloc more memory: %d bytes", size);
625     return NULL;
626 }
627 
628 /**
629  * @brief 通用内存释放函数
630  *
631  * @param address 要释放的内存线性地址
632  * @return unsigned long
633  */
kfree(void * address)634 unsigned long kfree(void *address)
635 {
636     if (unlikely(address == NULL))
637         return 0;
638     struct slab_obj *slab_obj_ptr = NULL;
639 
640     // 将线性地址按照2M物理页对齐, 获得所在物理页的起始线性地址
641     void *page_base_addr = (void *)((ul)address & PAGE_2M_MASK);
642 
643     int index;
644 
645     for (int i = 0; i < 16; ++i)
646     {
647         slab_obj_ptr = kmalloc_cache_group[i].cache_pool_entry;
648 
649         do
650         {
651             // 不属于当前slab_obj的管理范围
652             if (likely(slab_obj_ptr->vaddr != page_base_addr))
653             {
654                 slab_obj_ptr = container_of(list_next(&slab_obj_ptr->list), struct slab_obj, list);
655             }
656             else
657             {
658                 // 对当前内存池加锁
659                 spin_lock(&kmalloc_cache_group[i].lock);
660                 // 计算地址属于哪一个内存对象
661                 index = (address - slab_obj_ptr->vaddr) / kmalloc_cache_group[i].size;
662 
663                 // 复位bmp
664                 *(slab_obj_ptr->bmp + (index >> 6)) ^= 1UL << (index % 64);
665 
666                 ++(slab_obj_ptr->count_free);
667                 --(slab_obj_ptr->count_using);
668                 ++kmalloc_cache_group[i].count_total_free;
669                 --kmalloc_cache_group[i].count_total_using;
670 
671                 // 回收空闲的slab_obj
672                 // 条件:当前slab_obj_ptr的使用为0、总空闲内存对象>=当前slab_obj的总对象的2倍 且当前slab_pool不为起始slab_obj
673                 if ((slab_obj_ptr->count_using == 0) && (kmalloc_cache_group[i].count_total_free >= ((slab_obj_ptr->bmp_count) << 1)) && (kmalloc_cache_group[i].cache_pool_entry != slab_obj_ptr))
674                 {
675                     switch (kmalloc_cache_group[i].size)
676                     {
677                     case 32:
678                     case 64:
679                     case 128:
680                     case 256:
681                     case 512:
682                         // 在这种情况下,slab_obj是被安放在page内部的
683                         list_del(&slab_obj_ptr->list);
684 
685                         kmalloc_cache_group[i].count_total_free -= slab_obj_ptr->bmp_count;
686                         page_clean(slab_obj_ptr->page);
687                         free_pages(slab_obj_ptr->page, 1);
688                         break;
689 
690                     default:
691                         // 在这种情况下,slab_obj是被安放在额外获取的内存对象中的
692                         list_del(&slab_obj_ptr->list);
693                         kmalloc_cache_group[i].count_total_free -= slab_obj_ptr->bmp_count;
694 
695                         kfree(slab_obj_ptr->bmp);
696 
697                         page_clean(slab_obj_ptr->page);
698                         free_pages(slab_obj_ptr->page, 1);
699 
700                         kfree(slab_obj_ptr);
701                         break;
702                     }
703                 }
704                 // 放锁
705                 spin_unlock(&kmalloc_cache_group[i].lock);
706                 return 0;
707             }
708 
709         } while (slab_obj_ptr != kmalloc_cache_group[i].cache_pool_entry);
710     }
711     kBUG("kfree(): Can't free memory. address=%#018lx", address);
712     return ECANNOT_FREE_MEM;
713 }