歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux Slob分配器(三)--釋放對象

Linux Slob分配器(三)--釋放對象

日期:2017/3/1 10:18:26   编辑:Linux編程

slob釋放對象由函數slob_free()來完成,分為三種情況進行處理:

  • slob中已有的空閒單元加上釋放對象塊的空閒單元正好等於一個空閒的page,那麼將直接將該page釋放回伙伴系統
  • slob中已無空閒單元,那麼這次釋放將更新slob的信息
  • 普通情況,即slob處於部分滿狀態,那麼更新slob的信息的同時還要將釋放的塊插入到相應的位置,要注意插入後是否能和相鄰塊進行合並!

下面來看具體的代碼

  1. /*
  2. * slob_free: entry point into the slob allocator.
  3. */
  4. static void slob_free(void *block, int size)
  5. {
  6. struct slob_page *sp;
  7. slob_t *prev, *next, *b = (slob_t *)block;
  8. slobidx_t units;
  9. unsigned long flags;
  10. if (unlikely(ZERO_OR_NULL_PTR(block)))
  11. return;
  12. BUG_ON(!size);
  13. sp = slob_page(block);//獲取slob地址
  14. units = SLOB_UNITS(size);//計算釋放的單元數
  15. spin_lock_irqsave(&slob_lock, flags);
  16. /*slob剩余的單元數加上待釋放的單元數正好等於一個slob本有的總單元數,
  17. 直接將slob占用的頁框釋放回伙伴系統*/
  18. if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
  19. /* Go directly to page allocator. Do not pass slob allocator */
  20. if (slob_page_free(sp))
  21. clear_slob_page_free(sp);
  22. spin_unlock_irqrestore(&slob_lock, flags);
  23. clear_slob_page(sp);
  24. free_slob_page(sp);
  25. slob_free_pages(b, 0);
  26. return;
  27. }
  28. if (!slob_page_free(sp)) {//slob沒有空閒塊
  29. /* This slob page is about to become partially free. Easy! */
  30. sp->units = units;//設置slob的單元數為釋放對象的單元數
  31. sp->free = b;//設置首對象為釋放對象
  32. set_slob(b, units,//最後一個對象的空閒對象設置為下一個頁的首個單元
  33. (void *)((unsigned long)(b +
  34. SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
  35. set_slob_page_free(sp, &free_slob_small);//將slob鏈入free_slob_small鏈表
  36. goto out;
  37. }
  38. /*
  39. * Otherwise the page is already partially free, so find reinsertion
  40. * point.
  41. */
  42. sp->units += units;//空閒單元總數增加units
  43. if (b < sp->free) {//待釋放塊的地址小於sp->free
  44. if (b + units == sp->free) {//可以合並
  45. units += slob_units(sp->free);
  46. sp->free = slob_next(sp->free);//取free的下一個空閒對象作為free
  47. }
  48. /*將釋放塊插入在free前面,並將其作為首個空閒塊賦給free*/
  49. set_slob(b, units, sp->free);
  50. sp->free = b;
  51. } else {
  52. prev = sp->free;//取首個空閒塊
  53. next = slob_next(prev);//取第二個空閒塊
  54. while (b > next) {//掃描至待釋放塊處
  55. prev = next;
  56. next = slob_next(prev);
  57. }
  58. /*將b插在prev和next中間,prev-->b-->next,要考慮是否能夠合並*/
  59. /*如果prev不是最後一個空閒塊並且b可以和next合並,則進行合並*/
  60. if (!slob_last(prev) && b + units == next) {
  61. units += slob_units(next);
  62. set_slob(b, units, slob_next(next));
  63. } else//否則將b插入在next前面
  64. set_slob(b, units, next);
  65. if (prev + slob_units(prev) == b) {//如果prev可以和b合並,則進行合並
  66. units = slob_units(b) + slob_units(prev);
  67. set_slob(prev, units, slob_next(b));
  68. } else//否則,將b插在prev後面
  69. set_slob(prev, slob_units(prev), b);
  70. }
  71. out:
  72. spin_unlock_irqrestore(&slob_lock, flags);
  73. }

相關閱讀:
Linux Slob分配器(一)--概述 http://www.linuxidc.com/Linux/2012-07/64107.htm
Linux Slob分配器(二)--分配對象 http://www.linuxidc.com/Linux/2012-07/64108.htm
Linux Slob分配器(三)--釋放對象 http://www.linuxidc.com/Linux/2012-07/64109.htm

Copyright © Linux教程網 All Rights Reserved