1 1.2 yamt /* $NetBSD: pdsim.c,v 1.2 2006/10/14 04:43:41 yamt Exp $ */ 2 1.1 yamt 3 1.1 yamt /*- 4 1.1 yamt * Copyright (c)2006 YAMAMOTO Takashi, 5 1.1 yamt * All rights reserved. 6 1.1 yamt * 7 1.1 yamt * Redistribution and use in source and binary forms, with or without 8 1.1 yamt * modification, are permitted provided that the following conditions 9 1.1 yamt * are met: 10 1.1 yamt * 1. Redistributions of source code must retain the above copyright 11 1.1 yamt * notice, this list of conditions and the following disclaimer. 12 1.1 yamt * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 yamt * notice, this list of conditions and the following disclaimer in the 14 1.1 yamt * documentation and/or other materials provided with the distribution. 15 1.1 yamt * 16 1.1 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 yamt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 yamt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 yamt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 yamt * SUCH DAMAGE. 27 1.1 yamt */ 28 1.1 yamt 29 1.1 yamt #include "pdsim.h" 30 1.1 yamt 31 1.1 yamt #define SHOWFAULT 32 1.1 yamt #if defined(SHOWQLEN) || defined(SHOWIRR) 33 1.1 yamt #undef SHOWFAULT 34 1.1 yamt #endif 35 1.1 yamt 36 1.1 yamt #undef READAHEAD 37 1.1 yamt 38 1.1 yamt struct vm_page *pages; 39 1.1 yamt 40 1.1 yamt struct uvmexp uvmexp; 41 1.1 yamt 42 1.1 yamt int npagein; 43 1.1 yamt int nfault; 44 1.1 yamt int raio; 45 1.1 yamt int rahit; 46 1.1 yamt 47 1.1 yamt int lastacc[MAXID]; 48 1.1 yamt int irr[MAXID]; 49 1.1 yamt int ts; 50 1.1 yamt 51 1.1 yamt struct { 52 1.1 yamt int fault; 53 1.1 yamt int hit; 54 1.1 yamt } stats[MAXID]; 55 1.1 yamt 56 1.1 yamt TAILQ_HEAD(, vm_page) freeq; 57 1.1 yamt 58 1.1 yamt struct vm_page * 59 1.1 yamt pdsim_pagealloc(struct uvm_object *obj, int idx) 60 1.1 yamt { 61 1.1 yamt struct vm_page *pg; 62 1.1 yamt 63 1.1 yamt pg = TAILQ_FIRST(&freeq); 64 1.1 yamt if (pg == NULL) { 65 1.1 yamt return NULL; 66 1.1 yamt } 67 1.1 yamt TAILQ_REMOVE(&freeq, pg, pageq); 68 1.1 yamt pg->offset = idx << PAGE_SHIFT; 69 1.1 yamt pg->uanon = NULL; 70 1.1 yamt pg->uobject = obj; 71 1.1 yamt pg->pqflags = 0; 72 1.1 yamt obj->pages[idx] = pg; 73 1.1 yamt uvmexp.free--; 74 1.1 yamt uvmexp.filepages++; 75 1.1 yamt 76 1.1 yamt return pg; 77 1.1 yamt } 78 1.1 yamt 79 1.1 yamt void 80 1.1 yamt pdsim_pagefree(struct vm_page *pg) 81 1.1 yamt { 82 1.1 yamt struct uvm_object *obj; 83 1.1 yamt 84 1.1 yamt KASSERT(pg != NULL); 85 1.1 yamt 86 1.1 yamt #if defined(SHOWFREE) 87 1.1 yamt if (pg->offset != -1) { 88 1.1 yamt int idx = pg->offset >> PAGE_SHIFT; 89 1.1 yamt printf("%d %d # FREE IRR\n", idx, irr[idx]); 90 1.1 yamt } 91 1.1 yamt #endif /* defined(SHOWFREE) */ 92 1.1 yamt 93 1.1 yamt uvmpdpol_pagedequeue(pg); 94 1.1 yamt 95 1.1 yamt KASSERT(pg->uanon == NULL); 96 1.1 yamt obj = pg->uobject; 97 1.1 yamt if (obj != NULL) { 98 1.1 yamt int idx; 99 1.1 yamt 100 1.1 yamt idx = pg->offset >> PAGE_SHIFT; 101 1.1 yamt KASSERT(obj->pages[idx] == pg); 102 1.1 yamt obj->pages[idx] = NULL; 103 1.1 yamt uvmexp.filepages--; 104 1.1 yamt } 105 1.1 yamt TAILQ_INSERT_HEAD(&freeq, pg, pageq); 106 1.1 yamt uvmexp.free++; 107 1.1 yamt } 108 1.1 yamt 109 1.1 yamt static struct vm_page * 110 1.1 yamt pdsim_pagelookup(struct uvm_object *obj, int index) 111 1.1 yamt { 112 1.1 yamt struct vm_page *pg; 113 1.1 yamt 114 1.1 yamt pg = obj->pages[index]; 115 1.1 yamt 116 1.1 yamt return pg; 117 1.1 yamt } 118 1.1 yamt 119 1.1 yamt static void 120 1.1 yamt pdsim_pagemarkreferenced(struct vm_page *pg) 121 1.1 yamt { 122 1.1 yamt 123 1.1 yamt pg->_mdflags |= MDPG_REFERENCED; 124 1.1 yamt } 125 1.1 yamt 126 1.1 yamt boolean_t 127 1.1 yamt pmap_is_referenced(struct vm_page *pg) 128 1.1 yamt { 129 1.1 yamt 130 1.1 yamt return pg->_mdflags & MDPG_REFERENCED; 131 1.1 yamt } 132 1.1 yamt 133 1.1 yamt boolean_t 134 1.1 yamt pmap_clear_reference(struct vm_page *pg) 135 1.1 yamt { 136 1.1 yamt boolean_t referenced = pmap_is_referenced(pg); 137 1.1 yamt 138 1.1 yamt pg->_mdflags &= ~MDPG_REFERENCED; 139 1.1 yamt 140 1.1 yamt return referenced; 141 1.1 yamt } 142 1.1 yamt 143 1.1 yamt static void 144 1.1 yamt pdsim_init(int n) 145 1.1 yamt { 146 1.1 yamt struct vm_page *pg; 147 1.1 yamt int i; 148 1.1 yamt 149 1.1 yamt uvmpdpol_init(); 150 1.1 yamt uvmexp.npages = n; 151 1.1 yamt uvmpdpol_reinit(); 152 1.1 yamt 153 1.1 yamt TAILQ_INIT(&freeq); 154 1.1 yamt pages = calloc(n, sizeof(*pg)); 155 1.1 yamt for (i = 0; i < n; i++) { 156 1.1 yamt pg = &pages[i]; 157 1.1 yamt pg->offset = -1; 158 1.1 yamt pdsim_pagefree(pg); 159 1.1 yamt } 160 1.1 yamt } 161 1.1 yamt 162 1.1 yamt static void 163 1.1 yamt pdsim_reclaimone(void) 164 1.1 yamt { 165 1.1 yamt struct vm_page *pg; 166 1.1 yamt 167 1.1 yamt uvmexp.freetarg = 1; 168 1.1 yamt while (uvmexp.free < uvmexp.freetarg) { 169 1.1 yamt uvmpdpol_tune(); 170 1.1 yamt uvmpdpol_scaninit(); 171 1.1 yamt pg = uvmpdpol_selectvictim(); 172 1.1 yamt if (pg != NULL) { 173 1.1 yamt pdsim_pagefree(pg); 174 1.1 yamt } 175 1.1 yamt uvmpdpol_balancequeue(0); 176 1.1 yamt } 177 1.1 yamt } 178 1.1 yamt 179 1.1 yamt static void 180 1.1 yamt fault(struct uvm_object *obj, int index) 181 1.1 yamt { 182 1.1 yamt struct vm_page *pg; 183 1.1 yamt 184 1.1 yamt DPRINTF("fault: %d -> ", index); 185 1.1 yamt nfault++; 186 1.1 yamt ts++; 187 1.1 yamt if (lastacc[index]) { 188 1.1 yamt irr[index] = ts - lastacc[index]; 189 1.1 yamt } 190 1.1 yamt lastacc[index] = ts; 191 1.1 yamt stats[index].fault++; 192 1.1 yamt pg = pdsim_pagelookup(obj, index); 193 1.1 yamt if (pg) { 194 1.1 yamt DPRINTF("cached\n"); 195 1.1 yamt pdsim_pagemarkreferenced(pg); 196 1.1 yamt stats[index].hit++; 197 1.1 yamt if ((pg->_mdflags & MDPG_SPECULATIVE) != 0) { 198 1.1 yamt pg->_mdflags &= ~MDPG_SPECULATIVE; 199 1.1 yamt rahit++; 200 1.1 yamt } 201 1.1 yamt return; 202 1.1 yamt } 203 1.1 yamt DPRINTF("miss\n"); 204 1.1 yamt retry: 205 1.1 yamt pg = pdsim_pagealloc(obj, index); 206 1.1 yamt if (pg == NULL) { 207 1.1 yamt pdsim_reclaimone(); 208 1.1 yamt goto retry; 209 1.1 yamt } 210 1.1 yamt npagein++; 211 1.1 yamt #if defined(SHOWFAULT) 212 1.1 yamt printf("%d # FLT\n", index); 213 1.1 yamt #endif 214 1.1 yamt pdsim_pagemarkreferenced(pg); 215 1.1 yamt uvmpdpol_pageactivate(pg); 216 1.1 yamt uvmpdpol_pageactivate(pg); 217 1.1 yamt dump("fault"); 218 1.1 yamt #if defined(READAHEAD) 219 1.1 yamt pg = pdsim_pagelookup(obj, index + 1); 220 1.1 yamt if (pg == NULL) { 221 1.1 yamt ra_retry: 222 1.1 yamt pg = pdsim_pagealloc(obj, index + 1); 223 1.1 yamt if (pg == NULL) { 224 1.1 yamt pdsim_reclaimone(); 225 1.1 yamt goto ra_retry; 226 1.1 yamt } 227 1.1 yamt raio++; 228 1.1 yamt pg->_mdflags |= MDPG_SPECULATIVE; 229 1.1 yamt #if defined(SHOWFAULT) 230 1.1 yamt printf("%d # READ-AHEAD\n", index + 1); 231 1.1 yamt #endif 232 1.1 yamt } 233 1.1 yamt uvmpdpol_pageenqueue(pg); 234 1.1 yamt dump("read-ahead"); 235 1.1 yamt #endif /* defined(READAHEAD) */ 236 1.1 yamt } 237 1.1 yamt 238 1.1 yamt struct uvm_object obj; 239 1.1 yamt 240 1.1 yamt static void 241 1.1 yamt test(void) 242 1.1 yamt { 243 1.1 yamt memset(&obj, 0, sizeof(obj)); 244 1.1 yamt char *ln; 245 1.1 yamt 246 1.1 yamt for (;; free(ln)) { 247 1.1 yamt int i; 248 1.1 yamt int ch; 249 1.1 yamt 250 1.1 yamt ln = fparseln(stdin, NULL, NULL, NULL, 0); 251 1.1 yamt if (ln == NULL) { 252 1.1 yamt break; 253 1.1 yamt } 254 1.1 yamt ch = *ln; 255 1.1 yamt if (ch == '\0') { 256 1.1 yamt break; 257 1.1 yamt } 258 1.1 yamt if (ch == 'd') { 259 1.1 yamt dump("test"); 260 1.1 yamt continue; 261 1.1 yamt } 262 1.1 yamt i = atoi(ln); 263 1.1 yamt fault(&obj, i); 264 1.1 yamt #if defined(SHOWQLEN) 265 1.1 yamt showqlen(); 266 1.1 yamt #endif 267 1.1 yamt } 268 1.1 yamt } 269 1.1 yamt 270 1.2 yamt #if defined(DEBUG) 271 1.1 yamt static void 272 1.1 yamt dumpstats(void) 273 1.1 yamt { 274 1.1 yamt int i; 275 1.1 yamt for (i = 0; i < MAXID; i++) { 276 1.1 yamt if (stats[i].fault == 0) { 277 1.1 yamt continue; 278 1.1 yamt } 279 1.1 yamt DPRINTF("[%d] %d/%d %d\n", i, 280 1.1 yamt stats[i].hit, stats[i].fault, irr[i]); 281 1.1 yamt } 282 1.1 yamt } 283 1.2 yamt #endif /* defined(DEBUG) */ 284 1.1 yamt 285 1.1 yamt int 286 1.1 yamt main(int argc, char *argv[]) 287 1.1 yamt { 288 1.1 yamt 289 1.1 yamt setvbuf(stderr, NULL, _IOFBF, 0); /* XXX */ 290 1.1 yamt 291 1.1 yamt pdsim_init(atoi(argv[1])); 292 1.1 yamt test(); 293 1.1 yamt DPRINTF("io %d (%d + ra %d) / flt %d\n", 294 1.1 yamt npagein + raio, npagein, raio, nfault); 295 1.1 yamt DPRINTF("rahit / raio= %d / %d\n", rahit, raio); 296 1.1 yamt #if defined(DEBUG) 297 1.1 yamt dumpstats(); 298 1.1 yamt #endif 299 1.1 yamt exit(0); 300 1.1 yamt } 301