ZBLOG

加上中文注释: static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; struct kmem_cache_node *n; struct array_cache *ac, *shared; int node; void *list = NULL; struct page *page; ac = cp...

// 重新填充缓存中的对象
static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
{
    int batchcount;  // 批量分配的数量
    struct kmem_cache_node *n;  // 内存缓存节点
    struct array_cache *ac, *shared;  // CPU缓存、共享缓存
    int node;  // 节点索引
    void *list = NULL;  // 空闲对象链表
    struct page *page;  // 内存页

    ac = cpu_cache_get(cachep);  // 获取当前CPU缓存
    batchcount = ac->batchcount;  // 获取批量分配数量

	// 如果CPU缓存没有被访问过且批量分配数量超过阈值,则将批量分配数量限制为阈值
	if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
        batchcount = BATCHREFILL_LIMIT;
    }

	// 根据节点索引获取内存缓存节点
	n = get_node(cachep, node);

	BUG_ON(ac->avail > 0 || !n);  // 检查CPU缓存是否有可用对象,以及内存缓存节点是否存在

	shared = READ_ONCE(n->shared);  // 获取共享缓存

	// 如果没有空闲对象,并且没有共享空闲对象可分配,则跳转到direct_grow标签处执行直接增长逻辑
	if (!n->free_objects && (!shared || !shared->avail))
        goto direct_grow;

	spin_lock(&n->list_lock);

	shared = READ_ONCE(n->shared);  // 再次获取共享缓存

	// 尝试从共享缓存中重新填充CPU缓存
	if (shared && transfer_objects(ac, shared, batchcount)) {
        shared->touched = 1;
        goto alloc_done;
    }

	while (batchcount > 0) {
        page = get_first_slab(n, false);  // 获取第一个内存页

		// 如果没有可用的内存页,则跳转到must_grow标签处执行增长逻辑
        if (!page)
            goto must_grow;

        check_spinlock_acquired(cachep);  // 检查自旋锁是否被占用

		// 分配一块连续的对象,并将其加入空闲对象链表
        batchcount = alloc_block(cachep, ac, page, batchcount);
        fixup_slab_list(cachep, n, page, &list);
    }

must_grow:
	n->free_objects -= ac->avail;  // 更新空闲对象数量

alloc_done:
    spin_unlock(&n->list_lock);  // 解锁内存缓存节点链表
    fixup_objfreelist_debug(cachep, &list);  // 调整空闲对象链表的调试信息

direct_grow:
    if (unlikely(!ac->avail)) {
        // 检查是否可以使用pfmemalloc分配器中的对象
        if (sk_memalloc_socks()) {
            void *obj = cache_alloc_pfmemalloc(cachep, n, flags);

            if (obj)
                return obj;
        }

		// 开始进行直接增长操作
        page = cache_grow_begin(cachep, gfp_exact_node(flags), node);

        ac = cpu_cache_get(cachep);  // 再次获取CPU缓存
        if (!ac->avail && page)
            alloc_block(cachep, ac, page, batchcount);
        cache_grow_end(cachep, page);

		// 如果CPU缓存仍然没有可用对象,则返回NULL
        if (!ac->avail)
            return NULL;
    }
    ac->touched = 1;  // 标记CPU缓存已使用过

    return ac->entry[--ac->avail];  // 返回分配到的内存对象
}

这段代码是Linux内核中与slab分配器相关的函数片段,用于重新填充缓存中的对象。在此函数中,根据当前CPU缓存和节点信息,尝试从共享缓存或者内存页中重新填充CPU缓存的对象。如果无法找到可用对象,则会执行直接增长逻辑来扩大内存资源,并最终返回分配到的内存对象。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=10735

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?