## diffname port/page.c 1990/0227 ## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/page.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" struct { Lock; ulong addr; int active; Page *page; /* base of Page structures, indexed by phys addr */ ulong minppn; /* index of first usable page */ Page *head; /* most recently used */ Page *tail; /* least recently used */ }palloc; struct { Lock; Orig *arena; Orig *free; }origalloc; typedef union PTEA PTEA; union PTEA{ PTE; struct{ ulong n; /* for growpte */ Orig *o; /* for growpte */ PTEA *next; /* for newmod */ }; }; struct { Lock; PTEA *arena; PTEA *free; PTEA *end; }ptealloc; struct{ Lock; PTEA *free; }modalloc; /* * Called to allocate permanent data structures, before calling pageinit(). */ void* ialloc(ulong n, int align) { ulong p; if(palloc.active) print("ialloc bad\n"); if(palloc.addr == 0) palloc.addr = ((ulong)&end)&~KZERO; if(align){ palloc.addr += BY2PG-1; palloc.addr &= ~(BY2PG-1); } memset((void*)(palloc.addr|KZERO), 0, n); p = palloc.addr; palloc.addr += n; if(align){ palloc.addr += BY2PG-1; palloc.addr &= ~(BY2PG-1); } return (void*)(p|KZERO); } void audit(char *s) { int nf, nb; Page *p; static int here; do;while(here); here=1; p = palloc.head; nf=nb=0; while(p){ print("%lux %lux %d\n", p->pa, p->va, p->ref); if(p->o) print("\t%d %lux %c\n", p->o->nproc, p->o->qid, devchar[p->o->type]); delay(100); nf++; p = p->next; } p = palloc.tail; while(p){ nb++; p = p->prev; } print("%s: nf: %d nb: %d\n", s, nf, nb); delay(1000); here=0; } void pageinit(void) { ulong pa, nb, ppn; ulong i; Page *p; PTEA *pte; Orig *o; ptealloc.arena = ialloc(conf.npte*sizeof(PTEA), 0); ptealloc.free = ptealloc.arena; ptealloc.end = ptealloc.arena+conf.npte; modalloc.free = ialloc(conf.nmod*sizeof(PTEA), 0); pte = modalloc.free; for(i=0; inext = pte+1; pte->next = 0; origalloc.free = ialloc(conf.norig*sizeof(Orig), 0); origalloc.arena = origalloc.free; o = origalloc.free; for(i=0; inext = o+1; o->next = 0; palloc.active = 1; nb = (conf.npage<>PGSHIFT)*sizeof(Page); /* safe overestimate */ nb &= ~(BY2PG-1); pa = (conf.npage<> PGSHIFT; /* physical page number of first free page */ palloc.page = (Page *)((palloc.addr - ppn*sizeof(Page))|KZERO); /* * Now palloc.page[ppn] describes first free page */ palloc.minppn = ppn; palloc.addr = ppn<next = p+1; p->prev = p-1; p->pa = ppn<prev = 0; palloc.tail->next = 0; } Page* newpage(int noclear, Orig *o, ulong va) { Page *p; Orig *o1; if(palloc.active == 0) print("newpage inactive\n"); loop: lock(&palloc); for(p=palloc.tail; p; p=p->prev){ if(p->ref == 0) goto out; #ifdef asdf if(p->ref == 1){ /* a pageout daemon should do this */ o1 = p->o; if(o1 && o1->nproc==0 && canlock(o1)){ if(o1->nproc){ unlock(o1); continue; } print("free %d pages va %lux %lux %c\n", o1->npage, o->va, o1->qid, devchar[o1->type]); freepage(o1); /* neworig will free the orig and pte's later */ unlock(o1); if(p->ref == 0) goto out; print("newpage ref != 0"); } } #endif } audit("newpage"); print("no physical memory\n"); unlock(&palloc); if(u == 0) panic("newpage"); u->p->state = Wakeme; alarm(1000, wakeme, u->p); sched(); goto loop; out: if(p->o){ print("page in use %lux %lux %lux\n", p->va, p->o, origalloc.arena); print("%c %lux %lux, %d %d %d\n", devchar[p->o->type], p->o->va, p->o->qid, p->o->flag, p->o->nproc, p->o->npte); panic("shit"); } p->ref = 1; usepage(p, 0); unlock(&palloc); if(!noclear) memset((void*)(p->pa|KZERO), 0, BY2PG); p->o = o; p->va = va; return p; } /* * Move page to head of list */ void usepage(Page *p, int dolock) { if(dolock) lock(&palloc); /* * Unlink */ if(p->prev) p->prev->next = p->next; else palloc.head = p->next; if(p->next) p->next->prev = p->prev; else palloc.tail = p->prev; /* * Link */ p->next = palloc.head; p->prev = 0; if(p->next) p->next->prev = p; else palloc.tail = p; palloc.head = p; if(dolock) unlock(&palloc); } Orig* lookorig(ulong va, ulong npte, int flag, Chan *c) { Orig *o; ulong i; for(o=origalloc.arena,i=0; inpage && o->qid==c->qid && o->va==va){ lock(o); if(o->npage && o->qid==c->qid) if(o->va==va && o->npte==npte && o->flag==flag) if(o->type==c->type && o->dev==c->dev){ if(o->chan == 0){ o->chan = c; incref(c); } o->nproc++; unlock(o); return o; } unlock(o); } return 0; } Orig* neworig(ulong va, ulong npte, int flag, Chan *c) { Orig *o; int i, freed; lock(&origalloc); loop: if(o = origalloc.free){ /* assign = */ origalloc.free = o->next; o->va = va; o->pte = 0; o->flag = flag; o->nproc = 1; o->npage = 0; o->chan = c; if(c){ o->type = c->type; o->dev = c->dev; o->qid = c->qid; incref(c); }else{ o->type = -1; o->dev = -1; o->qid = -1; } growpte(o, npte); unlock(&origalloc); return o; } /* * This is feeble. Orig's should perhaps be held in * an LRU list. This algorithm is too aggressive. */ freed = 0; for(o=origalloc.arena,i=0; inproc==0 && canlock(o)){ if(o->nproc){ unlock(o); continue; } freepage(o); freepte(o); unlock(o); o->next = origalloc.free; origalloc.free = o; freed++; } } if(freed) goto loop; print("no origs freed\n"); unlock(&origalloc); if(u == 0) panic("neworig"); u->p->state = Wakeme; alarm(1000, wakeme, u->p); sched(); lock(&origalloc); goto loop; } PTE* newmod(void) { PTEA *pte; loop: lock(&modalloc); if(pte = modalloc.free){ /* assign = */ modalloc.free = pte->next; unlock(&modalloc); memset(pte, 0, sizeof(PTE)); return pte; } unlock(&modalloc); print("no mods\n"); if(u == 0) panic("newmod"); u->p->state = Wakeme; alarm(1000, wakeme, u->p); sched(); goto loop; } /* * Duplicate mod structure for this segment (old) in new process p. * old->o must be locked. */ void forkmod(Seg *old, Seg *new, Proc *p) { Orig *o; PTE *pte, *ppte, *opte, *npte; ulong va; o = old->o; ppte = 0; pte = old->mod; while(pte){ if(pte->page==0) panic("forkmod zero page"); if(pte->proc != u->p) panic("forkmod wrong page"); npte = newmod(); npte->proc = p; npte->page = pte->page; pte->page->ref++; o->npage++; /* * Link into mod list for this va */ npte->nextmod = pte->nextmod; pte->nextmod = npte; /* * Link into mod list for new segment */ if(ppte == 0) new->mod = npte; else ppte->nextva = npte; npte->nextva = 0; ppte = npte; pte = pte->nextva; } } void freesegs(int save) { int i, j; Seg *s; Orig *o; PTE *pte, *opte; PTEA *old; Page *pg; Chan *c; s = u->p->seg; for(i=0; io; if(o == 0) continue; lock(o); if(pte = s->mod){ /* assign = */ while(pte){ opte = &o->pte[(pte->page->va-o->va)>>PGSHIFT]; while(opte->nextmod != pte){ if(opte->page && opte->page->va != pte->page->va) panic("pte %lux %lux\n", opte->page->va, pte->page->va); opte = opte->nextmod; if(opte == 0) panic("freeseg opte==0"); } opte->nextmod = pte->nextmod; pg = pte->page; if(pg->ref == 1){ pte->page = 0; pg->o = 0; } pg->ref--; o->npage--; old = (PTEA*)pte; pte = pte->nextva; lock(&modalloc); old->next = modalloc.free; modalloc.free = old; unlock(&modalloc); } } o->nproc--; if(o->nproc == 0){ if(c = o->chan){ /* assign = */ o->chan = 0; close(c); } if(!(o->flag&OCACHED) || o->npage==0){ freepage(o); freepte(o); unlock(o); lock(&origalloc); o->next = origalloc.free; origalloc.free = o; unlock(&origalloc); }else unlock(o); }else{ /* * BUG: there is a leak here. if the origin pte is being used only * by the exiting process, the associated page will linger. the fix * is to remember either the length of the mod list at each va or * the number of processes sharing the origin pte, and to promote one * of the mods to the origin pte when no process is left using the * origin pte. */ unlock(o); } } } /* * Adjust segment to desired size. This implementation is rudimentary. */ int segaddr(Seg *s, ulong min, ulong max) { Orig *o; if(max < min) return 0; if(min != s->minva) /* can't grow down yet (stacks: fault.c) */ return 0; max = (max+(BY2PG-1)) & ~(BY2PG-1); o = s->o; if(max == s->maxva) return 1; if(max > s->maxva){ /* * Grow */ /* BUG: check spill onto other segments */ if(o->va+BY2PG*o->npte < max) growpte(o, (max-o->va)>>PGSHIFT); s->maxva = max; return 1; } /* * Shrink */ print("segaddr shrink"); for(;;); } /* * o is locked */ void freepage(Orig *o) { PTE *pte; Page *pg; int i; pte = o->pte; for(i=0; inpte; i++,pte++) if(pg = pte->page){ /* assign = */ if(pg->ref == 1){ pte->page = 0; pg->o = 0; } pg->ref--; } o->npage = 0; } /* * Compacting allocator */ void freepte(Orig *o) /* o is locked */ { PTEA *p; p = (PTEA*)(o->pte - 1); p->o = 0; } void growpte(Orig *o, ulong n) { PTEA *p; ulong nfree; lock(&ptealloc); lock(o); if(o->pte){ if(o->npte == n) panic("growpte pointless"); p = (PTEA*)(o->pte - 1); if(o->npte > n){ nfree = o->npte - n; p->n -= nfree; o->npte -= nfree; p += p->n; p->o = 0; p->n = nfree; }else{ n++; if(p+p->n == ptealloc.free){ compactpte(o, n - p->n); p = (PTEA*)(o->pte - 1); ptealloc.free += n - p->n; }else{ compactpte(o, n); p = ptealloc.free; ptealloc.free += n; memcpy(p+1, o->pte, o->npte*sizeof(PTE)); p->o = o; ((PTEA*)(o->pte-1))->o = 0; o->pte = p+1; } memset(p+1+o->npte, 0, (n-(1+o->npte))*sizeof(PTE)); p->n = n; o->npte = n-1; } unlock(o); unlock(&ptealloc); return; } n++; compactpte(o, n); p = ptealloc.free; ptealloc.free += n; memset(p, 0, n*sizeof(PTE)); p->n = n; p->o = o; o->pte = p+1; o->npte = n-1; unlock(o); unlock(&ptealloc); } void compactpte(Orig *o, ulong n) { PTEA *p1, *p2; Orig *p2o; if(ptealloc.end-ptealloc.free >= n) return; p1 = ptealloc.arena; /* dest */ p2 = ptealloc.arena; /* source */ while(p2 < ptealloc.free){ p2o = p2->o; if(p2o == 0){ Free: p2 += p2->n; continue; } if(p1 != p2){ if(p2o != o) lock(p2o); if(p2->o != p2o){ /* freepte()d very recently */ if(p2->o) panic("compactpte p2->o %lux\n", p2->o); unlock(p2o); goto Free; } memcpy(p1, p2, p2->n*sizeof(PTE)); p2o->pte = p1+1; if(p2o != o) unlock(p2o); } p2 += p1->n; p1 += p1->n; } ptealloc.free = p1; if(ptealloc.end-ptealloc.free >= n) return; unlock(o); unlock(&ptealloc); panic("compactpte %d %lux %d", n, o->va, o->npte); } . ## diffname port/page.c 1990/0303 ## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/page.c /n/bootesdump/1990/0303/sys/src/9/mips/page.c 298a o->mqid = -1; o->mchan = 0; . 297d 293a o->mchan = c->mchan; o->mqid = c->mqid; . 292d 260c if(o->mchan==c->mchan && o->mqid==c->mqid && o->type==c->type){ . 190d 101c here=0; . 88,90c print("%lux %lux %d\n", p->pa, p->va, p->ref); if(p->o){ print("\t%d %lux %c\n", p->o->nproc, p->o->qid, devchar[p->o->type]); delay(100); /* let it drain; there's a lot here */ } . 81,84c do;while(here); here=1; . 79a static int here; . ## diffname port/page.c 1990/0312 ## diff -e /n/bootesdump/1990/0303/sys/src/9/mips/page.c /n/bootesdump/1990/0312/sys/src/9/mips/page.c 437a o->nmod--; . 378a o->nmod++; . 352a DEBUG(); panic("mods"); . 289a o->nmod = 0; . ## diffname port/page.c 1990/0409 ## diff -e /n/bootesdump/1990/0312/sys/src/9/mips/page.c /n/bootesdump/1990/0409/sys/src/9/mips/page.c 191a pprint("no physical memory\n"); . ## diffname port/page.c 1990/0617 ## diff -e /n/bootesdump/1990/0409/sys/src/9/mips/page.c /n/bootesdump/1990/0617/sys/src/9/mips/page.c 209,210c if(!noclear){ k = kmap(p); memset((void*)VA(k), 0, BY2PG); kunmap(k); } . 163a KMap *k; . 13c Page *page; /* base of Page structures, indexed by phys page number */ . ## diffname port/page.c 1990/0720 ## diff -e /n/bootesdump/1990/0617/sys/src/9/mips/page.c /n/bootesdump/1990/0720/sys/src/9/mips/page.c 495a if(max > 20*1024*1024) pprint("segaddr %lux\n", max); . ## diffname port/page.c 1990/0728 ## diff -e /n/bootesdump/1990/0720/sys/src/9/mips/page.c /n/bootesdump/1990/0728/sys/src/9/mips/page.c 604a Return: . 592,594c goto Return; . 566a print("growpte shrink"); goto Return; . 563,564c if(o->npte == n){ if(u && u->p) print("%s: ", u->p->text); print("growpte pointless\n"); goto Return; } . ## diffname port/page.c 1990/0801 ## diff -e /n/bootesdump/1990/0728/sys/src/9/mips/page.c /n/bootesdump/1990/0801/sys/src/9/mips/page.c 533a unusepage(pg, 1); . 496c if(max > 20*1024*1024) {pprint("segaddr %lux\n", max);print("segaddr %lux\n", max);} . 253a /* * Move page to tail of list */ void unusepage(Page *p, int dolock) { return; if(dolock) lock(&palloc); /* * Unlink */ if(p->prev) p->prev->next = p->next; else palloc.head = p->next; if(p->next) p->next->prev = p->prev; else palloc.tail = p->prev; /* * Link */ p->prev = palloc.tail; p->next = 0; if(p->prev) p->prev->next = p; else palloc.head = p; palloc.tail = p; if(dolock) unlock(&palloc); } . ## diffname port/page.c 1990/0802 ## diff -e /n/bootesdump/1990/0801/sys/src/9/mips/page.c /n/bootesdump/1990/0802/sys/src/9/mips/page.c 687c if(u && u->p) print("%s: %s: ", u->p->text, u->p->pgrp->user); print("compactpte fails addr %lux\n", o->va+n*BY2PG); return 0; . 684c return 1; . 655c return 1; . 648c int . 645a return; Trouble: unlock(&ptealloc); if(u && u->p) error(0, Enovmem); panic("growpte fails %d %lux %d\n", n, o->va, o->npte); . 644d 635c if(!compactpte(o, n)) goto Trouble; . 620c if(!compactpte(o, n)) goto Trouble; . 616c if(!compactpte(o, n - p->n)) goto Trouble; . 596d 543a unlock(o); poperror(); . 541a lock(o); if(waserror()){ unlock(o); nexterror(); } . 530d 342a if(u && u->p) poperror(); unlock(o); . 341a lock(o); if(u && u->p && waserror()){ unlock(o); unlock(&origalloc); nexterror(); } . 260d 6a #include "errno.h" . ## diffname port/page.c 1990/0814 ## diff -e /n/bootesdump/1990/0802/sys/src/9/mips/page.c /n/bootesdump/1990/0814/sys/src/9/mips/page.c 665a unlock(o); . 661a unlock(o); . 647a memset(p+1+o->npte, 0, (n-(1+o->npte))*sizeof(PTE)); p->n = n; o->npte = n-1; . 628,646c if(!compactpte(o, n)) goto Trouble; p = ptealloc.free; ptealloc.free += n; memcpy(p+1, o->pte, o->npte*sizeof(PTE)); p->o = o; ((PTEA*)(o->pte-1))->o = 0; o->pte = p+1; . 618,626c n++; if(p+p->n == ptealloc.free){ if(!compactpte(o, n - p->n)) goto Trouble; p = (PTEA*)(o->pte - 1); ptealloc.free += n - p->n; . 616d 612,614c if(o->npte >= n) . 610a lock(o); . 603a /* * o is locked. this will always do a grow; if n<=o->npte someone * else got here first and we can just return. */ . 557,558d 550,554d 351d 344d 342d ## diffname port/page.c 1990/1013 ## diff -e /n/bootesdump/1990/0814/sys/src/9/mips/page.c /n/bootesdump/1990/1013/sys/src/9/mips/page.c 426c npte = newmod(o); . 400c panic("mods %lux %d %d", o->va, o->npte, o->nmod); . 385c newmod(Orig *o) . ## diffname port/page.c 1990/1018 ## diff -e /n/bootesdump/1990/1013/sys/src/9/mips/page.c /n/bootesdump/1990/1018/sys/src/9/mips/page.c 465a s->o = 0; /* seg() won't match it (e.g. in procread()) */ . ## diffname port/page.c 1990/1101 ## diff -e /n/bootesdump/1990/1018/sys/src/9/mips/page.c /n/bootesdump/1990/1101/sys/src/9/mips/page.c 374a if(freebroken()) goto lockloop; print("no origs freed\n"); . 373d 318a lockloop: . 197a print("no physical memory\n"); pprint("no physical memory\n"); . 195a if(freebroken()) goto loop; . 193,194d ## diffname port/page.c 1990/1115 ## diff -e /n/bootesdump/1990/1101/sys/src/9/mips/page.c /n/bootesdump/1990/1115/sys/src/9/mips/page.c 562c pexit("Suicide", 0); . ## diffname port/page.c 1990/11211 ## diff -e /n/bootesdump/1990/1115/sys/src/9/mips/page.c /n/bootesdump/1990/11211/sys/src/9/mips/page.c 656c error(Enovmem); . 493d 432d 404,405d 341,342c o->qid = (Qid){~0, ~0}; o->mqid = (Qid){~0, ~0}; . 332d 301c if(o->mchan==c->mchan && o->type==c->type && eqqid(o->mqid, c->mqid)){ . 299c if(o->npage && eqqid(o->qid, c->qid)) . 297c if(o->npage && o->qid.path==c->qid.path && o->va==va){ . ## diffname port/page.c 1990/1126 ## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/page.c /n/bootesdump/1990/1126/sys/src/9/mips/page.c 339c o->type = ~0; . ## diffname port/page.c 1990/1211 ## diff -e /n/bootesdump/1990/1211/sys/src/9/mips/page.c /n/bootesdump/1990/1211/sys/src/9/port/page.c 154c if(ppn < conf.npage0) p->pa = conf.base0+(ppn<pa = conf.base1+((ppn-conf.npage0)<= conf.maxialloc) panic("keep bill joy away"); . ## diffname port/page.c 1990/1212 ## diff -e /n/bootesdump/1990/1211/sys/src/9/port/page.c /n/bootesdump/1990/1212/sys/src/9/port/page.c 579c unusepage(pg, dolock); . 569c freepage(Orig *o, int dolock) . 509c freepage(o, 1); . 370c freepage(o, 1); . 188c freepage(o1, 0); . 58c if(palloc.active && n!=0) . ## diffname port/page.c 1990/1214 ## diff -e /n/bootesdump/1990/1212/sys/src/9/port/page.c /n/bootesdump/1990/1214/sys/src/9/port/page.c 344c o->type = 0xFFFF; . ## diffname port/page.c 1990/1226 ## diff -e /n/bootesdump/1990/1214/sys/src/9/port/page.c /n/bootesdump/1990/1226/sys/src/9/port/page.c 701c print("compactpte fails addr %lux %lux %d\n", o->va+n*BY2PG, o->va, n); . ## diffname port/page.c 1991/0110 ## diff -e /n/bootesdump/1990/1226/sys/src/9/port/page.c /n/bootesdump/1991/0110/sys/src/9/port/page.c 211c print("page in use %lux %lux %lux %lux\n", p, p->va, p->o, origalloc.arena); . 88c nf = nb = 0; . ## diffname port/page.c 1991/0115 ## diff -e /n/bootesdump/1991/0110/sys/src/9/port/page.c /n/bootesdump/1991/0115/sys/src/9/port/page.c 466a /* * flushvirt() is a no-op on machines without virtual write-back caches. * On such machines it is necessary to make sure the caches are flushed * before the pages are remapped. */ flushvirt(); . ## diffname port/page.c 1991/0318 ## diff -e /n/bootesdump/1991/0115/sys/src/9/port/page.c /n/bootesdump/1991/0318/sys/src/9/port/page.c 692c memmove(p1, p2, p2->n*sizeof(PTE)); . 633c memmove(p+1, o->pte, o->npte*sizeof(PTE)); . ## diffname port/page.c 1991/0425 ## diff -e /n/bootesdump/1991/0318/sys/src/9/port/page.c /n/bootesdump/1991/0425/sys/src/9/port/page.c 49a extern long end; . ## diffname port/page.c 1991/0606 ## diff -e /n/bootesdump/1991/0425/sys/src/9/port/page.c /n/bootesdump/1991/0606/sys/src/9/port/page.c 709a return 0; } long ibrk(ulong addr, int seg) { Seg *s; s = &u->p->seg[seg]; if(seg == LSEG && s->o == 0) mklockseg(s); /* Allows us to determine the base of the segment */ if(addr == 0) return s->minva; if(addr < s->endseg){ pprint("addr below segment\n"); pexit("Suicide", 0); error(Esegaddr); } if(addr > PGROUND(s->endseg)) if(segaddr(s, s->minva, addr) == 0){ pprint("bad segaddr in brk\n"); pexit("Suicide", 0); error(Esegaddr); } s->endseg = addr; . 552c max = PGROUND(max); . 71,74c if(align) palloc.addr = PGROUND(palloc.addr); . 64,67c if(align) palloc.addr = PGROUND(palloc.addr); . ## diffname port/page.c 1991/0607 ## diff -e /n/bootesdump/1991/0606/sys/src/9/port/page.c /n/bootesdump/1991/0607/sys/src/9/port/page.c 590a } . 585c (*o->freepg)(pg, dolock); . 582c for(i=0; inpte; i++,pte++) { . 431,432d 336a o->freepg = unusepage; . ## diffname port/page.c 1991/0705 ## diff -e /n/bootesdump/1991/0607/sys/src/9/port/page.c /n/bootesdump/1991/0705/sys/src/9/port/page.c 730,738c lock(&ptealloclk); p->next = ptealloclk.free; ptealloclk.free = p; unlock(&ptealloclk); . 720,727c switch(s->type&SG_TYPE) { case SG_PHYSICAL: for(pg = p->pages; pg < ptop; pg++) if(*pg) (*s->pgfree)(*pg); break; default: for(pg = p->pages; pg < ptop; pg++) if(*pg) putpage(*pg); . 716,718c ptop = &p->pages[PTEPERTAB]; . 714c Page **pg, **ptop; . 711,712c void freepte(Segment *s, Pte *p) . 700,708c new = ptealloclk.free; ptealloclk.free = new->next; unlock(&ptealloclk); memset(new->pages, 0, sizeof(new->pages)); return new; . 672,698c lock(&ptealloclk); while(ptealloclk.free == 0) { unlock(&ptealloclk); k = kmap(newpage(1, 0, 0)); new = (Pte*)VA(k); n = (BY2PG/sizeof(Pte))-1; for(i = 0; i < n; i++) new[i].next = &new[i+1]; lock(&ptealloclk); ptealloclk.pages++; new[i].next = ptealloclk.free; ptealloclk.free = new; . 669,670c Pte *new; int i, n; KMap *k; . 666,667c Pte* ptealloc(void) . 658,663c return new; . 638,656d 616,636c end = &old->pages[PTEPERTAB]; for(src = old->pages, dst = new->pages; src < end; src++, dst++) if(*src) { if(onswap(*src)) dupswap(*src); else { lockpage(*src); (*src)->ref++; unlockpage(*src); } *dst = *src; . 606,614c new = ptealloc(); . 601,604c Page **src, **dst, **end; Pte *new; . 594,599c Pte* ptecpy(Pte *old) . 591c unlock(&palloc.hashlock); return 0; . 588c lock(&palloc); if(++f->ref == 1) { if(f->prev) f->prev->next = f->next; else palloc.head = f->next; if(f->next) f->next->prev = f->prev; else palloc.tail = f->prev; palloc.freecount--; } unlock(&palloc); unlockpage(f); return f; . 580,586c lock(&palloc.hashlock); for(f = palloc.hash[PGHFUN(i, daddr)]; f; f = f->hash) { if(f->image == i && f->daddr == daddr) { unlock(&palloc.hashlock); lockpage(f); if(f->image != i || f->daddr != daddr) { unlockpage(f); return 0; . 576,578c Page *f; . 570,574c Page * lookpage(Image *i, ulong daddr) . 545,567c incref(i); lock(&palloc.hashlock); p->image = i; l = &pghash(p); p->hash = *l; *l = p; unlock(&palloc.hashlock); . 543c Page **l; . 537,541c void cachepage(Page *p, Image *i) . 507,533c unlock(&palloc.hashlock); putimage(p->image); p->image = 0; . 505a l = &f->hash; . 466,504c if(p->image) { lock(&palloc.hashlock); l = &pghash(p); for(f = *l; f; f = f->hash) { if(f == p) { *l = p->hash; break; . 458,464c Page **l, *f; . 456c uncachepage(Page *p) /* Alway called with a locked page */ . 428,452c ks = kmap(f); kd = kmap(t); memmove((void*)VA(kd), (void*)VA(ks), BY2PG); kunmap(ks); kunmap(kd); . 424,426c KMap *ks, *kd; . 422c copypage(Page *f, Page *t) . 417,420d 407,414c uncachepage(np); np->va = p->va; np->daddr = p->daddr; copypage(p, np); cachepage(np, p->image); unlockpage(np); uncachepage(p); . 399,405c lockpage(np); /* Cache the new version */ if(np->ref != 0) { /* Stolen by new page */ uncachepage(p); unlockpage(np); return; . 394,397c unlock(&palloc); . 379,392c else { palloc.head = palloc.tail = np; np->prev = np->next = 0; } . 360,377c np = palloc.head; /* Allocate a new page from freelist */ if(palloc.head = np->next) /* = Assign */ palloc.head->prev = 0; else palloc.tail = 0; if(palloc.tail) { /* Link back onto tail to give us lru */ np->prev = palloc.tail; palloc.tail->next = np; np->next = 0; palloc.tail = np; . 326,358c lock(&palloc); if(palloc.freecount < HIGHWATER || /* No freelist cache when memory is very low */ p->image == &swapimage) { /* No dup for swap pages */ unlock(&palloc); uncachepage(p); return; . 323,324c Page *np; . 320,321c void duppage(Page *p) /* Always call with p locked */ . 317c else { if(palloc.head) { p->next = palloc.head; palloc.head->prev = p; p->prev = 0; palloc.head = p; } else { palloc.head = palloc.tail = p; p->prev = p->next = 0; } } palloc.freecount++; /* Release people waiting for memory */ unlock(&palloc); } unlockpage(p); if(palloc.wanted) wakeup(&palloc.r); . 315c else { palloc.head = palloc.tail = p; p->prev = p->next = 0; } . 301,313c lockpage(p); if(--p->ref == 0) { lock(&palloc); if(p->image) { if(palloc.tail) { p->prev = palloc.tail; palloc.tail->next = p; p->next = 0; palloc.tail = p; . 295,299c if(onswap(p)) { putswap(p); return; } . 268,293c int count; . 266c putpage(Page *p) . 262,264d 235,259c return palloc.freecount >= HIGHWATER; . 229,233c int ispages(void *p) . 223,224d 203,218c uncachepage(p); p->ref++; p->va = va; p->modref = 0; for(i = 0; i < MAXMACH; i++) p->cachectl[i] = PG_NOFLUSH; unlockpage(p); if(clear){ . 199,201c lockpage(p); if(p->ref != 0) . 197a p = palloc.head; if(palloc.head = p->next) /* = Assign */ palloc.head->prev = 0; else palloc.tail = 0; palloc.freecount--; . 196c qlock(&palloc.pwait); /* Hold memory requesters here */ kickpager(); tsleep(&palloc.r, ispages, 0, 1000); qunlock(&palloc.pwait); lock(&palloc); palloc.wanted--; . 176,194c /* The kp test is a poor guard against the pager deadlocking */ while((palloc.freecount < HIGHWATER && u->p->kp == 0) || palloc.freecount == 0) { palloc.wanted++; unlock(&palloc); if(s && *s) { qunlock(&((*s)->lk)); *s = 0; . 174c . 170a int i; . 169d 166c newpage(int clear, Segment **s, ulong va) . 159a palloc.freecount++; . 152c pmem = ((conf.npage-ppn)*BY2PG)/1024; vmem = pmem + ((conf.nswap)*BY2PG)/1024; palloc.user = conf.npage-ppn; print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem); . 140,141c pa = (conf.npage<> PGSHIFT; /* physical page number of first free page */ . 117,134d 114,115d 112c ulong i, vmem, pmem; . 79,108d 74a . 50c void unlockpage(Page *p) { p->lock = 0; } . 45,48c for(;;) { if(p->lock == 0) { s = splhi(); lock(&pglock); if(p->lock == 0) { p->lock = 1; unlock(&pglock); splx(s); return; } unlock(&pglock); splx(s); } sched(); } } . 37,43c /* Multiplex a hardware lock for per page manipulations */ void lockpage(Page *p) { int s; . 27,35c extern long end; static Lock pglock; . 23,25c Pte *free; int pages; }ptealloclk; . 20c struct Palloc palloc; struct Ptealloc . 9,18c #define PGHFUN(x, y) (((ulong)x^(ulong)y)%PGHSIZE) #define pghash(s) palloc.hash[PGHFUN(s->image, p->daddr)] . ## diffname port/page.c 1991/0718 ## diff -e /n/bootesdump/1991/0705/sys/src/9/port/page.c /n/bootesdump/1991/0718/sys/src/9/port/page.c 299c uncachepage(Page *p) /* Always called with a locked page */ . ## diffname port/page.c 1991/0801 ## diff -e /n/bootesdump/1991/0718/sys/src/9/port/page.c /n/bootesdump/1991/0801/sys/src/9/port/page.c 67a if(palloc.addr+n > conf.base0 + conf.npage0*BY2PG) palloc.addr = conf.base1; . ## diffname port/page.c 1991/0802 ## diff -e /n/bootesdump/1991/0801/sys/src/9/port/page.c /n/bootesdump/1991/0802/sys/src/9/port/page.c 123a palloc.user = palloc.freecount = p - palloc.head; pmem = palloc.user*BY2PG/1024; vmem = pmem + ((conf.nswap)*BY2PG)/1024; print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem); . 121a addr = palloc.addr1 = PGROUND(palloc.addr1); lim = conf.base1 + (conf.npage1<next = p+1; p->prev = p-1; p->pa = addr; p++; } palloc.tail = p - 1; . 116,120c p->pa = addr; p++; . 104,113c /* * for each page in each bank, point a page structure to * the page and chain it into the free list */ p = palloc.head; addr = palloc.addr0 = PGROUND(palloc.addr0); lim = conf.base0 + (conf.npage0<>PGSHIFT; . 86c ulong np, addr, lim; . 79a /* * zero it */ memset((void*)(p|KZERO), 0, n); /* * don't put anything else into a page aligned ialloc */ *ap = align ? PGROUND(p+n) : (p+n); . 77,78c if(p >= conf.maxialloc) panic("keep bill joy away 2"); . 71,75c /* * try first bank */ p = align ? PGROUND(palloc.addr0) : palloc.addr0; if(p+n > conf.base0 + (conf.npage0<ref = 0; palloc.freecount++; if(palloc.head) { pg->next = palloc.head; palloc.head->prev = pg; pg->prev = 0; palloc.head = pg; } else { palloc.head = palloc.tail = pg; pg->prev = pg->next = 0; } } void . ## diffname port/page.c 1991/1115 ## diff -e /n/bootesdump/1991/1003/sys/src/9/port/page.c /n/bootesdump/1991/1115/sys/src/9/port/page.c 225a USED(p); . ## diffname port/page.c 1991/1122 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/page.c /n/bootesdump/1991/1122/sys/src/9/port/page.c 497c for(pg = p->first; pg <= p->last; pg++) . 491a ptop = &p->pages[PTEPERTAB]; . 488,489d 479a new->first = &new->pages[PTEPERTAB]; new->last = new->pages; . 464c k = kmap(newpage(0, 0, 0)); . 446a new->last = dst; . 436,438c dst = &new->pages[old->first-old->pages]; new->first = dst; for(src = old->first; src <= old->last; src++, dst++) . ## diffname port/page.c 1992/0111 ## diff -e /n/bootesdump/1991/1122/sys/src/9/port/page.c /n/bootesdump/1992/0111/sys/src/9/port/page.c 7c #include "../port/error.h" . ## diffname port/page.c 1992/0120 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/page.c /n/bootesdump/1992/0120/sys/src/9/port/page.c 6d ## diffname port/page.c 1992/0131 ## diff -e /n/bootesdump/1992/0120/sys/src/9/port/page.c /n/bootesdump/1992/0131/sys/src/9/port/page.c 500a *pg = 0; } . 499c if(*pg) { . 495a *pg = 0; } . 494c if(*pg) { . 481a . 479d 464c k = kmap(newpage(1, 0, 0)); . ## diffname port/page.c 1992/0204 ## diff -e /n/bootesdump/1992/0131/sys/src/9/port/page.c /n/bootesdump/1992/0204/sys/src/9/port/page.c 264a p->prev = 0; . 263c p->next = 0; . 258d 252a p->next = 0; . 251c p->prev = 0; . 246d ## diffname port/page.c 1992/0303 ## diff -e /n/bootesdump/1992/0204/sys/src/9/port/page.c /n/bootesdump/1992/0303/sys/src/9/port/page.c 300,301c /* No freelist cache when memory is very low, No dup for swap pages */ if(palloc.freecount < swapalloc.highwater || p->image == &swapimage) { . 271,272c if(wake && palloc.wanted) . 266a wake = 1; . 263a palloc.head = p; . 261c palloc.tail = p; . 258d 251a palloc.tail = p; . 249c palloc.head = p; . 246d 242c if(p->image && p->image != &swapimage) { . 238a wake = 0; . 232c int wake; . 226c return palloc.freecount >= swapalloc.highwater; . 169c while((palloc.freecount < swapalloc.highwater && u->p->kp == 0)||palloc.freecount == 0) { . 153c /* Pageing numbers */ swapalloc.highwater = (palloc.freecount*5)/100; swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4); hw = (swapalloc.highwater*BY2PG)/1024; hr = (swapalloc.headroom*BY2PG)/1024; print("%lud free pages, %dK bytes, swap %dK bytes, highwater %dK, headroom %dK\n", palloc.user, pmem, vmem, hw, hr); . 106c ulong i, vmem, pmem, hw, hr; . ## diffname port/page.c 1992/0304 ## diff -e /n/bootesdump/1992/0303/sys/src/9/port/page.c /n/bootesdump/1992/0304/sys/src/9/port/page.c 281,282d 276d 247d 240,241d ## diffname port/page.c 1992/0313 ## diff -e /n/bootesdump/1992/0304/sys/src/9/port/page.c /n/bootesdump/1992/0313/sys/src/9/port/page.c 99a } /* * allocate with possible page alignment */ void* ialloc(ulong n, int align) { return iallocspan(n, align ? BY2PG : 0, 0); . 97c memset((void*)(p|KZERO), 0, n); . 95c * zero it . 92c if(palloc.addr0 < r->start && r->start <= conf.base0+(conf.npage0<start; else if(palloc.addr1 < r->start && r->start <= conf.base1+(conf.npage1<start; . 90c * remember high water marks . 88a /* check for crossing a crevasse */ if(crevasse){ ledge = p / crevasse; if(ledge != ((p+n-1) / crevasse)) p = ((p+n-1) / crevasse) * crevasse; } /* see if it fits */ if(p + n > r->end) continue; /* split the region */ if(p != r->start) addsplit(r, r->start, p); r->start = p + n; break; } if(r == ®ion[Nregion]) panic("out of memory"); . 86,87c p = 0; for(r = region; r < ®ion[Nregion]; r++){ /* allign region */ p = r->start; if(align){ m = p % align; if(m) p += align - m; } . 74,84c if(align){ m = n % align; if(m) n += align - m; } . 72c * alignment also applies to length . 66,68c region[Nregion-2].start = (((ulong)&end)&~KZERO) + conf.base0; region[Nregion-2].end = conf.base0 + (conf.npage0<end - rr->start == 0){ rr->start = start; rr->end = end; return; } } /* then look for a smaller one */ for(rr = region; rr < ®ion[Nregion]; rr++){ if(rr == r) continue; if(rr->end - rr->start < len){ rr->start = start; rr->end = end; return; } } } . 54a * * alignment is in number of bytes * * WARNING: You can't cross a crevasse! . 51a typedef struct Region Region; struct Region { ulong start; ulong end; }; enum { Nregion= 10, }; Region region[Nregion]; . ## diffname port/page.c 1992/0315 ## diff -e /n/bootesdump/1992/0313/sys/src/9/port/page.c /n/bootesdump/1992/0315/sys/src/9/port/page.c 134c /* align region */ . 101a /* * Called to allocate permanent data structures, before calling pageinit(). * We assume all of text+data+bss is in the first memory bank. * * alignment is in number of bytes. It pretains both to the start and * end of the allocated memory. * * If crevasse is specified, no allocation can span an address that is * a multiple of crevasse. */ . 66,73d 20c extern long end; ulong hiaddr; . ## diffname port/page.c 1992/0317 ## diff -e /n/bootesdump/1992/0315/sys/src/9/port/page.c /n/bootesdump/1992/0317/sys/src/9/port/page.c 197a print("addr0 %lux addr1 %lux\n", palloc.addr0, palloc.addr1); . 100c * alignment is in number of bytes. It pertains both to the start and . ## diffname port/page.c 1992/0318 ## diff -e /n/bootesdump/1992/0317/sys/src/9/port/page.c /n/bootesdump/1992/0318/sys/src/9/port/page.c 198d ## diffname port/page.c 1992/0319 ## diff -e /n/bootesdump/1992/0318/sys/src/9/port/page.c /n/bootesdump/1992/0319/sys/src/9/port/page.c 118c region[Nregion-2].start = (((ulong)end)&~KZERO) + conf.base0; . 20d ## diffname port/page.c 1992/0321 ## diff -e /n/bootesdump/1992/0319/sys/src/9/port/page.c /n/bootesdump/1992/0321/sys/src/9/port/page.c 2c #include "../port/lib.h" . ## diffname port/page.c 1992/0618 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/page.c /n/bootesdump/1992/0618/sys/src/9/port/page.c 177d 117,120c r = ®ion[Nregion-2]; r->start = (((ulong)end)&~KZERO) + conf.base0; r->end = conf.base0 + (conf.npage0<start = conf.base1; r->end = conf.base1 + (conf.npage1<lock == 0) { s = splhi(); lock(&pglock); if(p->lock == 0) { p->lock = 1; unlock(&pglock); splx(s); return; } unlock(&pglock); splx(s); } sched(); } } void unlockpage(Page *p) { p->lock = 0; . 269c while((palloc.freecount < swapalloc.highwater && u->p->kp == 0) || palloc.freecount == 0) { . 263,265d 252,253c print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", palloc.user, pmem, vmem, hw/1024, hr/1024); . 249,250c hw = swapalloc.highwater*BY2PG; hr = swapalloc.headroom*BY2PG; . 244c vmem = pmem + (conf.nswap*BY2PG)/1024; . 242c palloc.user = p - palloc.head; palloc.freecount = palloc.user; . 235c p->next = p+1; p->pa = palloc.p1; palloc.p1 += BY2PG; palloc.np1--; . 230,233c while(palloc.np1 > 0) { . 227c p->next = p+1; p->pa = palloc.p0; palloc.p0 += BY2PG; palloc.np0--; . 222,225c while(palloc.np0 > 0) { . 209,220d 201,207c np = palloc.np0+palloc.np1; palloc.head = xalloc(np*sizeof(Page)); if(palloc.head == 0) panic("pageinit"); . 199a ulong np, hw, hr, vmem, pmem; . 197,198d 25,194d 23d 20,21c static Lock pglock; struct Palloc palloc; . 11,12d ## diffname port/page.c 1992/0620 ## diff -e /n/bootesdump/1992/0619/sys/src/9/port/page.c /n/bootesdump/1992/0620/sys/src/9/port/page.c 413,417c free(p); . 388d 367,385c new = smalloc(sizeof(Pte)); . 364,365d 11,17d ## diffname port/page.c 1992/0621 ## diff -e /n/bootesdump/1992/0620/sys/src/9/port/page.c /n/bootesdump/1992/0621/sys/src/9/port/page.c 24c print("page: %lux %d %lux %d\n", palloc.p0, palloc.np0, palloc.p1, palloc.np1); . ## diffname port/page.c 1992/0622 ## diff -e /n/bootesdump/1992/0621/sys/src/9/port/page.c /n/bootesdump/1992/0622/sys/src/9/port/page.c 24c . ## diffname port/page.c 1992/0625 ## diff -e /n/bootesdump/1992/0622/sys/src/9/port/page.c /n/bootesdump/1992/0625/sys/src/9/port/page.c 386,414d 344c unlock(*src); . 342c lock(*src); . 332a Page **src, **dst, **end; . 331d 320c unlock(f); . 301c unlock(f); . 299c lock(f); . 272a unlock(&palloc.hashlock); putimage(p->image); p->image = 0; . 269,271c l = &f->hash; . 259,267c if(p->image == 0) return; lock(&palloc.hashlock); l = &pghash(p); for(f = *l; f; f = f->hash) { if(f == p) { *l = p->hash; break; . 238c unlock(np); . 229c unlock(np); . 226c lock(np); /* Cache the new version */ . 189a pg->next = palloc.head; palloc.head->prev = pg; pg->prev = 0; palloc.head = pg; . 188a return; . 180,186c if(palloc.head == 0) { . 172c unlock(p); . 141c lock(p); . 115c unlock(p); . 104c lock(p); . ## diffname port/page.c 1992/0628 ## diff -e /n/bootesdump/1992/0625/sys/src/9/port/page.c /n/bootesdump/1992/0628/sys/src/9/port/page.c 199,200c if(palloc.freecount < swapalloc.highwater) { . 195a if(p->image == &swapimage) return; . ## diffname port/page.c 1992/0629 ## diff -e /n/bootesdump/1992/0628/sys/src/9/port/page.c /n/bootesdump/1992/0629/sys/src/9/port/page.c 287a unlock(&palloc.hashlock); } void cachedel(Image *i, ulong daddr) { Page *f, **l; lock(&palloc.hashlock); l = &palloc.hash[PGHFUN(i, daddr)]; for(f = *l; f; f = f->hash) { if(f->image == i && f->daddr == daddr) { *l = f->hash; break; } l = &f->hash; } . 200,201c /* No freelist cache when memory is very low */ . 197a } . 196c /* No dup for swap pages */ if(p->image == &swapimage) { uncachepage(p); . ## diffname port/page.c 1992/0711 ## diff -e /n/bootesdump/1992/0629/sys/src/9/port/page.c /n/bootesdump/1992/0711/sys/src/9/port/page.c 353c Page **src, **dst; . ## diffname port/page.c 1992/0805 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/page.c /n/bootesdump/1992/0805/sys/src/9/port/page.c 90a /* * If called from fault and we lost the segment from underneath * don't waste time allocating and freeing a page. Fault will call * newpage again when it has reaquired the segment locks */ if(dontalloc) return 0; . 78a dontalloc = 1; . 75a dontalloc = 0; . 71,73c hw = swapalloc.highwater; while((palloc.freecount < hw && u->p->kp == 0) || palloc.freecount == 0) { . 67c int hw, i, dontalloc; . ## diffname port/page.c 1992/0905 ## diff -e /n/bootesdump/1992/0805/sys/src/9/port/page.c /n/bootesdump/1992/0905/sys/src/9/port/page.c 240c if(np->ref != 0) { /* Stolen by lookpage */ . 187a if(pg->ref != 1) panic("simpleputpage"); . 115,118c if(p->ref != 0) { /* lookpage has priority on steal */ unlock(p); goto retry; } . 68a retry: . ## diffname port/page.c 1992/0910 ## diff -e /n/bootesdump/1992/0905/sys/src/9/port/page.c /n/bootesdump/1992/0910/sys/src/9/port/page.c 97c * newpage again when it has reacquired the segment locks . ## diffname port/page.c 1992/0911 ## diff -e /n/bootesdump/1992/0910/sys/src/9/port/page.c /n/bootesdump/1992/0911/sys/src/9/port/page.c 58,59c /* print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", palloc.user, pmem, vmem, hw/1024, hr/1024);/**/ . ## diffname port/page.c 1992/0913 ## diff -e /n/bootesdump/1992/0911/sys/src/9/port/page.c /n/bootesdump/1992/0913/sys/src/9/port/page.c 58c print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", . ## diffname port/page.c 1992/1209 ## diff -e /n/bootesdump/1992/0913/sys/src/9/port/page.c /n/bootesdump/1992/1209/sys/src/9/port/page.c 329c for(f = pghash(daddr); f; f = f->hash) { . 312c l = &pghash(daddr); . 300c l = &pghash(p->daddr); . 296a /* If this ever happens it should be fixed by calling * uncachepage instead of panic. I think there is a race * with pio in which this can happen. Calling uncachepage is * correct - I just wanted to see if we got here. */ if(p->image) panic("cachepage"); . 279c l = &pghash(p->daddr); . 271c uncachepage(Page *p) /* Always called with a locked page */ . 229c if(palloc.tail) { /* Link back onto tail to give us lru */ . 223,224c np = palloc.head; /* Allocate a new page from freelist */ if(palloc.head = np->next) /* = Assign */ . 180c palloc.freecount++; /* Release people waiting for memory */ . 116c if(p->ref != 0) { /* lookpage has priority on steal */ . 8,9c #define pghash(daddr) palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)] . ## diffname port/page.c 1993/0116 ## diff -e /n/bootesdump/1992/1209/sys/src/9/port/page.c /n/bootesdump/1993/0116/sys/src/9/port/page.c 250a mmunewpage(np); . 124a mmunewpage(p); . ## diffname port/page.c 1993/0210 ## diff -e /n/bootesdump/1993/0116/sys/src/9/port/page.c /n/bootesdump/1993/0210/sys/src/9/port/page.c 419a break; } for(pg = p->pages; pg < ptop; pg++) { pt = *pg; if(pt == 0) continue; lock(pt); ref = --pt->ref; unlock(pt); if(ref == 0) free(pt); } . 415,417c if(fn) { for(pg = p->pages; pg < ptop; pg++) { if(*pg == 0) continue; (*fn)(*pg); . 413a fn = s->pseg->pgfree; . 410c int ref; Page *pt, **pg, **ptop; void (*fn)(Page*); . ## diffname port/page.c 1993/0501 ## diff -e /n/bootesdump/1993/0210/sys/src/9/port/page.c /n/fornaxdump/1993/0501/sys/src/brazil/port/page.c 412a Page *pt, **pg, **ptop; . 411d 252c for(i = 0; i < MAXMACH; i++) np->cachectl[i] |= PG_DATINVALID; . 207a int i; . 123,125c memset(p->cachectl, PG_DATINVALID, sizeof(p->cachectl)); . 72c while((palloc.freecount < hw && up->kp == 0) || palloc.freecount == 0) { . 66c int hw, dontalloc; . 54,58c print("%lud free pages\n%dK bytes\n%dK swap\n", palloc.user, pmem, vmem); . 17c ulong np, vmem, pmem; . ## diffname port/page.c 1993/0810 ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/page.c /n/fornaxdump/1993/0810/sys/src/brazil/port/page.c 192,195c palloc.freecount++; /* Release people waiting for memory */ unlock(&palloc); unlock(p); . 177,190c else { if(palloc.head) { p->next = palloc.head; palloc.head->prev = p; } else { palloc.tail = p; p->next = 0; } palloc.head = p; p->prev = 0; . 173,175c palloc.tail = p; p->next = 0; . 162,169d 147,159c if(--p->ref > 0) { unlock(p); return; } vcacheinval(p); lock(&palloc); if(p->image && p->image != &swapimage) { if(palloc.tail) { p->prev = palloc.tail; palloc.tail->next = p; . 122c if(clear) { . 90,92c * If called from fault and we lost the segment from * underneath don't waste time allocating and freeing * a page. Fault will call newpage again when it has * reacquired the segment locks . 79c while(waserror()) /* Ignore interrupts */ . 77c qlock(&palloc.pwait); /* Hold memory requesters here */ . 68c fc = palloc.freecount; while((fc < hw && up->kp == 0) || fc == 0) { . 62c int hw, dontalloc, fc; . ## diffname port/page.c 1993/0811 ## diff -e /n/fornaxdump/1993/0810/sys/src/brazil/port/page.c /n/fornaxdump/1993/0811/sys/src/brazil/port/page.c 234,235d 189d 152a . 121c for(i = 0; i < MAXMACH; i++) p->cachectl[i] = PG_NOFLUSH; . 62c int i, hw, dontalloc, fc; . ## diffname port/page.c 1993/0815 ## diff -e /n/fornaxdump/1993/0811/sys/src/brazil/port/page.c /n/fornaxdump/1993/0815/sys/src/brazil/port/page.c 155c vcacheinval(p, p->va); . ## diffname port/page.c 1993/0816 ## diff -e /n/fornaxdump/1993/0815/sys/src/brazil/port/page.c /n/fornaxdump/1993/0816/sys/src/brazil/port/page.c 230a if(np->log == 0) { np->log = smalloc(8192); np->lptr = 0; } . 116a if(p->log == 0) { p->log = smalloc(8192); p->lptr = 0; } . ## diffname port/page.c 1993/0817 ## diff -e /n/fornaxdump/1993/0816/sys/src/brazil/port/page.c /n/fornaxdump/1993/0817/sys/src/brazil/port/page.c 351a palloc.freecol[f->color]--; . 217a if(np->next) np->next->prev = np->prev; else palloc.tail = np->prev; . 216c palloc.head = np->next; . 212,214c color = getcolor(p->va); for(np = palloc.head; np; np = np->next) if(np->color == color) break; /* No page of the correct color */ if(np == 0) { unlock(&palloc); uncachepage(p); return; } if(np->prev) np->prev->next = np->next; . 196a int color; . 188a palloc.freecol[p->color]++; if(palloc.r.p != 0) wakeup(&palloc.r); . 161d 109a palloc.freecol[color]--; . 108a if(p->next) p->next->prev = p->prev; else palloc.tail = p->prev; . 107c palloc.head = p->next; . 103,105c for(p = palloc.head; p; p = p->next) if(p->color == color) break; if(p == 0) panic("newpage"); if(p->prev) p->prev->next = p->next; . 78c qlock(&palloc.pwait); /* Hold memory requesters here */ . 68,69c for(;;) { if(palloc.freecol[color] > hw) break; if(up->kp && palloc.freecol[color] > 0) break; . 66a color = getcolor(va); . 62c int i, hw, dontalloc, color; . 54c print("%lud free pages\n%dK bytes\n%dK swap\n", palloc.user, pm, vm); . 51c swapalloc.highwater = (palloc.user*5)/100; . 46,48c pm = palloc.user*BY2PG/1024; vm = pm + (conf.nswap*BY2PG)/1024; . 36a p->color = color; palloc.freecol[color]++; color = (color+1)%NCOLOR; . 28a p->color = color; palloc.freecol[color]++; color = (color+1)%NCOLOR; . 23a color = 0; . 17c ulong np, vm, pm; . 15a int color; . ## diffname port/page.c 1993/0818 ## diff -e /n/fornaxdump/1993/0817/sys/src/brazil/port/page.c /n/fornaxdump/1993/0818/sys/src/brazil/port/page.c 282,285d 263c /* Link back onto tail to give us lru in the free list */ if(palloc.tail) { . 143,147d ## diffname port/page.c 1993/0819 ## diff -e /n/fornaxdump/1993/0818/sys/src/brazil/port/page.c /n/fornaxdump/1993/0819/sys/src/brazil/port/page.c 365a return 0; . ## diffname port/page.c 1993/0825 ## diff -e /n/fornaxdump/1993/0819/sys/src/brazil/port/page.c /n/fornaxdump/1993/0825/sys/src/brazil/port/page.c 398a print("#"); . 366d ## diffname port/page.c 1993/0827 ## diff -e /n/fornaxdump/1993/0825/sys/src/brazil/port/page.c /n/fornaxdump/1993/0827/sys/src/brazil/port/page.c 398d ## diffname port/page.c 1993/0906 ## diff -e /n/fornaxdump/1993/0827/sys/src/brazil/port/page.c /n/fornaxdump/1993/0906/sys/src/brazil/port/page.c 236c color = getpgcolor(p->va); . 74c color = getpgcolor(va); . ## diffname port/page.c 1993/0910 ## diff -e /n/fornaxdump/1993/0906/sys/src/brazil/port/page.c /n/fornaxdump/1993/0910/sys/src/brazil/port/page.c 388c . 230c if(palloc.freecol[p->color] < swapalloc.highwater/NCOLOR) { . 209,210c r = &palloc.r[p->color]; if(r->p != 0) wakeup(r); . 207d 169a Rendez *r; . 163,164c int color; color = (int)p; return palloc.freecol[color] >= swapalloc.highwater/NCOLOR; . 133d 100c qunlock(&palloc.pwait[color]); . 96c tsleep(&palloc.r[color], ispages, (void*)color, 1000); . 90c qlock(&palloc.pwait[color]); /* Hold memory requesters here */ . ## diffname port/page.c 1993/0918 ## diff -e /n/fornaxdump/1993/0910/sys/src/brazil/port/page.c /n/fornaxdump/1993/0918/sys/src/brazil/port/page.c 61c print("%lud free pages\n", palloc.user); print("%dK bytes\n", pm); print("%dK swap\n", vm); . ## diffname port/page.c 1993/1008 ## diff -e /n/fornaxdump/1993/0918/sys/src/brazil/port/page.c /n/fornaxdump/1993/1008/sys/src/brazil/port/page.c 79c if(palloc.freecol[color] > hw/NCOLOR) . ## diffname port/page.c 1993/1015 ## diff -e /n/fornaxdump/1993/1008/sys/src/brazil/port/page.c /n/fornaxdump/1993/1015/sys/src/brazil/port/page.c 324a p->daddr = 0; . 220a Page* auxpage() { Page *p; lock(&palloc); p = palloc.head; if(palloc.freecol[p->color] < swapalloc.highwater/NCOLOR) { unlock(&palloc); return 0; } p->next->prev = 0; palloc.head = p->next; palloc.freecol[p->color]--; unlock(&palloc); lock(p); if(p->ref != 0) { /* Stolen by lookpage */ unlock(p); return 0; } p->ref++; uncachepage(p); unlock(p); return p; } . ## diffname port/page.c 1993/1120 ## diff -e /n/fornaxdump/1993/1015/sys/src/brazil/port/page.c /n/fornaxdump/1993/1120/sys/src/brazil/port/page.c 422c palloc.freecount--; . 262c if(palloc.freecount < swapalloc.highwater) { . 234c palloc.freecount--; . 228c if(palloc.freecount < swapalloc.highwater) { . 212,215c palloc.freecount++; if(palloc.r.p != 0) wakeup(&palloc.r); . 173,174d 164,167c USED(p); return palloc.freecount >= swapalloc.highwater; . 140a print("stolen\n"); lock(&palloc); palloc.freecount++; . 135c palloc.freecount--; . 121,122c if(p == 0) { p = palloc.head; memset(p->cachectl, PG_DATFLUSH, sizeof(p->cachectl)); p->color = color; } . 116a /* First try for out colour */ . 114d 102c qunlock(&palloc.pwait); . 98c tsleep(&palloc.r, ispages, 0, 1000); . 92c qlock(&palloc.pwait); /* Hold memory requesters here */ . 84d 81c if(up->kp && palloc.freecount > 0) . 79c if(palloc.freecount > hw) . 75a lock(&palloc); retry: . 73,74d 43c palloc.freecount++; . 32c palloc.freecount++; . ## diffname port/page.c 1993/1211 ## diff -e /n/fornaxdump/1993/1120/sys/src/brazil/port/page.c /n/fornaxdump/1993/1211/sys/src/brazil/port/page.c 120a print("! "); . ## diffname port/page.c 1993/1212 ## diff -e /n/fornaxdump/1993/1211/sys/src/brazil/port/page.c /n/fornaxdump/1993/1212/sys/src/brazil/port/page.c 123c memset(p->cachectl, PG_NEWCOL, sizeof(p->cachectl)); . 115c /* First try for our colour */ . ## diffname port/page.c 1993/1219 ## diff -e /n/fornaxdump/1993/1212/sys/src/brazil/port/page.c /n/fornaxdump/1993/1219/sys/src/brazil/port/page.c 137d ## diffname port/page.c 1994/0508 ## diff -e /n/fornaxdump/1993/1219/sys/src/brazil/port/page.c /n/fornaxdump/1994/0508/sys/src/brazil/port/page.c 121d ## diffname port/page.c 1994/0817 ## diff -e /n/fornaxdump/1994/0508/sys/src/brazil/port/page.c /n/fornaxdump/1994/0817/sys/src/brazil/port/page.c 336c if(p->image == 0 || p->image->notext) . 257d 253,255c /* No dup for swap/cache pages */ if(p->image->notext) . ## diffname port/page.c 1994/0819 ## diff -e /n/fornaxdump/1994/0817/sys/src/brazil/port/page.c /n/fornaxdump/1994/0819/sys/src/brazil/port/page.c 334c if(p->image == 0) . ## diffname port/page.c 1994/1213 ## diff -e /n/fornaxdump/1994/0819/sys/src/brazil/port/page.c /n/fornaxdump/1994/1213/sys/src/brazil/port/page.c 153c p->cachectl[i] = ct; . 123a ct = PG_NEWCOL; . 122d 119a ct = PG_NOFLUSH; . 70a uchar ct; . ## diffname port/page.c 1995/0804 ## diff -e /n/fornaxdump/1994/1213/sys/src/brazil/port/page.c /n/fornaxdump/1995/0804/sys/src/brazil/port/page.c 170d 168c ispages(void*) . ## diffname port/page.c 1998/0512 ## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/page.c /n/emeliedump/1998/0512/sys/src/brazil/port/page.c 490c if(pt == 0) . 454c return new; . 425c return f; . 410c if(f->prev) . 308c . 278c if(np->prev) . 274c uncachepage(p); . 262c uncachepage(p); . 128c if(p->prev) . 106,107c * underneath don't waste time allocating and freeing * a page. Fault will call newpage again when it has . ## diffname port/page.c 1998/0513 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/page.c /n/emeliedump/1998/0513/sys/src/brazil/port/page.c 428a . 424a . 423d 419d 414d 407,408d 404a unlock(&palloc); . 401a lock(&palloc); . 302,308c /* Cache the new version */ . 299a lock(np); . 282d 258c /* * normal lock ordering is to call * lock(&palloc) before lock(p). * To avoid deadlock, we have to drop * our locks and try again. */ if(!canlock(&palloc)){ unlock(p); if(up) sched(); lock(p); goto retry; } . 255c if(p->ref == 0 || p->image == nil || p->image->notext) . 253a retries = 0; retry: if(retries++ > 10000) panic("duppage"); . 252a int retries; . 244a unlock(&palloc); . 238,241c if(p->ref != 0) panic("auxpage"); . 235d 218a unlock(&palloc); . 217d 213a . 212d 187d 183a unlock(&palloc); . 180a lock(&palloc); . 156a unlock(&palloc); . 142,148c if(p->ref != 0) panic("newpage"); . 139d 137d 132d 76d ## diffname port/page.c 1998/0605 ## diff -e /n/emeliedump/1998/0513/sys/src/brazil/port/page.c /n/emeliedump/1998/0605/sys/src/brazil/port/page.c 414,424c if(++f->ref == 1) pageunchain(f); . 298,309d 289,296c pageunchain(np); pagechaintail(np); . 250c panic("duppage %d", retries); . 248a . 225,227c pageunchain(p); . 181,205c if(p->image && p->image != &swapimage) pagechaintail(p); else pagechainhead(p); . 127,135c pageunchain(p); . 74d 65a static void pageunchain(Page *p) { if(canlock(&palloc)) panic("pageunchain"); if(p->prev) p->prev->next = p->next; else palloc.head = p->next; if(p->next) p->next->prev = p->prev; else palloc.tail = p->prev; p->prev = p->next = nil; palloc.freecount--; } void pagechaintail(Page *p) { if(canlock(&palloc)) panic("pagechaintail"); if(palloc.tail) { p->prev = palloc.tail; palloc.tail->next = p; } else { palloc.head = p; p->prev = 0; } palloc.tail = p; p->next = 0; palloc.freecount++; } void pagechainhead(Page *p) { if(canlock(&palloc)) panic("pagechainhead"); if(palloc.head) { p->next = palloc.head; palloc.head->prev = p; } else { palloc.tail = p; p->next = 0; } palloc.head = p; p->prev = 0; palloc.freecount++; } . 10d ## diffname port/page.c 1998/0825 ## diff -e /n/emeliedump/1998/0605/sys/src/brazil/port/page.c /n/emeliedump/1998/0825/sys/src/brazil/port/page.c 61,62c print("%ludK bytes\n", pm); print("%ludK swap\n", vm); . ## diffname port/page.c 1999/0108 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/port/page.c /n/emeliedump/1999/0108/sys/src/brazil/port/page.c 392a putimage(f->image); f->image = 0; f->daddr = 0; . 276a /* No dup for swap/cache pages but we still have to uncache */ if(p->image->notext){ uncachepage(p); return; } . 273,274c /* don't dup pages with no image */ if(p->ref == 0 || p->image == nil) . ## diffname port/page.c 1999/0109 ## diff -e /n/emeliedump/1999/0108/sys/src/brazil/port/page.c /n/emeliedump/1999/0109/sys/src/brazil/port/page.c 398,401c lock(f); if(f->image == i && f->daddr == daddr){ *l = f->hash; putimage(f->image); f->image = 0; f->daddr = 0; } unlock(f); . 277,282d 274c if(p->ref == 0 || p->image == nil || p->image->notext) . 217a if(p->ref == 0) panic("putpage"); . ## diffname port/page.c 2001/0110 ## diff -e /n/emeliedump/1999/0109/sys/src/brazil/port/page.c /n/emeliedump/2001/0110/sys/src/9/port/page.c 232a uncachepage(p); . ## diffname port/page.c 2001/0218 ## diff -e /n/emeliedump/2001/0110/sys/src/9/port/page.c /n/emeliedump/2001/0218/sys/src/9/port/page.c 233d ## diffname port/page.c 2001/0821 ## diff -e /n/emeliedump/2001/0218/sys/src/9/port/page.c /n/emeliedump/2001/0821/sys/src/9/port/page.c 60,61c print("%lud free pages, ", palloc.user); print("%ludK bytes, ", pm); . ## diffname port/page.c 2003/0405 ## diff -e /n/emeliedump/2001/0821/sys/src/9/port/page.c /n/emeliedump/2003/0405/sys/src/9/port/page.c 69c panic("pageunchain (palloc %p)", &palloc); . ## diffname port/page.c 2003/0417 ## diff -e /n/emeliedump/2003/0405/sys/src/9/port/page.c /n/emeliedump/2003/0417/sys/src/9/port/page.c 20a print("pageinit: allocated %p to %p\n", palloc.head, (uchar*)palloc.head+np*sizeof(Page)); . ## diffname port/page.c 2003/0418 ## diff -e /n/emeliedump/2003/0417/sys/src/9/port/page.c /n/emeliedump/2003/0418/sys/src/9/port/page.c 180d ## diffname port/page.c 2003/0506 ## diff -e /n/emeliedump/2003/0418/sys/src/9/port/page.c /n/emeliedump/2003/0506/sys/src/9/port/page.c 21d ## diffname port/page.c 2003/0507 ## diff -e /n/emeliedump/2003/0506/sys/src/9/port/page.c /n/emeliedump/2003/0507/sys/src/9/port/page.c 178a .