slab函数分析之cache_alloc_refill

当array cache中没有可用的object的时候,需要批量从slab缓存中申请对象,这个时候
该函数被调用。下面分析一下这个函数。
static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
{
 int batchcount;
 struct kmem_list3 *l3;
 struct array_cache *ac;

 check_irq_off();
 取得当前CPU对应的array cache.
 ac = cpu_cache_get(cachep);
      retry:
 batchcount = ac->batchcount;
 对批量申请的slab对象数进行重新调整
 if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
  batchcount = BATCHREFILL_LIMIT;
 }
 取得本节点对应的kmem_list3缓存。
 l3 = cachep->nodelists[numa_node_id()];

 BUG_ON(ac->avail > 0 || !l3);
 对kmem_list3加锁
 spin_lock(&l3->list_lock);
  看看是不是在多节点环境下,并且同其他节点共享的l3缓存是不是为空,
  如果不为空,则首先从同其他节点共享的array cache中进行对象分配。
 if (l3->shared) {
  struct array_cache *shared_array = l3->shared;
  if (shared_array->avail) {
   if (batchcount > shared_array->avail)
    batchcount = shared_array->avail;
   shared_array->avail -= batchcount;
   ac->avail = batchcount;
   对象拷贝
   memcpy(ac->entry,
          &(shared_array->entry[shared_array->avail]),
          sizeof(void *) * batchcount);
   shared_array->touched = 1;
   goto alloc_done;
  }
 }
 如果是单节点,或者共享节点的对象已经分配完,则从slab缓存中进行分配
 while (batchcount > 0) {
  struct list_head *entry;
  struct slab *slabp;
  分配规则:
  1. 先从半满的缓存中进行分配
  2. 如果半满缓存分配完。再从全部空闲的缓存中进行对象分配
  entry = l3->slabs_partial.next;
  if (entry == &l3->slabs_partial) {
   l3->free_touched = 1;
   entry = l3->slabs_free.next;
   if (entry == &l3->slabs_free)
    goto must_grow;
  }

  slabp = list_entry(entry, struct slab, list);
  check_slabp(cachep, slabp);
  check_spinlock_acquired(cachep);
  检查slab缓存中的对象有没有被全部暂用,如果被暂用则退出这个
  while循环。
  while (slabp->inuse < cachep->num && batchcount--) {
   STATS_INC_ALLOCED(cachep);
   STATS_INC_ACTIVE(cachep);
   STATS_SET_HIGH(cachep);
      对象分配
   ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
           numa_node_id());
  }
  check_slabp(cachep, slabp);

    将该slab从之前的链表中游离出来
  list_del(&slabp->list);
  如果该slab的对象全部被分配出去,则把它放到全满的链表中
  否则放入半满的链表中。
  if (slabp->free == BUFCTL_END)
   list_add(&slabp->list, &l3->slabs_full);
  else
   list_add(&slabp->list, &l3->slabs_partial);
 }

      must_grow:
 l3->free_objects -= ac->avail;
      alloc_done:
 spin_unlock(&l3->list_lock);

 if (unlikely(!ac->avail)) {
  int x;
  表示slab缓存中没有足够的对象可以供分配,需要grow一下slab的大小。
  x = cache_grow(cachep, flags, numa_node_id());

  ac = cpu_cache_get(cachep);
  如果缓存增长失败,则返回空。表示对象分配失败
  if (!x && ac->avail == 0)
   return NULL;
    分配完之后,需要从新执行之前的操作,把缓存填满。
  if (!ac->avail)
   goto retry;
 }
 ac->touched = 1;
 对象分配。
 return ac->entry[--ac->avail];
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值