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