|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: ! 8: int canflush(Proc *p, Segment*); ! 9: void executeio(void); ! 10: int needpages(void*); ! 11: void pageout(Proc *p, Segment*); ! 12: void pagepte(int, Page**); ! 13: void pager(void*); ! 14: ! 15: Image swapimage; ! 16: static int swopen; ! 17: static Page **iolist; ! 18: static int ioptr; ! 19: static int maxpages; ! 20: ! 21: void ! 22: swapinit(void) ! 23: { ! 24: swapalloc.swmap = xalloc(conf.nswap); ! 25: swapalloc.top = &swapalloc.swmap[conf.nswap]; ! 26: swapalloc.alloc = swapalloc.swmap; ! 27: swapalloc.last = swapalloc.swmap; ! 28: swapalloc.free = conf.nswap; ! 29: maxpages = SEGMAXSIZE/BY2PG; ! 30: if(maxpages > conf.nswap/2) ! 31: maxpages = conf.nswap/2; ! 32: iolist = xalloc(maxpages*sizeof(Page*)); ! 33: if(swapalloc.swmap == 0 || iolist == 0) ! 34: panic("swapinit: not enough memory"); ! 35: } ! 36: ! 37: ulong ! 38: newswap(void) ! 39: { ! 40: uchar *look; ! 41: ! 42: lock(&swapalloc); ! 43: if(swapalloc.free == 0) ! 44: panic("out of swap space"); ! 45: ! 46: look = memchr(swapalloc.last, 0, swapalloc.top-swapalloc.last); ! 47: if(look == 0) ! 48: panic("inconsistent swap"); ! 49: ! 50: *look = 1; ! 51: swapalloc.last = look; ! 52: swapalloc.free--; ! 53: unlock(&swapalloc); ! 54: return (look-swapalloc.swmap) * BY2PG; ! 55: } ! 56: ! 57: void ! 58: putswap(Page *p) ! 59: { ! 60: uchar *idx; ! 61: ! 62: lock(&swapalloc); ! 63: idx = &swapalloc.swmap[((ulong)p)/BY2PG]; ! 64: if(--(*idx) == 0) { ! 65: swapalloc.free++; ! 66: if(idx < swapalloc.last) ! 67: swapalloc.last = idx; ! 68: } ! 69: unlock(&swapalloc); ! 70: } ! 71: ! 72: void ! 73: dupswap(Page *p) ! 74: { ! 75: lock(&swapalloc); ! 76: swapalloc.swmap[((ulong)p)/BY2PG]++; ! 77: unlock(&swapalloc); ! 78: } ! 79: ! 80: void ! 81: kickpager(void) ! 82: { ! 83: static int started; ! 84: ! 85: if(started) ! 86: wakeup(&swapalloc.r); ! 87: else { ! 88: kproc("pager", pager, 0); ! 89: started = 1; ! 90: } ! 91: } ! 92: ! 93: void ! 94: pager(void *junk) ! 95: { ! 96: int i; ! 97: Proc *p, *ep; ! 98: Segment *s, *ts; ! 99: ! 100: if(waserror()) ! 101: panic("pager: os error\n"); ! 102: ! 103: USED(junk); ! 104: p = proctab(0); ! 105: ep = &p[conf.nproc]; ! 106: ! 107: loop: ! 108: u->p->psstate = "Idle"; ! 109: sleep(&swapalloc.r, needpages, 0); ! 110: ! 111: while(needpages(junk)) { ! 112: p++; ! 113: if(p >= ep) ! 114: p = proctab(0); ! 115: ! 116: if(p->state == Dead || p->kp) ! 117: continue; ! 118: ! 119: /* don't swap out programs from devroot.c - they ! 120: * supply important system services ! 121: */ ! 122: ts = p->seg[TSEG]; ! 123: if(ts && ts->image && devchar[ts->image->c->type] == '/') ! 124: continue; ! 125: ! 126: if(swapimage.c) { ! 127: for(i = 0; i < NSEG; i++) { ! 128: if(!needpages(junk)) ! 129: goto loop; ! 130: ! 131: if(s = p->seg[i]) { ! 132: switch(s->type&SG_TYPE) { ! 133: default: ! 134: break; ! 135: case SG_TEXT: ! 136: pageout(p, s); ! 137: break; ! 138: case SG_DATA: ! 139: case SG_BSS: ! 140: case SG_STACK: ! 141: case SG_SHARED: ! 142: u->p->psstate = "Pageout"; ! 143: pageout(p, s); ! 144: if(ioptr != 0) { ! 145: u->p->psstate = "I/O"; ! 146: executeio(); ! 147: } ! 148: } ! 149: } ! 150: } ! 151: continue; ! 152: } ! 153: ! 154: if(palloc.freecount < swapalloc.highwater) { ! 155: if(!cpuserver) ! 156: freebroken(); /* can use the memory */ ! 157: ! 158: /* Emulate the old system if no swap channel */ ! 159: print("no physical memory\n"); ! 160: tsleep(&swapalloc.r, return0, 0, 1000); ! 161: wakeup(&palloc.r); ! 162: } ! 163: } ! 164: goto loop; ! 165: } ! 166: ! 167: void ! 168: pageout(Proc *p, Segment *s) ! 169: { ! 170: int type, i; ! 171: Pte *l; ! 172: Page **pg, *entry; ! 173: ! 174: if(!canqlock(&s->lk)) /* We cannot afford to wait, we will surely deadlock */ ! 175: return; ! 176: ! 177: if(s->steal) { /* Protected by /dev/proc */ ! 178: qunlock(&s->lk); ! 179: return; ! 180: } ! 181: ! 182: if(!canflush(p, s)) { /* Able to invalidate all tlbs with references */ ! 183: qunlock(&s->lk); ! 184: putseg(s); ! 185: return; ! 186: } ! 187: ! 188: if(waserror()) { ! 189: qunlock(&s->lk); ! 190: putseg(s); ! 191: return; ! 192: } ! 193: ! 194: /* Pass through the pte tables looking for memory pages to swap out */ ! 195: type = s->type&SG_TYPE; ! 196: for(i = 0; i < SEGMAPSIZE; i++) { ! 197: l = s->map[i]; ! 198: if(l == 0) ! 199: continue; ! 200: for(pg = l->first; pg < l->last; pg++) { ! 201: entry = *pg; ! 202: if(pagedout(entry)) ! 203: continue; ! 204: ! 205: if(entry->modref & PG_REF) { ! 206: entry->modref &= ~PG_REF; ! 207: continue; ! 208: } ! 209: ! 210: while(swapalloc.free == 0) { ! 211: if(ioptr != 0) ! 212: goto out; ! 213: ! 214: print("out of swap space\n"); ! 215: tsleep(&swapalloc.r, return0, 0, 1000); ! 216: } ! 217: ! 218: pagepte(type, pg); ! 219: ! 220: if(ioptr >= maxpages) ! 221: goto out; ! 222: } ! 223: } ! 224: out: ! 225: poperror(); ! 226: qunlock(&s->lk); ! 227: putseg(s); ! 228: wakeup(&palloc.r); ! 229: } ! 230: ! 231: int ! 232: canflush(Proc *p, Segment *s) ! 233: { ! 234: int i; ! 235: Proc *ep; ! 236: ! 237: lock(s); ! 238: if(s->ref == 1) { /* Easy if we are the only user */ ! 239: s->ref++; ! 240: unlock(s); ! 241: return canpage(p); ! 242: } ! 243: s->ref++; ! 244: unlock(s); ! 245: ! 246: /* Now we must do hardwork to ensure all processes which have tlb ! 247: * entries for this segment will be flushed if we suceed in pageing it out ! 248: */ ! 249: p = proctab(0); ! 250: ep = &p[conf.nproc]; ! 251: while(p < ep) { ! 252: if(p->state != Dead) { ! 253: for(i = 0; i < NSEG; i++) ! 254: if(p->seg[i] == s) ! 255: if(!canpage(p)) ! 256: return 0; ! 257: } ! 258: p++; ! 259: } ! 260: return 1; ! 261: } ! 262: ! 263: void ! 264: pagepte(int type, Page **pg) ! 265: { ! 266: ulong daddr; ! 267: Page *outp; ! 268: ! 269: outp = *pg; ! 270: switch(type) { ! 271: case SG_TEXT: /* Revert to demand load */ ! 272: putpage(outp); ! 273: *pg = 0; ! 274: break; ! 275: ! 276: case SG_DATA: ! 277: case SG_BSS: ! 278: case SG_STACK: ! 279: case SG_SHARED: ! 280: case SG_SHDATA: ! 281: daddr = newswap(); ! 282: cachedel(&swapimage, daddr); ! 283: lock(outp); ! 284: outp->ref++; ! 285: uncachepage(outp); ! 286: unlock(outp); ! 287: ! 288: /* Enter swap page into cache before segment is unlocked so that ! 289: * a fault will cause a cache recovery rather than a pagein on a ! 290: * partially written block. ! 291: */ ! 292: outp->daddr = daddr; ! 293: cachepage(outp, &swapimage); ! 294: *pg = (Page*)(daddr|PG_ONSWAP); ! 295: ! 296: /* Add me to IO transaction list */ ! 297: iolist[ioptr++] = outp; ! 298: } ! 299: } ! 300: ! 301: void ! 302: executeio(void) ! 303: { ! 304: Page *out; ! 305: int i, n; ! 306: Chan *c; ! 307: char *kaddr; ! 308: KMap *k; ! 309: ! 310: c = swapimage.c; ! 311: ! 312: for(i = 0; i < ioptr; i++) { ! 313: out = iolist[i]; ! 314: k = kmap(out); ! 315: kaddr = (char*)VA(k); ! 316: ! 317: if(waserror()) ! 318: panic("executeio: page out I/O error"); ! 319: ! 320: n = (*devtab[c->type].write)(c, kaddr, BY2PG, out->daddr); ! 321: if(n != BY2PG) ! 322: nexterror(); ! 323: ! 324: kunmap(k); ! 325: poperror(); ! 326: ! 327: /* Free up the page after I/O */ ! 328: lock(out); ! 329: out->ref--; ! 330: unlock(out); ! 331: putpage(out); ! 332: } ! 333: ioptr = 0; ! 334: } ! 335: ! 336: int ! 337: needpages(void *p) ! 338: { ! 339: USED(p); ! 340: return palloc.freecount < swapalloc.headroom; ! 341: } ! 342: ! 343: void ! 344: setswapchan(Chan *c) ! 345: { ! 346: if(swapimage.c) { ! 347: if(swapalloc.free != conf.nswap) ! 348: error(Einuse); ! 349: close(swapimage.c); ! 350: } ! 351: incref(c); ! 352: swapimage.c = c; ! 353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.