lirs.c revision 1.1 1 /* $NetBSD: lirs.c,v 1.1 2006/10/09 12:32:46 yamt Exp $ */
2
3 /*-
4 * Copyright (c)2005 YAMAMOTO Takashi,
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/queue.h>
30
31 #include <assert.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #if defined(DEBUG)
36 #define DFPRINTF(...) fprintf(__VA_ARGS__)
37 #else
38 #define DFPRINTF(...) /* nothing */
39 #endif
40
41 #define MAXID 102400
42
43 struct buf {
44 TAILQ_ENTRY(buf) b_s;
45 TAILQ_ENTRY(buf) b_q;
46 int b_type;
47 #define B_L 1
48 #define B_H 2
49 #define B_R 4
50 int b_flags;
51 #define B_S 8
52 int b_irr;
53 int b_lastts;
54 };
55
56 struct buf bufs[MAXID];
57
58 TAILQ_HEAD(, buf) q_q;
59 TAILQ_HEAD(, buf) q_s;
60
61 int nlirs_max = 2;
62 int nbufs_max = 3;
63 int nlirs;
64 int nbufs;
65
66 void buf_print(struct buf *, char *);
67
68 void
69 buf_print(struct buf *bp, char *s)
70 {
71
72 DFPRINTF(stderr, "%d(%s,%s,%d)%s", (bp - bufs),
73 (bp->b_type == B_L) ? "L" :
74 (bp->b_type == (B_H | B_R)) ? "HR" :
75 (bp->b_type == B_H) ? "H" :
76 (bp->b_type == 0) ? "free" :
77 "unknown",
78 (bp->b_flags & B_S) ? "S" : "",
79 bp->b_irr,
80 s);
81 }
82
83 void
84 dump()
85 {
86 #if defined(DEBUG)
87 struct buf *bp;
88 int i;
89
90 DFPRINTF(stderr, "S: ");
91 TAILQ_FOREACH(bp, &q_s, b_s) {
92 buf_print(bp, " ");
93 }
94 DFPRINTF(stderr, "\n");
95
96 DFPRINTF(stderr, "Q: ");
97 TAILQ_FOREACH(bp, &q_q, b_q) {
98 buf_print(bp, " ");
99 }
100 DFPRINTF(stderr, "\n");
101
102 #if 0
103 for (i = 0; i < 256; i++) {
104
105 bp = &bufs[i];
106 if (bufs->b_type == 0) {
107 continue;
108 }
109 }
110 #endif
111
112 DFPRINTF(stderr, "nlirs=%d, nbufs=%d\n", nlirs, nbufs);
113 #endif /* defined(DEBUG) */
114 }
115
116 void
117 reclaim()
118 {
119 struct buf *bp;
120
121 if (nbufs <= nbufs_max) {
122 return;
123 }
124
125 bp = TAILQ_FIRST(&q_q);
126 buf_print(bp, ": reclaim\n");
127 assert(bp->b_type == B_H | B_R);
128 TAILQ_REMOVE(&q_q, bp, b_q);
129 bp->b_type &= ~B_R;
130 nbufs--;
131 }
132
133 void
134 prune()
135 {
136
137 while (1) {
138 struct buf *bp;
139
140 bp = TAILQ_FIRST(&q_s);
141 if (bp->b_type == B_L) {
142 break;
143 }
144 buf_print(bp, ": prune\n");
145 TAILQ_REMOVE(&q_s, bp, b_s);
146 assert(bp->b_flags & B_S);
147 bp->b_flags &= ~B_S;
148 if ((bp->b_type & B_R) == 0) {
149 bp->b_type &= ~B_H;
150 }
151 }
152 }
153
154 void
155 reclaim_l()
156 {
157 struct buf *bp;
158
159 if (nlirs <= nlirs_max) {
160 return;
161 }
162
163 bp = TAILQ_FIRST(&q_s);
164 buf_print(bp, ": reclaim_l\n");
165 assert(bp->b_type == B_L);
166 assert(bp->b_flags & B_S);
167 bp->b_type = B_H | B_R;
168 bp->b_flags &= ~B_S;
169 TAILQ_REMOVE(&q_s, bp, b_s);
170 TAILQ_INSERT_TAIL(&q_q, bp, b_q);
171 nlirs--;
172 prune();
173 }
174
175 void
176 init(int n)
177 {
178
179 TAILQ_INIT(&q_q);
180 TAILQ_INIT(&q_s);
181 memset(&bufs, 0, sizeof(bufs));
182 nbufs_max = n;
183 #if 0
184 nlirs_max = nbufs_max * 2 / 3;
185 #else
186 nlirs_max = nbufs_max * 90 / 100;
187 #endif
188 }
189
190 struct object {int dummy;};
191 int ts = 1;
192
193 void
194 fault(struct object *dummy, int i)
195 {
196 struct buf *bp;
197
198 DFPRINTF(stderr, "----------\n");
199 dump();
200
201 DFPRINTF(stderr, "---------- ts %d\n", ts);
202
203 bp = &bufs[i];
204 buf_print(bp, ": access\n");
205 if (bp->b_type == 0) {
206 bp->b_irr = -1;
207 } else {
208 bp->b_irr = ts - bp->b_lastts - 1;
209 }
210 bp->b_lastts = ts;
211
212 if (bp->b_type == B_L) {
213 assert(bp->b_flags & B_S);
214 TAILQ_REMOVE(&q_s, bp, b_s);
215 TAILQ_INSERT_TAIL(&q_s, bp, b_s);
216 prune();
217 goto done;
218 }
219 if (bp->b_type == (B_H | B_R)) {
220 if (bp->b_flags & B_S) {
221 TAILQ_REMOVE(&q_s, bp, b_s);
222 TAILQ_REMOVE(&q_q, bp, b_q);
223 bp->b_type = B_L;
224 nlirs++;
225 reclaim_l();
226 } else {
227 TAILQ_REMOVE(&q_q, bp, b_q);
228 TAILQ_INSERT_TAIL(&q_q, bp, b_q);
229 }
230 TAILQ_INSERT_TAIL(&q_s, bp, b_s);
231 bp->b_flags |= B_S;
232 goto done;
233 }
234 nbufs++;
235 reclaim();
236 if ((bp->b_flags & (B_R | B_L)) == 0) {
237 printf("%d\n", i);
238 }
239 if (bp->b_type == 0) {
240 buf_print(bp, ": new\n");
241 if (nlirs < nlirs_max) {
242 bp->b_type = B_L;
243 TAILQ_INSERT_TAIL(&q_s, bp, b_s);
244 bp->b_flags |= B_S;
245 nlirs++;
246 } else {
247 bp->b_type = B_H;
248 }
249 }
250 if (bp->b_type == B_H) {
251 if (bp->b_flags & B_S) {
252 TAILQ_REMOVE(&q_s, bp, b_s);
253 bp->b_type = B_L;
254 nlirs++;
255 reclaim_l();
256 } else {
257 bp->b_type |= B_R;
258 TAILQ_INSERT_TAIL(&q_q, bp, b_q);
259 }
260 TAILQ_INSERT_TAIL(&q_s, bp, b_s);
261 bp->b_flags |= B_S;
262 }
263 done:
264 ts++;
265 }
266
267 void
268 test(void)
269 {
270 struct object obj;
271 memset(&obj, 0, sizeof(obj));
272 char *ln;
273
274 for (;; free(ln)) {
275 int i;
276 int ch;
277
278 ln = fparseln(stdin, NULL, NULL, NULL, 0);
279 if (ln == NULL) {
280 break;
281 }
282 ch = *ln;
283 if (ch == '\0') {
284 break;
285 }
286 #if 1
287 if (ch == 'd') {
288 dump();
289 continue;
290 }
291 #endif
292 i = atoi(ln);
293 fault(&obj, i);
294 }
295 }
296
297 int
298 main(int argc, char *argv[])
299 {
300
301 init(atoi(argv[1]));
302 test();
303 exit(0);
304 }
305