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)
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));
85 incr_use_count(ckrm_mem_res_t *cls, int borrow)
87 atomic_inc(&cls->pg_total);
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);
96 incr_use_count(parcls, 1);
100 atomic_inc(&ckrm_mem_real_count);
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)) {
111 decr_use_count(ckrm_mem_res_t *cls, int borrowed)
113 atomic_dec(&cls->pg_total);
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);
120 decr_use_count(parcls, 1);
125 atomic_dec(&ckrm_mem_real_count);
129 ckrm_set_page_class(struct page *page, ckrm_mem_res_t *cls)
131 if (mem_rcbs.resid != -1 && cls != NULL) {
132 if (unlikely(page->memclass)) {
133 mem_class_put(page->memclass);
135 page->memclass = cls;
138 page->memclass = NULL;
143 ckrm_set_pages_class(struct page *pages, int numpages, ckrm_mem_res_t *cls)
146 for (i = 0; i < numpages; pages++, i++) {
147 ckrm_set_page_class(pages, cls);
152 ckrm_clear_page_class(struct page *page)
154 if (page->memclass != NULL) {
155 mem_class_put(page->memclass);
156 page->memclass = NULL;
161 ckrm_clear_pages_class(struct page *pages, int numpages)
164 for (i = 0; i < numpages; pages++, i++) {
165 ckrm_clear_page_class(pages);
170 ckrm_change_page_class(struct page *page, ckrm_mem_res_t *newcls)
172 ckrm_mem_res_t *oldcls = page_class(page);
174 if (!newcls || oldcls == newcls)
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)]++;
186 oldcls->nr_inactive[page_zonenum(page)]--;
187 newcls->nr_inactive[page_zonenum(page)]++;
193 ckrm_change_pages_class(struct page *pages, int numpages,
197 for (i = 0; i < numpages; pages++, i++) {
198 ckrm_change_page_class(pages, cls);
203 ckrm_mem_inc_active(struct page *page)
205 ckrm_mem_res_t *cls = page_class(page), *curcls;
206 if (unlikely(!cls)) {
209 BUG_ON(test_bit(PG_ckrm_account, &page->flags));
210 if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
212 ckrm_change_page_class(page, cls);
214 cls->nr_active[page_zonenum(page)]++;
215 incr_use_count(cls, 0);
216 set_bit(PG_ckrm_account, &page->flags);
220 ckrm_mem_dec_active(struct page *page)
222 ckrm_mem_res_t *cls = page_class(page);
223 if (unlikely(!cls)) {
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);
233 ckrm_mem_inc_inactive(struct page *page)
235 ckrm_mem_res_t *cls = page_class(page), *curcls;
236 if (unlikely(!cls)) {
239 BUG_ON(test_bit(PG_ckrm_account, &page->flags));
240 if (unlikely(cls != (curcls = GET_MEM_CLASS(current)))) {
242 ckrm_change_page_class(page, cls);
244 cls->nr_inactive[page_zonenum(page)]++;
245 incr_use_count(cls, 0);
246 set_bit(PG_ckrm_account, &page->flags);
250 ckrm_mem_dec_inactive(struct page *page)
252 ckrm_mem_res_t *cls = page_class(page);
253 if (unlikely(!cls)) {
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);
263 ckrm_kick_page(struct page *page, unsigned int bits)
265 if (page_class(page) == NULL) {
268 return (page_class(page)->reclaim_flags & bits);
273 ckrm_class_limit_ok(ckrm_mem_res_t *cls)
275 if ((mem_rcbs.resid == -1) || !cls) {
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));
283 return (atomic_read(&cls->pg_total) <= (11 * cls->pg_limit) / 10);
287 #else // !CONFIG_CKRM_RES_MEM
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)
303 #endif // CONFIG_CKRM_RES_MEM
305 #endif // _LINUX_CKRM_MEM_INLINE_H_