diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /include/linux/page_cgroup.h | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'include/linux/page_cgroup.h')
-rw-r--r-- | include/linux/page_cgroup.h | 102 |
1 files changed, 78 insertions, 24 deletions
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h index 5bb13b3db84d..961ecc7d30bc 100644 --- a/include/linux/page_cgroup.h +++ b/include/linux/page_cgroup.h | |||
@@ -1,8 +1,26 @@ | |||
1 | #ifndef __LINUX_PAGE_CGROUP_H | 1 | #ifndef __LINUX_PAGE_CGROUP_H |
2 | #define __LINUX_PAGE_CGROUP_H | 2 | #define __LINUX_PAGE_CGROUP_H |
3 | 3 | ||
4 | enum { | ||
5 | /* flags for mem_cgroup */ | ||
6 | PCG_LOCK, /* Lock for pc->mem_cgroup and following bits. */ | ||
7 | PCG_CACHE, /* charged as cache */ | ||
8 | PCG_USED, /* this object is in use. */ | ||
9 | PCG_MIGRATION, /* under page migration */ | ||
10 | /* flags for mem_cgroup and file and I/O status */ | ||
11 | PCG_MOVE_LOCK, /* For race between move_account v.s. following bits */ | ||
12 | PCG_FILE_MAPPED, /* page is accounted as "mapped" */ | ||
13 | /* No lock in page_cgroup */ | ||
14 | PCG_ACCT_LRU, /* page has been accounted for (under lru_lock) */ | ||
15 | __NR_PCG_FLAGS, | ||
16 | }; | ||
17 | |||
18 | #ifndef __GENERATING_BOUNDS_H | ||
19 | #include <generated/bounds.h> | ||
20 | |||
4 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | 21 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR |
5 | #include <linux/bit_spinlock.h> | 22 | #include <linux/bit_spinlock.h> |
23 | |||
6 | /* | 24 | /* |
7 | * Page Cgroup can be considered as an extended mem_map. | 25 | * Page Cgroup can be considered as an extended mem_map. |
8 | * A page_cgroup page is associated with every page descriptor. The | 26 | * A page_cgroup page is associated with every page descriptor. The |
@@ -13,7 +31,6 @@ | |||
13 | struct page_cgroup { | 31 | struct page_cgroup { |
14 | unsigned long flags; | 32 | unsigned long flags; |
15 | struct mem_cgroup *mem_cgroup; | 33 | struct mem_cgroup *mem_cgroup; |
16 | struct page *page; | ||
17 | struct list_head lru; /* per cgroup LRU list */ | 34 | struct list_head lru; /* per cgroup LRU list */ |
18 | }; | 35 | }; |
19 | 36 | ||
@@ -32,16 +49,7 @@ static inline void __init page_cgroup_init(void) | |||
32 | #endif | 49 | #endif |
33 | 50 | ||
34 | struct page_cgroup *lookup_page_cgroup(struct page *page); | 51 | struct page_cgroup *lookup_page_cgroup(struct page *page); |
35 | 52 | struct page *lookup_cgroup_page(struct page_cgroup *pc); | |
36 | enum { | ||
37 | /* flags for mem_cgroup */ | ||
38 | PCG_LOCK, /* page cgroup is locked */ | ||
39 | PCG_CACHE, /* charged as cache */ | ||
40 | PCG_USED, /* this object is in use. */ | ||
41 | PCG_ACCT_LRU, /* page has been accounted for */ | ||
42 | PCG_FILE_MAPPED, /* page is accounted as "mapped" */ | ||
43 | PCG_MIGRATION, /* under page migration */ | ||
44 | }; | ||
45 | 53 | ||
46 | #define TESTPCGFLAG(uname, lname) \ | 54 | #define TESTPCGFLAG(uname, lname) \ |
47 | static inline int PageCgroup##uname(struct page_cgroup *pc) \ | 55 | static inline int PageCgroup##uname(struct page_cgroup *pc) \ |
@@ -59,8 +67,6 @@ static inline void ClearPageCgroup##uname(struct page_cgroup *pc) \ | |||
59 | static inline int TestClearPageCgroup##uname(struct page_cgroup *pc) \ | 67 | static inline int TestClearPageCgroup##uname(struct page_cgroup *pc) \ |
60 | { return test_and_clear_bit(PCG_##lname, &pc->flags); } | 68 | { return test_and_clear_bit(PCG_##lname, &pc->flags); } |
61 | 69 | ||
62 | TESTPCGFLAG(Locked, LOCK) | ||
63 | |||
64 | /* Cache flag is set only once (at allocation) */ | 70 | /* Cache flag is set only once (at allocation) */ |
65 | TESTPCGFLAG(Cache, CACHE) | 71 | TESTPCGFLAG(Cache, CACHE) |
66 | CLEARPCGFLAG(Cache, CACHE) | 72 | CLEARPCGFLAG(Cache, CACHE) |
@@ -84,24 +90,69 @@ SETPCGFLAG(Migration, MIGRATION) | |||
84 | CLEARPCGFLAG(Migration, MIGRATION) | 90 | CLEARPCGFLAG(Migration, MIGRATION) |
85 | TESTPCGFLAG(Migration, MIGRATION) | 91 | TESTPCGFLAG(Migration, MIGRATION) |
86 | 92 | ||
87 | static inline int page_cgroup_nid(struct page_cgroup *pc) | 93 | static inline void lock_page_cgroup(struct page_cgroup *pc) |
88 | { | 94 | { |
89 | return page_to_nid(pc->page); | 95 | /* |
96 | * Don't take this lock in IRQ context. | ||
97 | * This lock is for pc->mem_cgroup, USED, CACHE, MIGRATION | ||
98 | */ | ||
99 | bit_spin_lock(PCG_LOCK, &pc->flags); | ||
90 | } | 100 | } |
91 | 101 | ||
92 | static inline enum zone_type page_cgroup_zid(struct page_cgroup *pc) | 102 | static inline void unlock_page_cgroup(struct page_cgroup *pc) |
93 | { | 103 | { |
94 | return page_zonenum(pc->page); | 104 | bit_spin_unlock(PCG_LOCK, &pc->flags); |
95 | } | 105 | } |
96 | 106 | ||
97 | static inline void lock_page_cgroup(struct page_cgroup *pc) | 107 | static inline void move_lock_page_cgroup(struct page_cgroup *pc, |
108 | unsigned long *flags) | ||
98 | { | 109 | { |
99 | bit_spin_lock(PCG_LOCK, &pc->flags); | 110 | /* |
111 | * We know updates to pc->flags of page cache's stats are from both of | ||
112 | * usual context or IRQ context. Disable IRQ to avoid deadlock. | ||
113 | */ | ||
114 | local_irq_save(*flags); | ||
115 | bit_spin_lock(PCG_MOVE_LOCK, &pc->flags); | ||
100 | } | 116 | } |
101 | 117 | ||
102 | static inline void unlock_page_cgroup(struct page_cgroup *pc) | 118 | static inline void move_unlock_page_cgroup(struct page_cgroup *pc, |
119 | unsigned long *flags) | ||
103 | { | 120 | { |
104 | bit_spin_unlock(PCG_LOCK, &pc->flags); | 121 | bit_spin_unlock(PCG_MOVE_LOCK, &pc->flags); |
122 | local_irq_restore(*flags); | ||
123 | } | ||
124 | |||
125 | #ifdef CONFIG_SPARSEMEM | ||
126 | #define PCG_ARRAYID_WIDTH SECTIONS_SHIFT | ||
127 | #else | ||
128 | #define PCG_ARRAYID_WIDTH NODES_SHIFT | ||
129 | #endif | ||
130 | |||
131 | #if (PCG_ARRAYID_WIDTH > BITS_PER_LONG - NR_PCG_FLAGS) | ||
132 | #error Not enough space left in pc->flags to store page_cgroup array IDs | ||
133 | #endif | ||
134 | |||
135 | /* pc->flags: ARRAY-ID | FLAGS */ | ||
136 | |||
137 | #define PCG_ARRAYID_MASK ((1UL << PCG_ARRAYID_WIDTH) - 1) | ||
138 | |||
139 | #define PCG_ARRAYID_OFFSET (BITS_PER_LONG - PCG_ARRAYID_WIDTH) | ||
140 | /* | ||
141 | * Zero the shift count for non-existent fields, to prevent compiler | ||
142 | * warnings and ensure references are optimized away. | ||
143 | */ | ||
144 | #define PCG_ARRAYID_SHIFT (PCG_ARRAYID_OFFSET * (PCG_ARRAYID_WIDTH != 0)) | ||
145 | |||
146 | static inline void set_page_cgroup_array_id(struct page_cgroup *pc, | ||
147 | unsigned long id) | ||
148 | { | ||
149 | pc->flags &= ~(PCG_ARRAYID_MASK << PCG_ARRAYID_SHIFT); | ||
150 | pc->flags |= (id & PCG_ARRAYID_MASK) << PCG_ARRAYID_SHIFT; | ||
151 | } | ||
152 | |||
153 | static inline unsigned long page_cgroup_array_id(struct page_cgroup *pc) | ||
154 | { | ||
155 | return (pc->flags >> PCG_ARRAYID_SHIFT) & PCG_ARRAYID_MASK; | ||
105 | } | 156 | } |
106 | 157 | ||
107 | #else /* CONFIG_CGROUP_MEM_RES_CTLR */ | 158 | #else /* CONFIG_CGROUP_MEM_RES_CTLR */ |
@@ -124,7 +175,7 @@ static inline void __init page_cgroup_init_flatmem(void) | |||
124 | { | 175 | { |
125 | } | 176 | } |
126 | 177 | ||
127 | #endif | 178 | #endif /* CONFIG_CGROUP_MEM_RES_CTLR */ |
128 | 179 | ||
129 | #include <linux/swap.h> | 180 | #include <linux/swap.h> |
130 | 181 | ||
@@ -160,5 +211,8 @@ static inline void swap_cgroup_swapoff(int type) | |||
160 | return; | 211 | return; |
161 | } | 212 | } |
162 | 213 | ||
163 | #endif | 214 | #endif /* CONFIG_CGROUP_MEM_RES_CTLR_SWAP */ |
164 | #endif | 215 | |
216 | #endif /* !__GENERATING_BOUNDS_H */ | ||
217 | |||
218 | #endif /* __LINUX_PAGE_CGROUP_H */ | ||