• static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
  • {
  •     int batchcount;
  •     struct kmem_list3 *l3;
  •     struct array_cache *ac;
  •     int node;

  • retry:
  •     check_irq_off();
  •     /* 获取当前的NUMA节点 */
  •     node = numa_node_id();
  •     /* 获取local cache */
  •     ac = cpu_cache_get(cachep);
  •     /* 批量填充的数目 */
  •     batchcount = ac->batchcount;
  •     /* 如果最近未使用过该local cache,则一次填充的上限为BATCHREFILL_LIMIT个 */
  •     if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
  •         /*
  •          * If there was little recent activity on this cache, then
  •          * perform only a partial refill. Otherwise we could generate
  •          * refill bouncing.
  •          */
  •         batchcount = BATCHREFILL_LIMIT;
  •     }
  •     /* 获取本内存节点的kmem_list3的几个slab链表 */
  •     l3 = cachep->nodelists[node];

  •     BUG_ON(ac->avail > 0 || !l3);
  •     spin_lock(&l3->list_lock);

  •     /* See if we can refill from the shared array */
  •     /* shared local cache 用于多核中,所有cpu共享,首先从shared中批量获取slab对象到local */
  •     if (l3->shared && transfer_objects(ac, l3->shared, batchcount))
  •         goto alloc_done;
  •     /* 如果shared为空,或者已无空闲对象,则从slab链表中分配 */
  •     while (batchcount > 0) {
  •         struct list_head *entry;
  •         struct slab *slabp;
  •         /* Get slab alloc is to come from. */
  •         /* 先从部分未满的slab链表中分配 */
  •         entry = l3->slabs_partial.next;
  •         /* 判断是否为空 */
  •         if (entry == &l3->slabs_partial) {
  •             /* 标示刚访问了空链表 */
  •             l3->free_touched = 1;
  •             entry = l3->slabs_free.next;
  •             /* 如果空链表为空,则必须新增slab */
  •             if (entry == &l3->slabs_free)
  •                 goto must_grow;
  •         }
  •         /* 从链表上获取到了一个slab */
  •         slabp = list_entry(entry, struct slab, list);
  •         check_slabp(cachep, slabp);
  •         check_spinlock_acquired(cachep);

  •         /*
  •          * The slab was either on partial or free list so
  •          * there must be at least one object available for
  •          * allocation.
  •          */
  •         BUG_ON(slabp->inuse >= cachep->num);
  •         /* 当前slab的对象活跃数必须小于每个slab的最大对象数 */
  •         while (slabp->inuse < cachep->num && batchcount--) {
  •             STATS_INC_ALLOCED(cachep);
  •             STATS_INC_ACTIVE(cachep);
  •             STATS_SET_HIGH(cachep);
  •             /* 从slab中提取空闲对象,将虚拟地址插入到local cache中 */
  •             ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
  •                              node);
  •         }
  •         check_slabp(cachep, slabp);

  •         /* move slabp to correct slabp list: */
  •         /* 从原链表中删除slab */
  •         list_del(&slabp->list);
  •         if (slabp->free == BUFCTL_END)
  •             /* 此slab中已经没有空闲对象,移动到full链表中 */
  •             list_add(&slabp->list, &l3->slabs_full);
  •         else
  •             /* 此slab中还有空闲对象,移动到partial链表中 */
  •             list_add(&slabp->list, &l3->slabs_partial);
  •     }

  • must_grow:
  •     /* 从slab链表中添加了avail个空闲对象到local cache中,空闲的对象数量需要更新一下 */
  •     l3->free_objects -= ac->avail;
  • alloc_done:
  •     spin_unlock(&l3->list_lock);
  •     /* slab链表中也无空闲对象,创建新的slab */
  •     if (unlikely(!ac->avail)) {
  •         int x;
  •         /* 创建空slab */
  •         x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);

  •         /* cache_grow can reenable interrupts, then ac could change. */
  •         /* 看注释,由于cache_grow开启了中断,local cache指针可能发生裱花,ac需要重新获取 */
  •         ac = cpu_cache_get(cachep);
  •         /* 新的slab创建失败 */
  •         if (!x && ac->avail == 0)    /* no objects in sight? abort */
  •             return NULL;
  •         /* 新增slab成功,重新填充local cache */
  •         if (!ac->avail)        /* objects refilled by interrupt? */
  •             goto retry;
  •     }
  •     /* 设置近期访问的标志 */
  •     ac->touched = 1;
  •     /* 返回空闲对象的地址 */
  •     return ac->entry[--ac->avail];
  • }