This commit was manufactured by cvs2svn to create tag
[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         
77         if (cls && atomic_dec_and_test(&(cls->nr_users)) ) {
78                 printk("freeing memclass %p of <core:%s>\n", cls, cls->core->name);
79                 BUG_ON(ckrm_memclass_valid(cls));
80                 //kfree(cls);
81         }       
82 }
83
84 static inline void
85 incr_use_count(ckrm_mem_res_t *cls, int borrow)
86 {
87         atomic_inc(&cls->pg_total);
88
89         if (borrow) 
90                 cls->pg_lent++;
91         if ((cls->pg_guar == CKRM_SHARE_DONTCARE) ||
92                                 (atomic_read(&cls->pg_total) > cls->pg_unused)) {
93                 ckrm_mem_res_t *parcls = ckrm_get_res_class(cls->parent,
94                                 mem_rcbs.resid, ckrm_mem_res_t);
95                 if (parcls) {
96                         incr_use_count(parcls, 1);
97                         cls->pg_borrowed++;
98                 }
99         } else {
100                 atomic_inc(&ckrm_mem_real_count);
101         }
102         if ((cls->pg_limit != CKRM_SHARE_DONTCARE) && 
103                         (atomic_read(&cls->pg_total) >= cls->pg_limit) &&
104                         ((cls->flags & MEM_AT_LIMIT) != MEM_AT_LIMIT)) {
105                 ckrm_at_limit(cls);
106         }
107         return;
108 }
109
110 static inline void
111 decr_use_count(ckrm_mem_res_t *cls, int borrowed)
112 {
113         atomic_dec(&cls->pg_total);
114         if (borrowed)
115                 cls->pg_lent--;
116         if (cls->pg_borrowed > 0) {
117                 ckrm_mem_res_t *parcls = ckrm_get_res_class(cls->parent,
118                                 mem_rcbs.resid, ckrm_mem_res_t);
119                 if (parcls) {
120                         decr_use_count(parcls, 1);
121                         cls->pg_borrowed--;
122                         return;
123                 }
124         }
125         atomic_dec(&ckrm_mem_real_count);
126 }
127
128 static inline void
129 ckrm_set_page_class(struct page *page, ckrm_mem_res_t *cls)
130 {
131         if (mem_rcbs.resid != -1 && cls != NULL) {
132                 if (unlikely(page->memclass)) {
133                         mem_class_put(page->memclass);
134                 }
135                 page->memclass = cls;
136                 mem_class_get(cls);
137         } else {
138                 page->memclass = NULL;
139         }
140 }
141
142 static inline void
143 ckrm_set_pages_class(struct page *pages, int numpages, ckrm_mem_res_t *cls)
144 {
145         int i;
146         for (i = 0; i < numpages; pages++, i++) {
147                 ckrm_set_page_class(pages, cls);
148         }
149 }
150
151 static inline void
152 ckrm_clear_page_class(struct page *page)
153 {
154         if (page->memclass != NULL) {
155                 mem_class_put(page->memclass);
156                 page->memclass = NULL;
157         }
158 }
159
160 static inline void
161 ckrm_clear_pages_class(struct page *pages, int numpages)
162 {
163         int i;
164         for (i = 0; i < numpages; pages++, i++) {
165                 ckrm_clear_page_class(pages);
166         }
167 }
168
169 static inline void
170 ckrm_change_page_class(struct page *page, ckrm_mem_res_t *newcls)
171 {
172         ckrm_mem_res_t *oldcls = page_class(page);
173
174         if (!newcls || oldcls == newcls)
175                 return;
176
177         ckrm_clear_page_class(page);
178         ckrm_set_page_class(page, newcls);
179         if (test_bit(PG_ckrm_account, &page->flags)) {
180                 decr_use_count(oldcls, 0);
181                 incr_use_count(newcls, 0);
182                 if (PageActive(page)) {
183                         oldcls->nr_active[page_zonenum(page)]--;
184                         newcls->nr_active[page_zonenum(page)]++;
185                 } else {
186                         oldcls->nr_inactive[page_zonenum(page)]--;
187                         newcls->nr_inactive[page_zonenum(page)]++;
188                 }
189         }
190 }
191
192 static inline void
193 ckrm_change_pages_class(struct page *pages, int numpages, 
194                                         ckrm_mem_res_t *cls)
195 {
196         int i;
197         for (i = 0; i < numpages; pages++, i++) {
198                 ckrm_change_page_class(pages, cls);
199         }
200 }
201
202 static inline void
203 ckrm_mem_inc_active(struct page *page)
204 {
205         ckrm_mem_res_t *cls = page_class(page), *curcls;
206         if (unlikely(!cls)) {
207                 return;
208         }
209         BUG_ON(test_bit(PG_ckrm_account, &page->flags));
210         if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
211                 cls = curcls;
212                 ckrm_change_page_class(page, cls);
213         }
214         cls->nr_active[page_zonenum(page)]++;
215         incr_use_count(cls, 0);
216         set_bit(PG_ckrm_account, &page->flags);
217 }
218
219 static inline void
220 ckrm_mem_dec_active(struct page *page)
221 {
222         ckrm_mem_res_t *cls = page_class(page);
223         if (unlikely(!cls)) {
224                 return;
225         }
226         BUG_ON(!test_bit(PG_ckrm_account, &page->flags));
227         cls->nr_active[page_zonenum(page)]--;
228         decr_use_count(cls, 0);
229         clear_bit(PG_ckrm_account, &page->flags);
230 }
231
232 static inline void
233 ckrm_mem_inc_inactive(struct page *page)
234 {
235         ckrm_mem_res_t *cls = page_class(page), *curcls;
236         if (unlikely(!cls)) {
237                 return;
238         }
239         BUG_ON(test_bit(PG_ckrm_account, &page->flags));
240         if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
241                 cls = curcls;
242                 ckrm_change_page_class(page, cls);
243         }
244         cls->nr_inactive[page_zonenum(page)]++;
245         incr_use_count(cls, 0);
246         set_bit(PG_ckrm_account, &page->flags);
247 }
248
249 static inline void
250 ckrm_mem_dec_inactive(struct page *page)
251 {
252         ckrm_mem_res_t *cls = page_class(page);
253         if (unlikely(!cls)) {
254                 return;
255         }
256         BUG_ON(!test_bit(PG_ckrm_account, &page->flags));
257         cls->nr_inactive[page_zonenum(page)]--;
258         decr_use_count(cls, 0);
259         clear_bit(PG_ckrm_account, &page->flags);
260 }
261
262 static inline int
263 ckrm_kick_page(struct page *page, unsigned int bits)
264 {
265         if (page_class(page) == NULL) {
266                 return bits;
267         } else {
268                 return (page_class(page)->reclaim_flags & bits);
269         }
270 }
271
272 static inline int 
273 ckrm_class_limit_ok(ckrm_mem_res_t *cls)
274 {
275         if ((mem_rcbs.resid == -1) || !cls) {
276                 return 1;
277         }
278         if (cls->pg_limit == CKRM_SHARE_DONTCARE) {
279                 ckrm_mem_res_t *parcls = ckrm_get_res_class(cls->parent,
280                                                 mem_rcbs.resid, ckrm_mem_res_t);
281                 return (!parcls ?: ckrm_class_limit_ok(parcls));
282         } else {
283                 return (atomic_read(&cls->pg_total) <= (11 * cls->pg_limit) / 10);
284         }
285 }
286
287 #else // !CONFIG_CKRM_RES_MEM
288
289 #define ckrm_set_page_class(a,b)                do{}while(0)
290 #define ckrm_set_pages_class(a,b,c)             do{}while(0)
291 #define ckrm_clear_page_class(a)                do{}while(0)
292 #define ckrm_clear_pages_class(a,b)             do{}while(0)
293 #define ckrm_change_page_class(a,b)             do{}while(0)
294 #define ckrm_change_pages_class(a,b,c)  do{}while(0)
295 #define ckrm_mem_inc_active(a)                  do{}while(0)
296 #define ckrm_mem_dec_active(a)                  do{}while(0)
297 #define ckrm_mem_inc_inactive(a)                do{}while(0)
298 #define ckrm_mem_dec_inactive(a)                do{}while(0)
299 #define ckrm_shrink_list_empty()                (1)
300 #define ckrm_kick_page(a,b)                             (0)
301 #define ckrm_class_limit_ok(a)                  (1)
302
303 #endif // CONFIG_CKRM_RES_MEM
304
305 #endif // _LINUX_CKRM_MEM_INLINE_H_