diff options
| author | Christoph Lameter <cl@linux.com> | 2013-09-11 17:21:32 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:57:31 -0400 |
| commit | fbc2edb05354480a88aa39db8a6acb5782fa1a1b (patch) | |
| tree | b3d10c8b1310e264a9d9d4b9a8ea3416b4d12c0d | |
| parent | 4edb0748b23887140578d68f5f4e6e2de337a481 (diff) | |
vmstat: use this_cpu() to avoid irqon/off sequence in refresh_cpu_vm_stats
Disabling interrupts repeatedly can be avoided in the inner loop if we use
a this_cpu operation.
Signed-off-by: Christoph Lameter <cl@linux.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
CC: Tejun Heo <tj@kernel.org>
Cc: Joonsoo Kim <js1304@gmail.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | mm/vmstat.c | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index 158ca6494bc6..d57a09143bf9 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
| @@ -437,33 +437,29 @@ static inline void fold_diff(int *diff) | |||
| 437 | * with the global counters. These could cause remote node cache line | 437 | * with the global counters. These could cause remote node cache line |
| 438 | * bouncing and will have to be only done when necessary. | 438 | * bouncing and will have to be only done when necessary. |
| 439 | */ | 439 | */ |
| 440 | static void refresh_cpu_vm_stats(int cpu) | 440 | static void refresh_cpu_vm_stats(void) |
| 441 | { | 441 | { |
| 442 | struct zone *zone; | 442 | struct zone *zone; |
| 443 | int i; | 443 | int i; |
| 444 | int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, }; | 444 | int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, }; |
| 445 | 445 | ||
| 446 | for_each_populated_zone(zone) { | 446 | for_each_populated_zone(zone) { |
| 447 | struct per_cpu_pageset *p; | 447 | struct per_cpu_pageset __percpu *p = zone->pageset; |
| 448 | 448 | ||
| 449 | p = per_cpu_ptr(zone->pageset, cpu); | 449 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) { |
| 450 | int v; | ||
| 450 | 451 | ||
| 451 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) | 452 | v = this_cpu_xchg(p->vm_stat_diff[i], 0); |
| 452 | if (p->vm_stat_diff[i]) { | 453 | if (v) { |
| 453 | unsigned long flags; | ||
| 454 | int v; | ||
| 455 | 454 | ||
| 456 | local_irq_save(flags); | ||
| 457 | v = p->vm_stat_diff[i]; | ||
| 458 | p->vm_stat_diff[i] = 0; | ||
| 459 | local_irq_restore(flags); | ||
| 460 | atomic_long_add(v, &zone->vm_stat[i]); | 455 | atomic_long_add(v, &zone->vm_stat[i]); |
| 461 | global_diff[i] += v; | 456 | global_diff[i] += v; |
| 462 | #ifdef CONFIG_NUMA | 457 | #ifdef CONFIG_NUMA |
| 463 | /* 3 seconds idle till flush */ | 458 | /* 3 seconds idle till flush */ |
| 464 | p->expire = 3; | 459 | __this_cpu_write(p->expire, 3); |
| 465 | #endif | 460 | #endif |
| 466 | } | 461 | } |
| 462 | } | ||
| 467 | cond_resched(); | 463 | cond_resched(); |
| 468 | #ifdef CONFIG_NUMA | 464 | #ifdef CONFIG_NUMA |
| 469 | /* | 465 | /* |
| @@ -473,23 +469,24 @@ static void refresh_cpu_vm_stats(int cpu) | |||
| 473 | * Check if there are pages remaining in this pageset | 469 | * Check if there are pages remaining in this pageset |
| 474 | * if not then there is nothing to expire. | 470 | * if not then there is nothing to expire. |
| 475 | */ | 471 | */ |
| 476 | if (!p->expire || !p->pcp.count) | 472 | if (!__this_cpu_read(p->expire) || |
| 473 | !__this_cpu_read(p->pcp.count)) | ||
| 477 | continue; | 474 | continue; |
| 478 | 475 | ||
| 479 | /* | 476 | /* |
| 480 | * We never drain zones local to this processor. | 477 | * We never drain zones local to this processor. |
| 481 | */ | 478 | */ |
| 482 | if (zone_to_nid(zone) == numa_node_id()) { | 479 | if (zone_to_nid(zone) == numa_node_id()) { |
| 483 | p->expire = 0; | 480 | __this_cpu_write(p->expire, 0); |
| 484 | continue; | 481 | continue; |
| 485 | } | 482 | } |
| 486 | 483 | ||
| 487 | p->expire--; | 484 | |
| 488 | if (p->expire) | 485 | if (__this_cpu_dec_return(p->expire)) |
| 489 | continue; | 486 | continue; |
| 490 | 487 | ||
| 491 | if (p->pcp.count) | 488 | if (__this_cpu_read(p->pcp.count)) |
| 492 | drain_zone_pages(zone, &p->pcp); | 489 | drain_zone_pages(zone, __this_cpu_ptr(&p->pcp)); |
| 493 | #endif | 490 | #endif |
| 494 | } | 491 | } |
| 495 | fold_diff(global_diff); | 492 | fold_diff(global_diff); |
| @@ -1216,7 +1213,7 @@ int sysctl_stat_interval __read_mostly = HZ; | |||
| 1216 | 1213 | ||
| 1217 | static void vmstat_update(struct work_struct *w) | 1214 | static void vmstat_update(struct work_struct *w) |
| 1218 | { | 1215 | { |
| 1219 | refresh_cpu_vm_stats(smp_processor_id()); | 1216 | refresh_cpu_vm_stats(); |
| 1220 | schedule_delayed_work(&__get_cpu_var(vmstat_work), | 1217 | schedule_delayed_work(&__get_cpu_var(vmstat_work), |
| 1221 | round_jiffies_relative(sysctl_stat_interval)); | 1218 | round_jiffies_relative(sysctl_stat_interval)); |
| 1222 | } | 1219 | } |
