xref: /netbsd/regress/sys/uvm/pdsim/lirs.c (revision 6550d01e)
1 /*	$NetBSD: lirs.c,v 1.3 2006/10/09 12:43:32 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 #include <string.h>
35 
36 #if defined(DEBUG)
37 #define	DFPRINTF(...)	fprintf(__VA_ARGS__)
38 #else
39 #define	DFPRINTF(...)	/* nothing */
40 #endif
41 
42 #define	MAXID	102400
43 
44 struct buf {
45 	TAILQ_ENTRY(buf) b_s;
46 	TAILQ_ENTRY(buf) b_q;
47 	int b_type;
48 #define	B_L	1
49 #define	B_H	2
50 #define	B_R	4
51 	int b_flags;
52 #define B_S	8
53 	int b_irr;
54 	int b_lastts;
55 };
56 
57 struct buf bufs[MAXID];
58 
59 TAILQ_HEAD(, buf) q_q;
60 TAILQ_HEAD(, buf) q_s;
61 
62 int nlirs_max = 2;
63 int nbufs_max = 3;
64 int nlirs;
65 int nbufs;
66 
67 void buf_print(struct buf *, char *);
68 
69 void
70 buf_print(struct buf *bp, char *s)
71 {
72 
73 	DFPRINTF(stderr, "%d(%s,%s,%d)%s", (bp - bufs),
74 	    (bp->b_type == B_L) ? "L" :
75 	    (bp->b_type == (B_H | B_R)) ? "HR" :
76 	    (bp->b_type == B_H) ? "H" :
77 	    (bp->b_type == 0) ? "free" :
78 	    "unknown",
79 	    (bp->b_flags & B_S) ? "S" : "",
80 	    bp->b_irr,
81 	    s);
82 }
83 
84 void
85 dump()
86 {
87 #if defined(DEBUG)
88 	struct buf *bp;
89 	int i;
90 
91 	DFPRINTF(stderr, "S: ");
92 	TAILQ_FOREACH(bp, &q_s, b_s) {
93 		buf_print(bp, " ");
94 	}
95 	DFPRINTF(stderr, "\n");
96 
97 	DFPRINTF(stderr, "Q: ");
98 	TAILQ_FOREACH(bp, &q_q, b_q) {
99 		buf_print(bp, " ");
100 	}
101 	DFPRINTF(stderr, "\n");
102 
103 #if 0
104 	for (i = 0; i < 256; i++) {
105 
106 		bp = &bufs[i];
107 		if (bufs->b_type == 0) {
108 			continue;
109 		}
110 	}
111 #endif
112 
113 	DFPRINTF(stderr, "nlirs=%d, nbufs=%d\n", nlirs, nbufs);
114 #endif /* defined(DEBUG) */
115 }
116 
117 void
118 reclaim()
119 {
120 	struct buf *bp;
121 
122 	if (nbufs <= nbufs_max) {
123 		return;
124 	}
125 
126 	bp = TAILQ_FIRST(&q_q);
127 	buf_print(bp, ": reclaim\n");
128 	assert(bp->b_type == (B_H | B_R));
129 	TAILQ_REMOVE(&q_q, bp, b_q);
130 	bp->b_type &= ~B_R;
131 	nbufs--;
132 }
133 
134 void
135 prune()
136 {
137 
138 	while (1) {
139 		struct buf *bp;
140 
141 		bp = TAILQ_FIRST(&q_s);
142 		if (bp->b_type == B_L) {
143 			break;
144 		}
145 		buf_print(bp, ": prune\n");
146 		TAILQ_REMOVE(&q_s, bp, b_s);
147 		assert(bp->b_flags & B_S);
148 		bp->b_flags &= ~B_S;
149 		if ((bp->b_type & B_R) == 0) {
150 			bp->b_type &= ~B_H;
151 		}
152 	}
153 }
154 
155 void
156 reclaim_l()
157 {
158 	struct buf *bp;
159 
160 	if (nlirs <= nlirs_max) {
161 		return;
162 	}
163 
164 	bp = TAILQ_FIRST(&q_s);
165 	buf_print(bp, ": reclaim_l\n");
166 	assert(bp->b_type == B_L);
167 	assert(bp->b_flags & B_S);
168 	bp->b_type = B_H | B_R;
169 	bp->b_flags &= ~B_S;
170 	TAILQ_REMOVE(&q_s, bp, b_s);
171 	TAILQ_INSERT_TAIL(&q_q, bp, b_q);
172 	nlirs--;
173 	prune();
174 }
175 
176 void
177 init(int n)
178 {
179 
180 	TAILQ_INIT(&q_q);
181 	TAILQ_INIT(&q_s);
182 	memset(&bufs, 0, sizeof(bufs));
183 	nbufs_max = n;
184 #if 0
185 	nlirs_max = nbufs_max * 2 / 3;
186 #else
187 	nlirs_max = nbufs_max * 90 / 100;
188 #endif
189 }
190 
191 struct object {int dummy;};
192 int ts = 1;
193 
194 void
195 fault(struct object *dummy, int i)
196 {
197 	struct buf *bp;
198 
199 	DFPRINTF(stderr, "----------\n");
200 	dump();
201 
202 	DFPRINTF(stderr, "---------- ts %d\n", ts);
203 
204 	bp = &bufs[i];
205 	buf_print(bp, ": access\n");
206 	if (bp->b_type == 0) {
207 		bp->b_irr = -1;
208 	} else {
209 		bp->b_irr = ts - bp->b_lastts - 1;
210 	}
211 	bp->b_lastts = ts;
212 
213 	if (bp->b_type == B_L) {
214 		assert(bp->b_flags & B_S);
215 		TAILQ_REMOVE(&q_s, bp, b_s);
216 		TAILQ_INSERT_TAIL(&q_s, bp, b_s);
217 		prune();
218 		goto done;
219 	}
220 	if (bp->b_type == (B_H | B_R)) {
221 		if (bp->b_flags & B_S) {
222 			TAILQ_REMOVE(&q_s, bp, b_s);
223 			TAILQ_REMOVE(&q_q, bp, b_q);
224 			bp->b_type = B_L;
225 			nlirs++;
226 			reclaim_l();
227 		} else {
228 			TAILQ_REMOVE(&q_q, bp, b_q);
229 			TAILQ_INSERT_TAIL(&q_q, bp, b_q);
230 		}
231 		TAILQ_INSERT_TAIL(&q_s, bp, b_s);
232 		bp->b_flags |= B_S;
233 		goto done;
234 	}
235 	nbufs++;
236 	reclaim();
237 	if ((bp->b_flags & (B_R | B_L)) == 0) {
238 		printf("%d\n", i);
239 	}
240 	if (bp->b_type == 0) {
241 		buf_print(bp, ": new\n");
242 		if (nlirs < nlirs_max) {
243 			bp->b_type = B_L;
244 			TAILQ_INSERT_TAIL(&q_s, bp, b_s);
245 			bp->b_flags |= B_S;
246 			nlirs++;
247 		} else {
248 			bp->b_type = B_H;
249 		}
250 	}
251 	if (bp->b_type == B_H) {
252 		if (bp->b_flags & B_S) {
253 			TAILQ_REMOVE(&q_s, bp, b_s);
254 			bp->b_type = B_L;
255 			nlirs++;
256 			reclaim_l();
257 		} else {
258 			bp->b_type |= B_R;
259 			TAILQ_INSERT_TAIL(&q_q, bp, b_q);
260 		}
261 		TAILQ_INSERT_TAIL(&q_s, bp, b_s);
262 		bp->b_flags |= B_S;
263 	}
264 done:
265 	ts++;
266 }
267 
268 void
269 test(void)
270 {
271 	struct object obj;
272 	memset(&obj, 0, sizeof(obj));
273 	char *ln;
274 
275 	for (;; free(ln)) {
276 		int i;
277 		int ch;
278 
279 		ln = fparseln(stdin, NULL, NULL, NULL, 0);
280 		if (ln == NULL) {
281 			break;
282 		}
283 		ch = *ln;
284 		if (ch == '\0') {
285 			break;
286 		}
287 #if 1
288 		if (ch == 'd') {
289 			dump();
290 			continue;
291 		}
292 #endif
293 		i = atoi(ln);
294 		fault(&obj, i);
295 	}
296 }
297 
298 int
299 main(int argc, char *argv[])
300 {
301 
302 	init(atoi(argv[1]));
303 	test();
304 	exit(0);
305 }
306