This commit was manufactured by cvs2svn to create branch
[linux-2.6.git] / include / linux / ckrm_mem_inline.h
1 /* include/linux/ckrm_mem_inline.h : memory control for CKRM
2  *
3  * Copyright (C) Jiantao Kong, IBM Corp. 2003
4  *           (C) Shailabh Nagar, IBM Corp. 2003
5  *           (C) Chandra Seetharaman, IBM Corp. 2004
6  * 
7  * 
8  * Memory control functions of the CKRM kernel API 
9  *
10  * Latest version, more details at http://ckrm.sf.net
11  * 
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  */
18
19 /* Changes
20  *
21  * 28 Aug 2003
22  *        Created.
23  */
24
25
26 #ifndef _LINUX_CKRM_MEM_INLINE_H_
27 #define _LINUX_CKRM_MEM_INLINE_H_
28
29 #include <linux/rmap.h>
30 #include <linux/mmzone.h>
31 #include <linux/ckrm_mem.h>
32
33
34 #ifdef CONFIG_CKRM_RES_MEM
35
36 #define GET_MEM_CLASS(tsk) \
37         ckrm_get_res_class(tsk->taskclass, mem_rcbs.resid, ckrm_mem_res_t)
38
39 #define ckrm_set_shrink(cls) \
40         set_bit(CLS_SHRINK_BIT, (unsigned long *)&(cls)->reclaim_flags)
41 #define ckrm_test_set_shrink(cls) \
42         test_and_set_bit(CLS_SHRINK_BIT, (unsigned long *)&(cls)->reclaim_flags)
43 #define ckrm_clear_shrink(cls) \
44         clear_bit(CLS_SHRINK_BIT, (unsigned long *)&(cls)->reclaim_flags)
45
46 #define ckrm_shrink_list_empty()        list_empty(&ckrm_shrink_list)
47
48 /*
49  * Currently, the class of an address is assigned to the class with max
50  * available guarantee. Simply replace this function for other policies.
51  */
52 static inline int
53 ckrm_mem_share_compare(ckrm_mem_res_t *a, ckrm_mem_res_t *b)
54 {
55         if (a == NULL) 
56                 return -(b != NULL) ;
57         if (b == NULL)
58                 return 0;
59         if (a->pg_guar == CKRM_SHARE_DONTCARE)
60                 return 1;
61         if (b->pg_guar == CKRM_SHARE_DONTCARE)
62                 return -1;
63         return (a->pg_unused - b->pg_unused);
64 }
65
66 static inline void
67 mem_class_get(ckrm_mem_res_t *cls)
68 {
69         if (cls)
70                 atomic_inc(&((cls)->nr_users));
71 }
72
73 static inline void
74 mem_class_put(ckrm_mem_res_t *cls)
75 {
76         const char *name;
77         
78         if (cls && atomic_dec_and_test(&(cls->nr_users)) ) {
79                 if (cls->core == NULL) {
80                         name = "unknown";
81                 } else {
82                         name = cls->core->name;
83                 }
84                 printk(KERN_DEBUG "freeing memclass %p of <core:%s>\n", cls, name);
85
86                 // BUG_ON(ckrm_memclass_valid(cls));
87                 // kfree(cls);
88         }       
89 }
90
91 static inline void
92 incr_use_count(ckrm_mem_res_t *cls, int borrow)
93 {
94         atomic_inc(&cls->pg_total);
95
96         if (borrow) 
97                 cls->pg_lent++;
98         if ((cls->pg_guar == CKRM_SHARE_DONTCARE) ||
99                                 (atomic_read(&cls->pg_total) > cls->pg_unused)) {
100                 ckrm_mem_res_t *parcls = ckrm_get_res_class(cls->parent,
101                                 mem_rcbs.resid, ckrm_mem_res_t);
102                 if (parcls) {
103                         incr_use_count(parcls, 1);
104                         cls->pg_borrowed++;
105                 }
106         } else {
107                 atomic_inc(&ckrm_mem_real_count);
108         }
109         if ((cls->pg_limit != CKRM_SHARE_DONTCARE) && 
110                         (atomic_read(&cls->pg_total) >= cls->pg_limit) &&
111                         ((cls->flags & MEM_AT_LIMIT) != MEM_AT_LIMIT)) {
112                 ckrm_at_limit(cls);
113         }
114         return;
115 }
116
117 static inline void
118 decr_use_count(ckrm_mem_res_t *cls, int borrowed)
119 {
120         atomic_dec(&cls->pg_total);
121         if (borrowed)
122                 cls->pg_lent--;
123         if (cls->pg_borrowed > 0) {
124                 ckrm_mem_res_t *parcls = ckrm_get_res_class(cls->parent,
125                                 mem_rcbs.resid, ckrm_mem_res_t);
126                 if (parcls) {
127                         decr_use_count(parcls, 1);
128                         cls->pg_borrowed--;
129                         return;
130                 }
131         }
132         atomic_dec(&ckrm_mem_real_count);
133 }
134
135 static inline void
136 ckrm_set_page_class(struct page *page, ckrm_mem_res_t *cls)
137 {
138         if (mem_rcbs.resid != -1 && cls != NULL) {
139                 if (unlikely(page->memclass)) {
140                         mem_class_put(page->memclass);
141                 }
142                 page->memclass = cls;
143                 mem_class_get(cls);
144         } else {
145                 page->memclass = NULL;
146         }
147 }
148
149 static inline void
150 ckrm_set_pages_class(struct page *pages, int numpages, ckrm_mem_res_t *cls)
151 {
152         int i;
153         for (i = 0; i < numpages; pages++, i++) {
154                 ckrm_set_page_class(pages, cls);
155         }
156 }
157
158 static inline void
159 ckrm_clear_page_class(struct page *page)
160 {
161         if (page->memclass != NULL) {
162                 mem_class_put(page->memclass);
163                 page->memclass = NULL;
164         }
165 }
166
167 static inline void
168 ckrm_clear_pages_class(struct page *pages, int numpages)
169 {
170         int i;
171         for (i = 0; i < numpages; pages++, i++) {
172                 ckrm_clear_page_class(pages);
173         }
174 }
175
176 static inline void
177 ckrm_change_page_class(struct page *page, ckrm_mem_res_t *newcls)
178 {
179         ckrm_mem_res_t *oldcls = page_class(page);
180
181         if (!newcls || oldcls == newcls)
182                 return;
183
184         ckrm_clear_page_class(page);
185         ckrm_set_page_class(page, newcls);
186         if (test_bit(PG_ckrm_account, &page->flags)) {
187                 decr_use_count(oldcls, 0);
188                 incr_use_count(newcls, 0);
189                 if (PageActive(page)) {
190                         oldcls->nr_active[page_zonenum(page)]--;
191                         newcls->nr_active[page_zonenum(page)]++;
192                 } else {
193                         oldcls->nr_inactive[page_zonenum(page)]--;
194                         newcls->nr_inactive[page_zonenum(page)]++;
195                 }
196         }
197 }
198
199 static inline void
200 ckrm_change_pages_class(struct page *pages, int numpages, 
201                                         ckrm_mem_res_t *cls)
202 {
203         int i;
204         for (i = 0; i < numpages; pages++, i++) {
205                 ckrm_change_page_class(pages, cls);
206         }
207 }
208
209 static inline void
210 ckrm_mem_inc_active(struct page *page)
211 {
212         ckrm_mem_res_t *cls = page_class(page), *curcls;
213         if (unlikely(!cls)) {
214                 return;
215         }
216         BUG_ON(test_bit(PG_ckrm_account, &page->flags));
217         if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
218                 cls = curcls;
219                 ckrm_change_page_class(page, cls);
220         }
221         cls->nr_active[page_zonenum(page)]++;
222         incr_use_count(cls, 0);
223         set_bit(PG_ckrm_account, &page->flags);
224 }
225
226 static inline void
227 ckrm_mem_dec_active(struct page *page)
228 {
229         ckrm_mem_res_t *cls = page_class(page);
230         if (unlikely(!cls)) {
231                 return;
232         }
233         BUG_ON(!test_bit(PG_ckrm_account, &page->flags));
234         cls->nr_active[page_zonenum(page)]--;
235         decr_use_count(cls, 0);
236         clear_bit(PG_ckrm_account, &page->flags);
237 }
238
239 static inline void
240 ckrm_mem_inc_inactive(struct page *page)
241 {
242         ckrm_mem_res_t *cls = page_class(page), *curcls;
243         if (unlikely(!cls)) {
244                 return;
245         }
246         BUG_ON(test_bit(PG_ckrm_account, &page->flags));
247         if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
248                 cls = curcls;
249                 ckrm_change_page_class(page, cls);
250         }
251         cls->nr_inactive[page_zonenum(page)]++;
252         incr_use_count(cls, 0);
253         set_bit(PG_ckrm_account, &page->flags);
254 }
255
256 static inline void
257 ckrm_mem_dec_inactive(struct page *page)
258 {
259         ckrm_mem_res_t *cls = page_class(page);
260         if (unlikely(!cls)) {
261                 return;
262         }
263         BUG_ON(!test_bit(PG_ckrm_account, &page->flags));
264         cls->nr_inactive[page_zonenum(page)]--;
265         decr_use_count(cls, 0);
266         clear_bit(PG_ckrm_account, &page->flags);
267 }
268
269 static inline int
270 ckrm_kick_page(struct page *page, unsigned int bits)
271 {
272         if (page_class(page) == NULL) {
273                 return bits;
274         } else {
275                 return (page_class(page)->reclaim_flags & bits);
276         }
277 }
278
279 static inline int 
280 ckrm_class_limit_ok(ckrm_mem_res_t *cls)
281 {
282         if ((mem_rcbs.resid == -1) || !cls) {
283                 return 1;
284         }
285         if (cls->pg_limit == CKRM_SHARE_DONTCARE) {
286                 ckrm_mem_res_t *parcls = ckrm_get_res_class(cls->parent,
287                                                 mem_rcbs.resid, ckrm_mem_res_t);
288                 return (!parcls ?: ckrm_class_limit_ok(parcls));
289         } else {
290                 return (atomic_read(&cls->pg_total) <= (11 * cls->pg_limit) / 10);
291         }
292 }
293
294 #else // !CONFIG_CKRM_RES_MEM
295
296 #define ckrm_set_page_class(a,b)                do{}while(0)
297 #define ckrm_set_pages_class(a,b,c)             do{}while(0)
298 #define ckrm_clear_page_class(a)                do{}while(0)
299 #define ckrm_clear_pages_class(a,b)             do{}while(0)
300 #define ckrm_change_page_class(a,b)             do{}while(0)
301 #define ckrm_change_pages_class(a,b,c)  do{}while(0)
302 #define ckrm_mem_inc_active(a)                  do{}while(0)
303 #define ckrm_mem_dec_active(a)                  do{}while(0)
304 #define ckrm_mem_inc_inactive(a)                do{}while(0)
305 #define ckrm_mem_dec_inactive(a)                do{}while(0)
306 #define ckrm_shrink_list_empty()                (1)
307 #define ckrm_kick_page(a,b)                             (0)
308 #define ckrm_class_limit_ok(a)                  (1)
309
310 #endif // CONFIG_CKRM_RES_MEM
311
312 #endif // _LINUX_CKRM_MEM_INLINE_H_