pageset_update()是 PCPPer-CPU Pages缓存配置的底层写入函数负责在运行时安全地更新某个 CPU 的 PCP 参数batch、high_min、high_max。核心实现static void pageset_update(struct per_cpu_pages *pcp, unsigned long high_min, unsigned long high_max, unsigned long batch) { WRITE_ONCE(pcp-batch, batch); WRITE_ONCE(pcp-high_min, high_min); WRITE_ONCE(pcp-high_max, high_max); }逐行解析1. 三个字段的含义字段含义pcp-batch批量补充/归还的页数pcp-high_min高水位下限自动调节的下界pcp-high_max高水位上限自动调节的上界2.WRITE_ONCE的作用防止编译器优化确保每次写入都真实发生不被优化掉或重排。保证原子性对于对齐的unsigned longWRITE_ONCE保证写入是单次、不可分割的读者不会看到写了一半的值。避免数据竞争并发读者如nr_pcp_alloc、nr_pcp_free、nr_pcp_high用READ_ONCE读取这些字段WRITE_ONCE与READ_ONCE配对符合内核的并发访问规范。3. 为什么不加锁这些字段是单个unsigned longWRITE_ONCE保证单次写入的原子性。读者读取时即使看到旧值也只是暂时的——不影响正确性只影响性能决策如 batch 用旧值下次更新就生效。加锁会引入不必要的开销而这些字段的更新是低频的zone 初始化、CPU 热插拔、sysctl 修改时。在 PCP 调节机制中的位置它被__zone_set_pageset_high_and_batch()调用后者负责更新 zone 内所有 CPU的 PCP 参数static void __zone_set_pageset_high_and_batch(struct zone *zone, unsigned long high_min, unsigned long high_max, unsigned long batch) { struct per_cpu_pages *pcp; int cpu; for_each_possible_cpu(cpu) { pcp per_cpu_ptr(zone-per_cpu_pageset, cpu); pageset_update(pcp, high_min, high_max, batch); } }调用链zone_set_pageset_high_and_batch(zone, cpu_online) ├── new_batch zone_batchsize(zone) ├── new_high zone_highsize(zone, new_batch, cpu_online) └── __zone_set_pageset_high_and_batch(zone, new_high, new_high, new_batch) └── for each cpu: pageset_update(pcp, high_min, high_max, batch) // ← 这里更新时机的考量pageset_update()在以下场景被调用zone 初始化zone_pcp_init()/setup_per_cpu_pageset()时首次设置。CPU 热插拔CPU 上线/下线时需要重新分配 PCP 份额。内存热插拔zone 大小变化时重新计算high。sysctl 修改用户调整vm.percpu_pagelist_high_fraction时。自动调节pcp-high在high_min和high_max之间动态变化但high_min/high_max/batch本身的更新走这里。与自动调节机制的配合2023 年引入的high_min/high_max机制让pcp-high可以在运行时自动增长和衰减nr_pcp_alloc()在分配压力大时抬高pcp-high不超过high_maxdecay_pcp_high()在压力小时降低pcp-high不低于high_minpageset_update()则更新调节的边界high_min/high_max以及batch。这样pcp-high的具体值可以频繁变化由自动调节逻辑处理而调节范围只在配置变化时才由pageset_update()更新。总结pageset_update()是 PCP 配置的原子写入接口它用WRITE_ONCE安全地更新某个 CPU 的batch、high_min、high_max三个字段避免数据竞争同时不加锁以保持轻量。它被__zone_set_pageset_high_and_batch()在 zone 初始化、CPU/内存热插拔、sysctl 修改时调用是 PCP 自动调节机制中更新调节边界的底层函数。
阅读完成 · 觉得有帮助?