1 #pragma once
2 
3 #include "mm.h"
4 #include <common/glib.h>
5 #include <common/printk.h>
6 #include <common/kprint.h>
7 #include <common/spinlock.h>
8 
9 #define SIZEOF_LONG_ALIGN(size) ((size + sizeof(long) - 1) & ~(sizeof(long) - 1))
10 #define SIZEOF_INT_ALIGN(size) ((size + sizeof(int) - 1) & ~(sizeof(int) - 1))
11 
12 // SLAB存储池count_using不为空
13 #define ESLAB_NOTNULL 101
14 #define ENOT_IN_SLAB 102     // 地址不在当前slab内存池中
15 #define ECANNOT_FREE_MEM 103 // 无法释放内存
16 
17 struct slab_obj
18 {
19     struct List list;
20     // 当前slab对象所使用的内存页
21     struct Page *page;
22 
23     ul count_using;
24     ul count_free;
25 
26     // 当前页面所在的线性地址
27     void *vaddr;
28 
29     // 位图
30     ul bmp_len;   // 位图的长度(字节)
31     ul bmp_count; // 位图的有效位数
32     ul *bmp;
33 };
34 
35 // slab内存池
36 struct slab
37 {
38     ul size; // 单位:byte
39     ul count_total_using;
40     ul count_total_free;
41     // 内存池对象
42     struct slab_obj *cache_pool_entry;
43     // dma内存池对象
44     struct slab_obj *cache_dma_pool_entry;
45 
46     spinlock_t lock; // 当前内存池的操作锁
47 
48     // 内存池的构造函数和析构函数
49     void *(*constructor)(void *vaddr, ul arg);
50     void *(*destructor)(void *vaddr, ul arg);
51 };
52 
53 /**
54  * @brief 通用内存分配函数
55  *
56  * @param size 要分配的内存大小
57  * @param gfp 内存的flag
58  * @return void* 分配得到的内存的指针
59  */
60 void *kmalloc(unsigned long size, gfp_t gfp);
61 
62 /**
63  * @brief 从kmalloc申请一块内存,并将这块内存清空
64  *
65  * @param size 要分配的内存大小
66  * @param gfp 内存的flag
67  * @return void* 分配得到的内存的指针
68  */
kzalloc(size_t size,gfp_t gfp)69 static __always_inline void *kzalloc(size_t size, gfp_t gfp)
70 {
71     return kmalloc(size, gfp | __GFP_ZERO);
72 }
73 
74 /**
75  * @brief 通用内存释放函数
76  *
77  * @param address 要释放的内存地址
78  * @return unsigned long
79  */
80 unsigned long kfree(void *address);
81 
82 /**
83  * @brief 创建一个内存池
84  *
85  * @param size 内存池容量大小
86  * @param constructor 构造函数
87  * @param destructor 析构函数
88  * @param arg 参数
89  * @return struct slab* 构建好的内存池对象
90  */
91 struct slab *slab_create(ul size, void *(*constructor)(void *vaddr, ul arg), void *(*destructor)(void *vaddr, ul arg), ul arg);
92 
93 /**
94  * @brief 销毁内存池对象
95  * 只有当slab对象是空的时候才能销毁
96  * @param slab_pool 要销毁的内存池对象
97  * @return ul
98  *
99  */
100 ul slab_destroy(struct slab *slab_pool);
101 
102 /**
103  * @brief 分配SLAB内存池中的内存对象
104  *
105  * @param slab_pool slab内存池
106  * @param arg 传递给内存对象构造函数的参数
107  * @return void* 内存空间的虚拟地址
108  */
109 void *slab_malloc(struct slab *slab_pool, ul arg);
110 
111 /**
112  * @brief 回收slab内存池中的对象
113  *
114  * @param slab_pool 对应的内存池
115  * @param addr 内存对象的虚拟地址
116  * @param arg 传递给虚构函数的参数
117  * @return ul
118  */
119 ul slab_free(struct slab *slab_pool, void *addr, ul arg);
120 
121 /**
122  * @brief 在kmalloc中创建slab_obj的函数(与slab_malloc()类似)
123  *
124  * @param size
125  * @return struct slab_obj* 创建好的slab_obj
126  */
127 struct slab_obj *kmalloc_create_slab_obj(ul size);
128 
129 /**
130  * @brief 初始化内存池组
131  * 在初始化通用内存管理单元期间,尚无内存空间分配函数,需要我们手动为SLAB内存池指定存储空间
132  * @return ul
133  */
134 ul slab_init();
135