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.
8 * Simple token based thrashing protection, using the algorithm
9 * described in: http://www.cs.wm.edu/~sjiang/token.pdf
11 #include <linux/jiffies.h>
13 #include <linux/sched.h>
14 #include <linux/swap.h>
16 static spinlock_t swap_token_lock
= SPIN_LOCK_UNLOCKED
;
17 static unsigned long swap_token_timeout
;
18 unsigned long swap_token_check
;
19 struct mm_struct
* swap_token_mm
= &init_mm
;
21 #define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2)
22 #define SWAP_TOKEN_TIMEOUT (HZ * 300)
25 * Take the token away if the process had no page faults
26 * in the last interval, or if it has held the token for
29 #define SWAP_TOKEN_ENOUGH_RSS 1
30 #define SWAP_TOKEN_TIMED_OUT 2
31 static int should_release_swap_token(struct mm_struct
*mm
)
34 if (!mm
->recent_pagein
)
35 ret
= SWAP_TOKEN_ENOUGH_RSS
;
36 else if (time_after(jiffies
, swap_token_timeout
))
37 ret
= SWAP_TOKEN_TIMED_OUT
;
38 mm
->recent_pagein
= 0;
43 * Try to grab the swapout protection token. We only try to
44 * grab it once every TOKEN_CHECK_INTERVAL, both to prevent
45 * SMP lock contention and to check that the process that held
46 * the token before is no longer thrashing.
48 void grab_swap_token(void)
53 /* We have the token. Let others know we still need it. */
54 if (has_swap_token(current
->mm
)) {
55 current
->mm
->recent_pagein
= 1;
59 if (time_after(jiffies
, swap_token_check
)) {
61 /* Can't get swapout protection if we exceed our RSS limit. */
62 // if (current->mm->rss > current->mm->rlimit_rss)
65 /* ... or if we recently held the token. */
66 if (time_before(jiffies
, current
->mm
->swap_token_time
))
69 if (!spin_trylock(&swap_token_lock
))
72 swap_token_check
= jiffies
+ SWAP_TOKEN_CHECK_INTERVAL
;
75 if ((reason
= should_release_swap_token(mm
))) {
76 unsigned long eligible
= jiffies
;
77 if (reason
== SWAP_TOKEN_TIMED_OUT
) {
78 eligible
+= SWAP_TOKEN_TIMEOUT
;
80 mm
->swap_token_time
= eligible
;
81 swap_token_timeout
= jiffies
+ SWAP_TOKEN_TIMEOUT
;
82 swap_token_mm
= current
->mm
;
84 spin_unlock(&swap_token_lock
);
89 /* Called on process exit. */
90 void __put_swap_token(struct mm_struct
*mm
)
92 spin_lock(&swap_token_lock
);
93 if (likely(mm
== swap_token_mm
)) {
94 swap_token_mm
= &init_mm
;
95 swap_token_check
= jiffies
;
97 spin_unlock(&swap_token_lock
);