歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

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

相關閱讀:
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