[PATCH v2 09/11] mm/vmstat: use cmpxchg loop in cpu_vm_stats_fold

From: Marcelo Tosatti
Date: Thu Feb 09 2023 - 10:34:07 EST


In preparation to switch vmstat shepherd to flush
per-CPU counters remotely, use a cmpxchg loop
instead of a pair of read/write instructions.

Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx>

Index: linux-2.6/mm/vmstat.c
===================================================================
--- linux-2.6.orig/mm/vmstat.c
+++ linux-2.6/mm/vmstat.c
@@ -885,7 +885,7 @@ static int refresh_cpu_vm_stats(void)
}

/*
- * Fold the data for an offline cpu into the global array.
+ * Fold the data for a cpu into the global array.
* There cannot be any access by the offline cpu and therefore
* synchronization is simplified.
*/
@@ -906,8 +906,9 @@ void cpu_vm_stats_fold(int cpu)
if (pzstats->vm_stat_diff[i]) {
int v;

- v = pzstats->vm_stat_diff[i];
- pzstats->vm_stat_diff[i] = 0;
+ do {
+ v = pzstats->vm_stat_diff[i];
+ } while (!try_cmpxchg(&pzstats->vm_stat_diff[i], &v, 0));
atomic_long_add(v, &zone->vm_stat[i]);
global_zone_diff[i] += v;
}
@@ -917,8 +918,9 @@ void cpu_vm_stats_fold(int cpu)
if (pzstats->vm_numa_event[i]) {
unsigned long v;

- v = pzstats->vm_numa_event[i];
- pzstats->vm_numa_event[i] = 0;
+ do {
+ v = pzstats->vm_numa_event[i];
+ } while (!try_cmpxchg(&pzstats->vm_numa_event[i], &v, 0));
zone_numa_event_add(v, zone, i);
}
}
@@ -934,8 +936,9 @@ void cpu_vm_stats_fold(int cpu)
if (p->vm_node_stat_diff[i]) {
int v;

- v = p->vm_node_stat_diff[i];
- p->vm_node_stat_diff[i] = 0;
+ do {
+ v = p->vm_node_stat_diff[i];
+ } while (!try_cmpxchg(&p->vm_node_stat_diff[i], &v, 0));
atomic_long_add(v, &pgdat->vm_stat[i]);
global_node_diff[i] += v;
}