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 }