Blame view
mm/thrash.c
3.91 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 |
/* * mm/thrash.c * * Copyright (C) 2004, Red Hat, Inc. * Copyright (C) 2004, Rik van Riel <riel@redhat.com> * Released under the GPL, see the file COPYING for details. * * Simple token based thrashing protection, using the algorithm |
e21c7ffd6 mm: swap-token: f... |
9 |
* described in: http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/abs05-1.html |
7602bdf2f [PATCH] new schem... |
10 11 12 13 14 15 16 17 |
* * Sep 2006, Ashwin Chaugule <ashwin.chaugule@celunite.com> * Improved algorithm to pass token: * Each task has a priority which is incremented if it contended * for the token in an interval less than its previous attempt. * If the token is acquired, that task's priority is boosted to prevent * the token from bouncing around too often and to let the task make * some progress in its execution. |
1da177e4c Linux-2.6.12-rc2 |
18 |
*/ |
7602bdf2f [PATCH] new schem... |
19 |
|
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 |
#include <linux/jiffies.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/swap.h> |
a433658c3 vmscan,memcg: mem... |
24 |
#include <linux/memcontrol.h> |
1da177e4c Linux-2.6.12-rc2 |
25 |
|
83cd81a34 vmscan: implement... |
26 |
#include <trace/events/vmscan.h> |
d7911ef30 vmscan: implement... |
27 |
#define TOKEN_AGING_INTERVAL (0xFF) |
1da177e4c Linux-2.6.12-rc2 |
28 |
static DEFINE_SPINLOCK(swap_token_lock); |
7602bdf2f [PATCH] new schem... |
29 |
struct mm_struct *swap_token_mm; |
a433658c3 vmscan,memcg: mem... |
30 |
struct mem_cgroup *swap_token_memcg; |
1da177e4c Linux-2.6.12-rc2 |
31 |
|
a433658c3 vmscan,memcg: mem... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#ifdef CONFIG_CGROUP_MEM_RES_CTLR static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) { struct mem_cgroup *memcg; memcg = try_get_mem_cgroup_from_mm(mm); if (memcg) css_put(mem_cgroup_css(memcg)); return memcg; } #else static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) { return NULL; } #endif |
a5c9b696e mm: pass mm to gr... |
49 |
void grab_swap_token(struct mm_struct *mm) |
1da177e4c Linux-2.6.12-rc2 |
50 |
{ |
7602bdf2f [PATCH] new schem... |
51 |
int current_interval; |
83cd81a34 vmscan: implement... |
52 |
unsigned int old_prio = mm->token_priority; |
53bb01f59 mm: swap-token: m... |
53 54 |
static unsigned int global_faults; static unsigned int last_aging; |
1da177e4c Linux-2.6.12-rc2 |
55 |
|
7602bdf2f [PATCH] new schem... |
56 |
global_faults++; |
1da177e4c Linux-2.6.12-rc2 |
57 |
|
a5c9b696e mm: pass mm to gr... |
58 |
current_interval = global_faults - mm->faultstamp; |
1da177e4c Linux-2.6.12-rc2 |
59 |
|
7602bdf2f [PATCH] new schem... |
60 61 |
if (!spin_trylock(&swap_token_lock)) return; |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
7602bdf2f [PATCH] new schem... |
63 |
/* First come first served */ |
a433658c3 vmscan,memcg: mem... |
64 65 |
if (!swap_token_mm) goto replace_token; |
45ebb8402 mm: swap-token: a... |
66 67 68 69 70 71 72 73 74 75 76 |
/* * Usually, we don't need priority aging because long interval faults * makes priority decrease quickly. But there is one exception. If the * token owner task is sleeping, it never make long interval faults. * Thus, we need a priority aging mechanism instead. The requirements * of priority aging are * 1) An aging interval is reasonable enough long. Too short aging * interval makes quick swap token lost and decrease performance. * 2) The swap token owner task have to get priority aging even if * it's under sleep. */ |
d7911ef30 vmscan: implement... |
77 78 79 80 |
if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { swap_token_mm->token_priority /= 2; last_aging = global_faults; } |
a433658c3 vmscan,memcg: mem... |
81 82 |
if (mm == swap_token_mm) { mm->token_priority += 2; |
83cd81a34 vmscan: implement... |
83 |
goto update_priority; |
7602bdf2f [PATCH] new schem... |
84 |
} |
1da177e4c Linux-2.6.12-rc2 |
85 |
|
a433658c3 vmscan,memcg: mem... |
86 87 88 89 90 |
if (current_interval < mm->last_interval) mm->token_priority++; else { if (likely(mm->token_priority > 0)) mm->token_priority--; |
1da177e4c Linux-2.6.12-rc2 |
91 |
} |
7602bdf2f [PATCH] new schem... |
92 |
|
a433658c3 vmscan,memcg: mem... |
93 94 95 |
/* Check if we deserve the token */ if (mm->token_priority > swap_token_mm->token_priority) goto replace_token; |
83cd81a34 vmscan: implement... |
96 |
update_priority: |
d7911ef30 vmscan: implement... |
97 |
trace_update_swap_token_priority(mm, old_prio, swap_token_mm); |
83cd81a34 vmscan: implement... |
98 |
|
7602bdf2f [PATCH] new schem... |
99 |
out: |
a5c9b696e mm: pass mm to gr... |
100 101 |
mm->faultstamp = global_faults; mm->last_interval = current_interval; |
7602bdf2f [PATCH] new schem... |
102 |
spin_unlock(&swap_token_lock); |
a433658c3 vmscan,memcg: mem... |
103 104 105 106 |
return; replace_token: mm->token_priority += 2; |
83cd81a34 vmscan: implement... |
107 |
trace_replace_swap_token(swap_token_mm, mm); |
a433658c3 vmscan,memcg: mem... |
108 109 |
swap_token_mm = mm; swap_token_memcg = swap_token_memcg_from_mm(mm); |
d7911ef30 vmscan: implement... |
110 |
last_aging = global_faults; |
a433658c3 vmscan,memcg: mem... |
111 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
112 113 114 115 116 117 |
} /* Called on process exit. */ void __put_swap_token(struct mm_struct *mm) { spin_lock(&swap_token_lock); |
a433658c3 vmscan,memcg: mem... |
118 |
if (likely(mm == swap_token_mm)) { |
83cd81a34 vmscan: implement... |
119 |
trace_put_swap_token(swap_token_mm); |
7602bdf2f [PATCH] new schem... |
120 |
swap_token_mm = NULL; |
a433658c3 vmscan,memcg: mem... |
121 122 |
swap_token_memcg = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
123 124 |
spin_unlock(&swap_token_lock); } |
a433658c3 vmscan,memcg: mem... |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b) { if (!a) return true; if (!b) return true; if (a == b) return true; return false; } void disable_swap_token(struct mem_cgroup *memcg) { /* memcg reclaim don't disable unrelated mm token. */ if (match_memcg(memcg, swap_token_memcg)) { spin_lock(&swap_token_lock); if (match_memcg(memcg, swap_token_memcg)) { |
83cd81a34 vmscan: implement... |
143 |
trace_disable_swap_token(swap_token_mm); |
a433658c3 vmscan,memcg: mem... |
144 145 146 147 148 149 |
swap_token_mm = NULL; swap_token_memcg = NULL; } spin_unlock(&swap_token_lock); } } |