mm: page_counter: rearrange struct page_counter fields
[linux-2.6-block.git] / include / linux / page_counter.h
index 679591301994d316062f92b275efa2459a8349c9..78a1c934e4163eea5b94393dc1de52a31a390a26 100644 (file)
@@ -3,15 +3,26 @@
 #define _LINUX_PAGE_COUNTER_H
 
 #include <linux/atomic.h>
+#include <linux/cache.h>
 #include <linux/kernel.h>
 #include <asm/page.h>
 
+#if defined(CONFIG_SMP)
+struct pc_padding {
+       char x[0];
+} ____cacheline_internodealigned_in_smp;
+#define PC_PADDING(name)       struct pc_padding name
+#else
+#define PC_PADDING(name)
+#endif
+
 struct page_counter {
+       /*
+        * Make sure 'usage' does not share cacheline with any other field. The
+        * memcg->memory.usage is a hot member of struct mem_cgroup.
+        */
        atomic_long_t usage;
-       unsigned long min;
-       unsigned long low;
-       unsigned long high;
-       unsigned long max;
+       PC_PADDING(_pad1_);
 
        /* effective memory.min and memory.min usage tracking */
        unsigned long emin;
@@ -23,18 +34,18 @@ struct page_counter {
        atomic_long_t low_usage;
        atomic_long_t children_low_usage;
 
-       /* legacy */
        unsigned long watermark;
        unsigned long failcnt;
 
-       /*
-        * 'parent' is placed here to be far from 'usage' to reduce
-        * cache false sharing, as 'usage' is written mostly while
-        * parent is frequently read for cgroup's hierarchical
-        * counting nature.
-        */
+       /* Keep all the read most fields in a separete cacheline. */
+       PC_PADDING(_pad2_);
+
+       unsigned long min;
+       unsigned long low;
+       unsigned long high;
+       unsigned long max;
        struct page_counter *parent;
-};
+} ____cacheline_internodealigned_in_smp;
 
 #if BITS_PER_LONG == 32
 #define PAGE_COUNTER_MAX LONG_MAX