2 /* $NetBSD: nbsd.hs,v 1.1 2006/09/30 08:50:32 yamt Exp $ */
5 * Copyright (c)2005 YAMAMOTO Takashi,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 import System
.Environment
35 import qualified Data
.Map
as Map
36 import Control
.Exception
40 data Page
= Pg
{ pgid
:: PageId
, referenced
:: Bool }
41 data Pageq
= Pgq
{ active
, inactive
:: PageList
}
44 data PageList = Pgl Int [Int]
45 pglenqueue x (Pgl n xs) = Pgl (n+1) (xs++[x])
46 pgldequeue (Pgl n (x:xs)) = (x, Pgl (n-1) xs)
50 data PageList
= Pgl
Int (Queue
Int)
51 pglenqueue x
(Pgl n q
) = Pgl
(n
+1) (addToQueue q x
)
52 pgldequeue
(Pgl n q
) = (x
, Pgl
(n
-1) nq
) where
53 Just
(x
,nq
) = deQueue q
55 pglempty
= Pgl
0 emptyQueue
58 instance Show Page where
59 show pg = "(" ++ (show $ pgid pg) ++ "," ++ (show $ referenced pg) ++ ")"
60 instance Show Pageq where
61 show q = "(act=" ++ (show $ active q) ++ ",inact=" ++ (show $ inactive q) ++ ")"
64 pglookup idx m
= Map
.lookup idx m
66 emptyq
= Pgq
{ active
= pglempty
, inactive
= pglempty
}
68 clrref pg
= pg
{ referenced
= False }
69 markref pg
= pg
{ referenced
= True }
71 clrrefm x m
= Map
.update
(Just
. clrref
) x m
73 reactivate
:: (Pageq
,Map
.Map
Int Page
) -> (Pageq
,Map
.Map
Int Page
)
74 reactivate
(q
,m
) = (nq
,nm
) where
75 nq
= q
{ active
= pglenqueue x
$ active q
, inactive
= niaq
}
77 (x
,niaq
) = pgldequeue
$ inactive q
78 reactivate_act
(q
,m
) = (nq
,nm
) where
79 nq
= q
{ active
= pglenqueue x
$ naq
}
81 (x
,naq
) = pgldequeue
$ active q
82 deactivate_act
(q
,m
) = (nq
,nm
) where
83 nq
= q
{ active
= naq
, inactive
= pglenqueue x
$ inactive q
}
85 (x
,naq
) = pgldequeue
$ active q
87 reclaim
:: Int -> (Pageq
,Map
.Map
Int Page
)->(Pageq
,Map
.Map
Int Page
)
90 reclaim pct
$ reactivate
(q
,m
)
92 (q
{ inactive
= npgl
},Map
.delete x m
)
94 (q
,m
) = fillinact pct
(q0
,m0
)
95 (x
,npgl
) = pgldequeue
$ inactive q
96 Just p
= Map
.lookup x m0
98 fillinact inactpct
(q
,m
) =
99 if inactlen
>= inacttarg
then (q
,m
) else
102 fillinact inactpct
$ reactivate_act
(q
,m
) else
104 fillinact inactpct
$ deactivate_act
(q
,m
)
106 Just p
= Map
.lookup x m
107 (x
,_
) = pgldequeue
$ active q
108 inactlen
= pglsize
$ inactive q
109 inacttarg
= div (Map
.size m
* inactpct
) 100
111 pgref
:: Int->Map
.Map
Int Page
-> Map
.Map
Int Page
112 pgref idx m
= Map
.update f idx m
where
115 do_nbsd1 npg pct n q m
[] = (reverse n
, q
)
116 do_nbsd1 npg pct n q m rs
@(r
:rs2
) =
121 do_nbsd1 npg pct n q
(pgref r m
) rs2
122 else if Map
.size m
< npg
then
123 do_nbsd1 npg pct
(r
:n
) (enqueue r q
) (pgenqueue r m
) rs2
126 (nq
, nm
) = reclaim pct
(q
,m
)
128 do_nbsd1 npg pct
(r
:n
) (enqueue r nq
) (pgenqueue r nm
) rs2
130 newpg i
= Pg
{pgid
= i
, referenced
= True}
131 pgenqueue i m
= Map
.insert i
(newpg i
) m
133 enqueue i q
= q
{ inactive
= pglenqueue i
$ inactive q
}
135 enqueue i q
= q
{ active
= pglenqueue i
$ active q
}
138 do_nbsd npg pct rs
= fst $ do_nbsd1 npg pct
[] emptyq Map
.empty rs
139 do_nbsd_dbg npg pct rs
= do_nbsd1 npg pct
[] emptyq Map
.empty rs
147 npgs
= read $ args
!! 0
148 pct
= read $ args
!! 1
151 mapM_ print $ do_nbsd npgs pct pgs