1 /* include/linux/ckrm_mem_inline.h : memory control for CKRM
3 * Copyright (C) Jiantao Kong, IBM Corp. 2003
4 * (C) Shailabh Nagar, IBM Corp. 2003
5 * (C) Chandra Seetharaman, IBM Corp. 2004
8 * Memory control functions of the CKRM kernel API
10 * Latest version, more details at http://ckrm.sf.net
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.
26 #ifndef _LINUX_CKRM_MEM_INLINE_H_
27 #define _LINUX_CKRM_MEM_INLINE_H_
29 #include <linux/rmap.h>
30 #include <linux/mmzone.h>
31 #include <linux/ckrm_mem.h>
34 #ifdef CONFIG_CKRM_RES_MEM
36 #define GET_MEM_CLASS(tsk) \
37 ckrm_get_res_class(tsk->taskclass, mem_rcbs.resid, ckrm_mem_res_t)
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)
46 #define ckrm_shrink_list_empty() list_empty(&ckrm_shrink_list)
49 * Currently, the class of an address is assigned to the class with max
50 * available guarantee. Simply replace this function for other policies.
53 ckrm_mem_share_compare(ckrm_mem_res_t *a, ckrm_mem_res_t *b)
59 if (a->pg_guar == CKRM_SHARE_DONTCARE)
61 if (b->pg_guar == CKRM_SHARE_DONTCARE)
63 return (a->pg_unused - b->pg_unused);
67 mem_class_get(ckrm_mem_res_t *cls)
70 atomic_inc(&((cls)->nr_users));
74 mem_class_put(ckrm_mem_res_t *cls)
78 if (cls && atomic_dec_and_test(&(cls->nr_users)) ) {
79 if (cls->core == NULL) {
82 name = cls->core->name;
84 printk(KERN_DEBUG "freeing memclass %p of <core:%s>\n", cls, name);
86 // BUG_ON(ckrm_memclass_valid(cls));
92 incr_use_count(ckrm_mem_res_t *cls, int borrow)
94 atomic_inc(&cls->pg_total);
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);
103 incr_use_count(parcls, 1);
107 atomic_inc(&ckrm_mem_real_count);
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)) {
118 decr_use_count(ckrm_mem_res_t *cls, int borrowed)
120 atomic_dec(&cls->pg_total);
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);
127 decr_use_count(parcls, 1);
132 atomic_dec(&ckrm_mem_real_count);
136 ckrm_set_page_class(struct page *page, ckrm_mem_res_t *cls)
138 if (mem_rcbs.resid != -1 && cls != NULL) {
139 if (unlikely(page->memclass)) {
140 mem_class_put(page->memclass);
142 page->memclass = cls;
145 page->memclass = NULL;
150 ckrm_set_pages_class(struct page *pages, int numpages, ckrm_mem_res_t *cls)
153 for (i = 0; i < numpages; pages++, i++) {
154 ckrm_set_page_class(pages, cls);
159 ckrm_clear_page_class(struct page *page)
161 if (page->memclass != NULL) {
162 mem_class_put(page->memclass);
163 page->memclass = NULL;
168 ckrm_clear_pages_class(struct page *pages, int numpages)
171 for (i = 0; i < numpages; pages++, i++) {
172 ckrm_clear_page_class(pages);
177 ckrm_change_page_class(struct page *page, ckrm_mem_res_t *newcls)
179 ckrm_mem_res_t *oldcls = page_class(page);
181 if (!newcls || oldcls == newcls)
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)]++;
193 oldcls->nr_inactive[page_zonenum(page)]--;
194 newcls->nr_inactive[page_zonenum(page)]++;
200 ckrm_change_pages_class(struct page *pages, int numpages,
204 for (i = 0; i < numpages; pages++, i++) {
205 ckrm_change_page_class(pages, cls);
210 ckrm_mem_inc_active(struct page *page)
212 ckrm_mem_res_t *cls = page_class(page), *curcls;
213 if (unlikely(!cls)) {
216 BUG_ON(test_bit(PG_ckrm_account, &page->flags));
217 if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
219 ckrm_change_page_class(page, cls);
221 cls->nr_active[page_zonenum(page)]++;
222 incr_use_count(cls, 0);
223 set_bit(PG_ckrm_account, &page->flags);
227 ckrm_mem_dec_active(struct page *page)
229 ckrm_mem_res_t *cls = page_class(page);
230 if (unlikely(!cls)) {
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);
240 ckrm_mem_inc_inactive(struct page *page)
242 ckrm_mem_res_t *cls = page_class(page), *curcls;
243 if (unlikely(!cls)) {
246 BUG_ON(test_bit(PG_ckrm_account, &page->flags));
247 if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
249 ckrm_change_page_class(page, cls);
251 cls->nr_inactive[page_zonenum(page)]++;
252 incr_use_count(cls, 0);
253 set_bit(PG_ckrm_account, &page->flags);
257 ckrm_mem_dec_inactive(struct page *page)
259 ckrm_mem_res_t *cls = page_class(page);
260 if (unlikely(!cls)) {
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);
270 ckrm_kick_page(struct page *page, unsigned int bits)
272 if (page_class(page) == NULL) {
275 return (page_class(page)->reclaim_flags & bits);
280 ckrm_class_limit_ok(ckrm_mem_res_t *cls)
282 if ((mem_rcbs.resid == -1) || !cls) {
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));
290 return (atomic_read(&cls->pg_total) <= (11 * cls->pg_limit) / 10);
294 #else // !CONFIG_CKRM_RES_MEM
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)
310 #endif // CONFIG_CKRM_RES_MEM
312 #endif // _LINUX_CKRM_MEM_INLINE_H_