slab.c 25 KB

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