Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/mm/thrash.c
Parent Directory | Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 2689 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 2689 byte(s)
Tag kernel26-2.6.12-alx-r9
1 | /* |
2 | * mm/thrash.c |
3 | * |
4 | * Copyright (C) 2004, Red Hat, Inc. |
5 | * Copyright (C) 2004, Rik van Riel <riel@redhat.com> |
6 | * Released under the GPL, see the file COPYING for details. |
7 | * |
8 | * Simple token based thrashing protection, using the algorithm |
9 | * described in: http://www.cs.wm.edu/~sjiang/token.pdf |
10 | */ |
11 | #include <linux/jiffies.h> |
12 | #include <linux/mm.h> |
13 | #include <linux/sched.h> |
14 | #include <linux/swap.h> |
15 | |
16 | static DEFINE_SPINLOCK(swap_token_lock); |
17 | static unsigned long swap_token_timeout; |
18 | static unsigned long swap_token_check; |
19 | struct mm_struct * swap_token_mm = &init_mm; |
20 | |
21 | #define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2) |
22 | #define SWAP_TOKEN_TIMEOUT 0 |
23 | /* |
24 | * Currently disabled; Needs further code to work at HZ * 300. |
25 | */ |
26 | unsigned long swap_token_default_timeout = SWAP_TOKEN_TIMEOUT; |
27 | |
28 | /* |
29 | * Take the token away if the process had no page faults |
30 | * in the last interval, or if it has held the token for |
31 | * too long. |
32 | */ |
33 | #define SWAP_TOKEN_ENOUGH_RSS 1 |
34 | #define SWAP_TOKEN_TIMED_OUT 2 |
35 | static int should_release_swap_token(struct mm_struct *mm) |
36 | { |
37 | int ret = 0; |
38 | if (!mm->recent_pagein) |
39 | ret = SWAP_TOKEN_ENOUGH_RSS; |
40 | else if (time_after(jiffies, swap_token_timeout)) |
41 | ret = SWAP_TOKEN_TIMED_OUT; |
42 | mm->recent_pagein = 0; |
43 | return ret; |
44 | } |
45 | |
46 | /* |
47 | * Try to grab the swapout protection token. We only try to |
48 | * grab it once every TOKEN_CHECK_INTERVAL, both to prevent |
49 | * SMP lock contention and to check that the process that held |
50 | * the token before is no longer thrashing. |
51 | */ |
52 | void grab_swap_token(void) |
53 | { |
54 | struct mm_struct *mm; |
55 | int reason; |
56 | |
57 | /* We have the token. Let others know we still need it. */ |
58 | if (has_swap_token(current->mm)) { |
59 | current->mm->recent_pagein = 1; |
60 | return; |
61 | } |
62 | |
63 | if (time_after(jiffies, swap_token_check)) { |
64 | |
65 | /* Can't get swapout protection if we exceed our RSS limit. */ |
66 | // if (current->mm->rss > current->mm->rlimit_rss) |
67 | // return; |
68 | |
69 | /* ... or if we recently held the token. */ |
70 | if (time_before(jiffies, current->mm->swap_token_time)) |
71 | return; |
72 | |
73 | if (!spin_trylock(&swap_token_lock)) |
74 | return; |
75 | |
76 | swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL; |
77 | |
78 | mm = swap_token_mm; |
79 | if ((reason = should_release_swap_token(mm))) { |
80 | unsigned long eligible = jiffies; |
81 | if (reason == SWAP_TOKEN_TIMED_OUT) { |
82 | eligible += swap_token_default_timeout; |
83 | } |
84 | mm->swap_token_time = eligible; |
85 | swap_token_timeout = jiffies + swap_token_default_timeout; |
86 | swap_token_mm = current->mm; |
87 | } |
88 | spin_unlock(&swap_token_lock); |
89 | } |
90 | return; |
91 | } |
92 | |
93 | /* Called on process exit. */ |
94 | void __put_swap_token(struct mm_struct *mm) |
95 | { |
96 | spin_lock(&swap_token_lock); |
97 | if (likely(mm == swap_token_mm)) { |
98 | swap_token_mm = &init_mm; |
99 | swap_token_check = jiffies; |
100 | } |
101 | spin_unlock(&swap_token_lock); |
102 | } |