nbsd.hs revision 1.1 1 1.1 yamt {-
2 1.1 yamt /* $NetBSD: nbsd.hs,v 1.1 2006/10/09 12:32:46 yamt Exp $ */
3 1.1 yamt
4 1.1 yamt /*-
5 1.1 yamt * Copyright (c)2005 YAMAMOTO Takashi,
6 1.1 yamt * All rights reserved.
7 1.1 yamt *
8 1.1 yamt * Redistribution and use in source and binary forms, with or without
9 1.1 yamt * modification, are permitted provided that the following conditions
10 1.1 yamt * are met:
11 1.1 yamt * 1. Redistributions of source code must retain the above copyright
12 1.1 yamt * notice, this list of conditions and the following disclaimer.
13 1.1 yamt * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 yamt * notice, this list of conditions and the following disclaimer in the
15 1.1 yamt * documentation and/or other materials provided with the distribution.
16 1.1 yamt *
17 1.1 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 1.1 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 yamt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 yamt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 1.1 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 yamt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 yamt * SUCH DAMAGE.
28 1.1 yamt */
29 1.1 yamt -}
30 1.1 yamt
31 1.1 yamt import System.Environment
32 1.1 yamt import System.IO
33 1.1 yamt import List
34 1.1 yamt import Maybe
35 1.1 yamt import qualified Data.Map as Map
36 1.1 yamt import Control.Exception
37 1.1 yamt import Data.Queue
38 1.1 yamt
39 1.1 yamt type PageId = Int
40 1.1 yamt data Page = Pg { pgid :: PageId, referenced :: Bool }
41 1.1 yamt data Pageq = Pgq { active, inactive :: PageList }
42 1.1 yamt
43 1.1 yamt {-
44 1.1 yamt data PageList = Pgl Int [Int]
45 1.1 yamt pglenqueue x (Pgl n xs) = Pgl (n+1) (xs++[x])
46 1.1 yamt pgldequeue (Pgl n (x:xs)) = (x, Pgl (n-1) xs)
47 1.1 yamt pglsize (Pgl n _) = n
48 1.1 yamt pglempty = Pgl 0 []
49 1.1 yamt -}
50 1.1 yamt data PageList = Pgl Int (Queue Int)
51 1.1 yamt pglenqueue x (Pgl n q) = Pgl (n+1) (addToQueue q x)
52 1.1 yamt pgldequeue (Pgl n q) = (x, Pgl (n-1) nq) where
53 1.1 yamt Just (x,nq) = deQueue q
54 1.1 yamt pglsize (Pgl n _) = n
55 1.1 yamt pglempty = Pgl 0 emptyQueue
56 1.1 yamt
57 1.1 yamt {-
58 1.1 yamt instance Show Page where
59 1.1 yamt show pg = "(" ++ (show $ pgid pg) ++ "," ++ (show $ referenced pg) ++ ")"
60 1.1 yamt instance Show Pageq where
61 1.1 yamt show q = "(act=" ++ (show $ active q) ++ ",inact=" ++ (show $ inactive q) ++ ")"
62 1.1 yamt -}
63 1.1 yamt
64 1.1 yamt pglookup idx m = Map.lookup idx m
65 1.1 yamt
66 1.1 yamt emptyq = Pgq { active = pglempty, inactive = pglempty }
67 1.1 yamt
68 1.1 yamt clrref pg = pg { referenced = False }
69 1.1 yamt markref pg = pg { referenced = True }
70 1.1 yamt
71 1.1 yamt clrrefm x m = Map.update (Just . clrref) x m
72 1.1 yamt
73 1.1 yamt reactivate :: (Pageq,Map.Map Int Page) -> (Pageq,Map.Map Int Page)
74 1.1 yamt reactivate (q,m) = (nq,nm) where
75 1.1 yamt nq = q { active = pglenqueue x $ active q, inactive = niaq }
76 1.1 yamt nm = clrrefm x m
77 1.1 yamt (x,niaq) = pgldequeue $ inactive q
78 1.1 yamt reactivate_act (q,m) = (nq,nm) where
79 1.1 yamt nq = q { active = pglenqueue x $ naq }
80 1.1 yamt nm = clrrefm x m
81 1.1 yamt (x,naq) = pgldequeue $ active q
82 1.1 yamt deactivate_act (q,m) = (nq,nm) where
83 1.1 yamt nq = q { active = naq, inactive = pglenqueue x $ inactive q }
84 1.1 yamt nm = clrrefm x m
85 1.1 yamt (x,naq) = pgldequeue $ active q
86 1.1 yamt
87 1.1 yamt reclaim :: Int -> (Pageq,Map.Map Int Page)->(Pageq,Map.Map Int Page)
88 1.1 yamt reclaim pct (q0,m0) =
89 1.1 yamt if referenced p then
90 1.1 yamt reclaim pct $ reactivate (q,m)
91 1.1 yamt else
92 1.1 yamt (q { inactive = npgl },Map.delete x m)
93 1.1 yamt where
94 1.1 yamt (q,m) = fillinact pct (q0,m0)
95 1.1 yamt (x,npgl) = pgldequeue $ inactive q
96 1.1 yamt Just p = Map.lookup x m0
97 1.1 yamt
98 1.1 yamt fillinact inactpct (q,m) =
99 1.1 yamt if inactlen >= inacttarg then (q,m) else
100 1.1 yamt #if defined(LINUX)
101 1.1 yamt if referenced p then
102 1.1 yamt fillinact inactpct $ reactivate_act (q,m) else
103 1.1 yamt #endif
104 1.1 yamt fillinact inactpct $ deactivate_act (q,m)
105 1.1 yamt where
106 1.1 yamt Just p = Map.lookup x m
107 1.1 yamt (x,_) = pgldequeue $ active q
108 1.1 yamt inactlen = pglsize $ inactive q
109 1.1 yamt inacttarg = div (Map.size m * inactpct) 100
110 1.1 yamt
111 1.1 yamt pgref :: Int->Map.Map Int Page -> Map.Map Int Page
112 1.1 yamt pgref idx m = Map.update f idx m where
113 1.1 yamt f = Just . markref
114 1.1 yamt
115 1.1 yamt do_nbsd1 npg pct n q m [] = (reverse n, q)
116 1.1 yamt do_nbsd1 npg pct n q m rs@(r:rs2) =
117 1.1 yamt let
118 1.1 yamt p = pglookup r m
119 1.1 yamt in
120 1.1 yamt if isJust p then
121 1.1 yamt do_nbsd1 npg pct n q (pgref r m) rs2
122 1.1 yamt else if Map.size m < npg then
123 1.1 yamt do_nbsd1 npg pct (r:n) (enqueue r q) (pgenqueue r m) rs2
124 1.1 yamt else
125 1.1 yamt let
126 1.1 yamt (nq, nm) = reclaim pct (q,m)
127 1.1 yamt in
128 1.1 yamt do_nbsd1 npg pct (r:n) (enqueue r nq) (pgenqueue r nm) rs2
129 1.1 yamt where
130 1.1 yamt newpg i = Pg {pgid = i, referenced = True}
131 1.1 yamt pgenqueue i m = Map.insert i (newpg i) m
132 1.1 yamt #if defined(LINUX)
133 1.1 yamt enqueue i q = q { inactive = pglenqueue i $ inactive q }
134 1.1 yamt #else
135 1.1 yamt enqueue i q = q { active = pglenqueue i $ active q }
136 1.1 yamt #endif
137 1.1 yamt
138 1.1 yamt do_nbsd npg pct rs = fst $ do_nbsd1 npg pct [] emptyq Map.empty rs
139 1.1 yamt do_nbsd_dbg npg pct rs = do_nbsd1 npg pct [] emptyq Map.empty rs
140 1.1 yamt
141 1.1 yamt main = do
142 1.1 yamt xs <- getContents
143 1.1 yamt args <- getArgs
144 1.1 yamt let
145 1.1 yamt ls = lines xs
146 1.1 yamt npgs::Int
147 1.1 yamt npgs = read $ args !! 0
148 1.1 yamt pct = read $ args !! 1
149 1.1 yamt pgs::[Int]
150 1.1 yamt pgs = map read ls
151 1.1 yamt mapM_ print $ do_nbsd npgs pct pgs
152