#ifndef PAGE_FLAGS_H
#define PAGE_FLAGS_H
+#include <linux/percpu.h>
+
/*
* Various page->flags bits:
*
* Global page accounting. One instance per CPU. Only unsigned longs are
* allowed.
*/
-extern struct page_state {
+struct page_state {
unsigned long nr_dirty;
unsigned long nr_writeback;
unsigned long nr_pagecache;
unsigned long kswapd_steal;
unsigned long pageoutrun;
unsigned long allocstall;
-} ____cacheline_aligned_in_smp page_states[NR_CPUS];
+};
+
+DECLARE_PER_CPU(struct page_state, page_states);
extern void get_page_state(struct page_state *ret);
extern void get_full_page_state(struct page_state *ret);
#define mod_page_state(member, delta) \
do { \
int cpu = get_cpu(); \
- page_states[cpu].member += (delta); \
+ per_cpu(page_states, cpu).member += (delta); \
put_cpu(); \
} while (0)
#include <linux/hdreg.h>
#include <linux/bootmem.h>
#include <linux/tty.h>
+#include <linux/gfp.h>
#include <linux/percpu.h>
#include <linux/kernel_stat.h>
#include <linux/security.h>
setup_arch(&command_line);
setup_per_cpu_areas();
build_all_zonelists();
+ page_alloc_init();
printk("Kernel command line: %s\n", saved_command_line);
parse_options(command_line);
trap_init();
#include <linux/pagevec.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
+#include <linux/notifier.h>
struct pglist_data *pgdat_list;
unsigned long totalram_pages;
* The result is unavoidably approximate - it can change
* during and after execution of this function.
*/
-struct page_state page_states[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(page_states);
+DEFINE_PER_CPU(struct page_state, page_states) = {0};
+EXPORT_PER_CPU_SYMBOL(page_states);
void __get_page_state(struct page_state *ret, int nr)
{
if (!cpu_online(cpu))
continue;
- in = (unsigned long *)(page_states + cpu);
+ in = (unsigned long *)&per_cpu(page_states, cpu);
out = (unsigned long *)ret;
for (off = 0; off < nr; off++)
*out++ += *in++;
};
#endif /* CONFIG_PROC_FS */
+
+static void __devinit init_page_alloc_cpu(int cpu)
+{
+ struct page_state *ps = &per_cpu(page_states, cpu);
+ memset(ps, 0, sizeof(*ps));
+}
+
+static int __devinit page_alloc_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (unsigned long)hcpu;
+ switch(action) {
+ case CPU_UP_PREPARE:
+ init_page_alloc_cpu(cpu);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata page_alloc_nb = {
+ .notifier_call = page_alloc_cpu_notify,
+};
+
+void __init page_alloc_init(void)
+{
+ init_page_alloc_cpu(smp_processor_id());
+ register_cpu_notifier(&page_alloc_nb);
+}