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分配器(一)--概述
Linux Slob分配器(二)--分配对象
Linux Slob分配器(三)--释放对象

相关内容