Blame view

mm/thrash.c 3.92 KB
1da177e4c   Linus Torvalds   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   KOSAKI Motohiro   mm: swap-token: f...
9
   * described in: http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/abs05-1.html
7602bdf2f   Ashwin Chaugule   [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   Linus Torvalds   Linux-2.6.12-rc2
18
   */
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
19

1da177e4c   Linus Torvalds   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   KOSAKI Motohiro   vmscan,memcg: mem...
24
  #include <linux/memcontrol.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

83cd81a34   KOSAKI Motohiro   vmscan: implement...
26
  #include <trace/events/vmscan.h>
d7911ef30   KOSAKI Motohiro   vmscan: implement...
27
  #define TOKEN_AGING_INTERVAL	(0xFF)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  static DEFINE_SPINLOCK(swap_token_lock);
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
29
  struct mm_struct *swap_token_mm;
22d5368a0   H Hartley Sweeten   mm/thrash.c: quie...
30
  static struct mem_cgroup *swap_token_memcg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

a433658c3   KOSAKI Motohiro   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   Hugh Dickins   mm: pass mm to gr...
49
  void grab_swap_token(struct mm_struct *mm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  {
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
51
  	int current_interval;
83cd81a34   KOSAKI Motohiro   vmscan: implement...
52
  	unsigned int old_prio = mm->token_priority;
53bb01f59   KOSAKI Motohiro   mm: swap-token: m...
53
54
  	static unsigned int global_faults;
  	static unsigned int last_aging;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
56
  	global_faults++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

a5c9b696e   Hugh Dickins   mm: pass mm to gr...
58
  	current_interval = global_faults - mm->faultstamp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59

7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
60
61
  	if (!spin_trylock(&swap_token_lock))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
63
  	/* First come first served */
a433658c3   KOSAKI Motohiro   vmscan,memcg: mem...
64
65
  	if (!swap_token_mm)
  		goto replace_token;
45ebb8402   KOSAKI Motohiro   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   KOSAKI Motohiro   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   KOSAKI Motohiro   vmscan,memcg: mem...
81
82
  	if (mm == swap_token_mm) {
  		mm->token_priority += 2;
83cd81a34   KOSAKI Motohiro   vmscan: implement...
83
  		goto update_priority;
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
84
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85

a433658c3   KOSAKI Motohiro   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   Linus Torvalds   Linux-2.6.12-rc2
91
  	}
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
92

a433658c3   KOSAKI Motohiro   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   KOSAKI Motohiro   vmscan: implement...
96
  update_priority:
d7911ef30   KOSAKI Motohiro   vmscan: implement...
97
  	trace_update_swap_token_priority(mm, old_prio, swap_token_mm);
83cd81a34   KOSAKI Motohiro   vmscan: implement...
98

7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
99
  out:
a5c9b696e   Hugh Dickins   mm: pass mm to gr...
100
101
  	mm->faultstamp = global_faults;
  	mm->last_interval = current_interval;
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
102
  	spin_unlock(&swap_token_lock);
a433658c3   KOSAKI Motohiro   vmscan,memcg: mem...
103
104
105
106
  	return;
  
  replace_token:
  	mm->token_priority += 2;
83cd81a34   KOSAKI Motohiro   vmscan: implement...
107
  	trace_replace_swap_token(swap_token_mm, mm);
a433658c3   KOSAKI Motohiro   vmscan,memcg: mem...
108
109
  	swap_token_mm = mm;
  	swap_token_memcg = swap_token_memcg_from_mm(mm);
d7911ef30   KOSAKI Motohiro   vmscan: implement...
110
  	last_aging = global_faults;
a433658c3   KOSAKI Motohiro   vmscan,memcg: mem...
111
  	goto out;
1da177e4c   Linus Torvalds   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   KOSAKI Motohiro   vmscan,memcg: mem...
118
  	if (likely(mm == swap_token_mm)) {
83cd81a34   KOSAKI Motohiro   vmscan: implement...
119
  		trace_put_swap_token(swap_token_mm);
7602bdf2f   Ashwin Chaugule   [PATCH] new schem...
120
  		swap_token_mm = NULL;
a433658c3   KOSAKI Motohiro   vmscan,memcg: mem...
121
122
  		swap_token_memcg = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
  	spin_unlock(&swap_token_lock);
  }
a433658c3   KOSAKI Motohiro   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   KOSAKI Motohiro   vmscan: implement...
143
  			trace_disable_swap_token(swap_token_mm);
a433658c3   KOSAKI Motohiro   vmscan,memcg: mem...
144
145
146
147
148
149
  			swap_token_mm = NULL;
  			swap_token_memcg = NULL;
  		}
  		spin_unlock(&swap_token_lock);
  	}
  }