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