zone_pcp_update_cacheinfo()是 PCP(Per-CPU Pages)机制中一个特定于缓存信息优化的辅助函数,用于根据 CPU 的缓存特性动态调整 PCP 的行为标志。
核心作用
该函数的核心目的是判断某个 CPU 的数据缓存切片(data cache slice)是否足够大,从而决定是否要为该 CPU 的 PCP 启用PCPF_FREE_HIGH_BATCH标志。
这个标志的作用是:允许 PCP 缓存保留更多的页,以应对连续的高阶页释放操作,从而减少 zone 锁的竞争,同时又不损害缓存热页的共享。
典型实现
static void zone_pcp_update_cacheinfo(struct zone *zone, unsigned int cpu) { struct per_cpu_pages *pcp; struct cpu_cacheinfo *cci; pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu); cci = get_cpu_cacheinfo(cpu); /* * If data cache slice of CPU is large enough, "pcp->batch" * pages can be preserved in PCP before draining PCP for * consecutive high-order pages freeing without allocation. * This can reduce zone lock contention without hurting * cache-hot pages sharing. */ spin_lock(&pcp->lock); if ((cci->per_cpu_data_slice_size >> PAGE_SHIFT) > 3 * pcp->batch) pcp->flags |= PCPF_FREE_HIGH_BATCH; else pcp->flags &= ~PCPF_FREE_HIGH_BATCH; spin_unlock(&pcp->lock); }逻辑解析
1. 获取缓存信息
cci = get_cpu_cacheinfo(cpu);
get_cpu_cacheinfo()返回该 CPU 的缓存层次结构信息,其中per_cpu_data_slice_size表示数据缓存切片的大小。
2. 条件判断
if ((cci->per_cpu_data_slice_size >> PAGE_SHIFT) > 3 * pcp->batch)
per_cpu_data_slice_size >> PAGE_SHIFT:把缓存切片大小从字节转换为页数。3 * pcp->batch:一个经验阈值(3 倍的批量大小)。如果缓存切片足够大(能容纳超过
3 * batch个页),说明保留更多页不会严重损害缓存局部性。
3. 设置或清除标志
满足条件:设置
PCPF_FREE_HIGH_BATCH,允许 PCP 在释放高阶页时保留更多页,减少 zone 锁竞争。不满足条件:清除该标志,保持更积极的排空策略,保护缓存热页。
调用场景
该函数由setup_pcp_cacheinfo()调用,后者通常在 CPU 上线或缓存信息初始化时执行:
void setup_pcp_cacheinfo(unsigned int cpu) { struct zone *zone; for_each_populated_zone(zone) zone_pcp_update_cacheinfo(zone, cpu); }它遍历所有 populated zone,为指定 CPU 更新每个 zone 的 PCP 缓存优化标志。
总结
zone_pcp_update_cacheinfo()是 PCP 机制中一个感知硬件缓存特性的优化开关:它读取 CPU 的数据缓存切片大小,当该缓存足够大(能容纳超过3 * batch个页)时,为 PCP 设置PCPF_FREE_HIGH_BATCH标志,允许在连续释放高阶页时保留更多页,以减少zone->lock竞争;否则清除该标志,保持更积极的排空策略以保护缓存热页的共享。