diff options
author | Christoph Lameter <cl@linux-foundation.org> | 2010-01-05 01:34:51 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-01-05 01:34:51 -0500 |
commit | 99dcc3e5a94ed491fbef402831d8c0bbb267f995 (patch) | |
tree | dd4d2b9e10ab0d4502e4b2a22dfc0a02a3300d7e /mm/vmstat.c | |
parent | 5917dae83cb02dfe74c9167b79e86e6d65183fa3 (diff) |
this_cpu: Page allocator conversion
Use the per cpu allocator functionality to avoid per cpu arrays in struct zone.
This drastically reduces the size of struct zone for systems with large
amounts of processors and allows placement of critical variables of struct
zone in one cacheline even on very large systems.
Another effect is that the pagesets of one processor are placed near one
another. If multiple pagesets from different zones fit into one cacheline
then additional cacheline fetches can be avoided on the hot paths when
allocating memory from multiple zones.
Bootstrap becomes simpler if we use the same scheme for UP, SMP, NUMA. #ifdefs
are reduced and we can drop the zone_pcp macro.
Hotplug handling is also simplified since cpu alloc can bring up and
shut down cpu areas for a specific cpu as a whole. So there is no need to
allocate or free individual pagesets.
V7-V8:
- Explain chicken egg dilemmna with percpu allocator.
V4-V5:
- Fix up cases where per_cpu_ptr is called before irq disable
- Integrate the bootstrap logic that was separate before.
tj: Build failure in pageset_cpuup_callback() due to missing ret
variable fixed.
Reviewed-by: Mel Gorman <mel@csn.ul.ie>
Signed-off-by: Christoph Lameter <cl@linux-foundation.org>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r-- | mm/vmstat.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index 6051fbab67ba..1ba0bb7ad043 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -139,7 +139,8 @@ static void refresh_zone_stat_thresholds(void) | |||
139 | threshold = calculate_threshold(zone); | 139 | threshold = calculate_threshold(zone); |
140 | 140 | ||
141 | for_each_online_cpu(cpu) | 141 | for_each_online_cpu(cpu) |
142 | zone_pcp(zone, cpu)->stat_threshold = threshold; | 142 | per_cpu_ptr(zone->pageset, cpu)->stat_threshold |
143 | = threshold; | ||
143 | } | 144 | } |
144 | } | 145 | } |
145 | 146 | ||
@@ -149,7 +150,8 @@ static void refresh_zone_stat_thresholds(void) | |||
149 | void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, | 150 | void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, |
150 | int delta) | 151 | int delta) |
151 | { | 152 | { |
152 | struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); | 153 | struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset); |
154 | |||
153 | s8 *p = pcp->vm_stat_diff + item; | 155 | s8 *p = pcp->vm_stat_diff + item; |
154 | long x; | 156 | long x; |
155 | 157 | ||
@@ -202,7 +204,7 @@ EXPORT_SYMBOL(mod_zone_page_state); | |||
202 | */ | 204 | */ |
203 | void __inc_zone_state(struct zone *zone, enum zone_stat_item item) | 205 | void __inc_zone_state(struct zone *zone, enum zone_stat_item item) |
204 | { | 206 | { |
205 | struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); | 207 | struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset); |
206 | s8 *p = pcp->vm_stat_diff + item; | 208 | s8 *p = pcp->vm_stat_diff + item; |
207 | 209 | ||
208 | (*p)++; | 210 | (*p)++; |
@@ -223,7 +225,7 @@ EXPORT_SYMBOL(__inc_zone_page_state); | |||
223 | 225 | ||
224 | void __dec_zone_state(struct zone *zone, enum zone_stat_item item) | 226 | void __dec_zone_state(struct zone *zone, enum zone_stat_item item) |
225 | { | 227 | { |
226 | struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); | 228 | struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset); |
227 | s8 *p = pcp->vm_stat_diff + item; | 229 | s8 *p = pcp->vm_stat_diff + item; |
228 | 230 | ||
229 | (*p)--; | 231 | (*p)--; |
@@ -300,7 +302,7 @@ void refresh_cpu_vm_stats(int cpu) | |||
300 | for_each_populated_zone(zone) { | 302 | for_each_populated_zone(zone) { |
301 | struct per_cpu_pageset *p; | 303 | struct per_cpu_pageset *p; |
302 | 304 | ||
303 | p = zone_pcp(zone, cpu); | 305 | p = per_cpu_ptr(zone->pageset, cpu); |
304 | 306 | ||
305 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) | 307 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) |
306 | if (p->vm_stat_diff[i]) { | 308 | if (p->vm_stat_diff[i]) { |
@@ -741,7 +743,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, | |||
741 | for_each_online_cpu(i) { | 743 | for_each_online_cpu(i) { |
742 | struct per_cpu_pageset *pageset; | 744 | struct per_cpu_pageset *pageset; |
743 | 745 | ||
744 | pageset = zone_pcp(zone, i); | 746 | pageset = per_cpu_ptr(zone->pageset, i); |
745 | seq_printf(m, | 747 | seq_printf(m, |
746 | "\n cpu: %i" | 748 | "\n cpu: %i" |
747 | "\n count: %i" | 749 | "\n count: %i" |