Home | History | Annotate | Line # | Download | only in pdsim
      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