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