--- /sys/src/9k/k10/asm.c +++ /sys/src/9k/k10/asm.c @@ -287,10 +287,9 @@ asmmeminit(void) { Asm* asm; PTE *pte; - int i, j, l; + int i, l; uintptr n, va; uintmem hi, lo, mem, nextmem, pa; - Pallocmem *pm; /* * to do here (done?): @@ -371,26 +370,22 @@ asmmeminit(void) } n = sys->vmend - sys->vmstart; /* close enough */ - if(n > 3*600ull*MiB) - n = 3*600ull*MiB; - ialloclimit(n/2); + if(n > 600ull*MiB) + n = 600ull*MiB; + ialloclimit(n/3); +} + +void +asmumeminit(void) +{ + Asm *asm; + extern void physallocdump(void); - pm = palloc.mem; - j = 0; for(asm = asmlist; asm != nil; asm = asm->next){ - if(asm->limit == asm->base) - continue; - if(pm >= palloc.mem+nelem(palloc.mem)){ - print("asmmeminit: losing %#P pages\n", - (asm->limit - asm->base)/PGSZ); + if(asm->type != AsmMEMORY) continue; - } - pm->base = asm->base; - pm->limit = asm->limit; - - DBG("asm pm%d: base %#P limit %#P npage %llud\n", - j, pm->base, pm->limit, (pm->limit - pm->base)/PGSZ); - j++; - pm++; + physinit(asm->addr, asm->size); + sys->pmpaged += ROUNDDN(asm->limit, 2*MiB) - ROUNDUP(asm->base, 2*MiB); } -} + physallocdump(); +} \ No newline at end of file --- /sys/src/9k/k10/dat.h +++ /sys/src/9k/k10/dat.h @@ -247,6 +247,7 @@ struct Sys { u64int pmstart; /* physical memory */ u64int pmoccupied; /* how much is occupied */ u64int pmend; /* total span */ + u64int pmpaged; /* how much assigned to page pool */ uintptr vmstart; /* base address for malloc */ uintptr vmunused; /* 1st unused va */ --- /sys/src/9k/k10/devacpi.c +++ /sys/src/9k/k10/devacpi.c @@ -870,6 +870,20 @@ acpislit(uchar *p, int len) return nil; /* can be unmapped once parsed */ } +uintmem +acpimblocksize(uintmem addr, int *dom) +{ + Srat *sl; + + for(sl = srat; sl != nil; sl = sl->next) + if(sl->type == SRmem) + if(sl->mem.addr <= addr && sl->mem.addr + sl->mem.len > addr){ + *dom = sl->mem.dom; + return sl->mem.len - (addr - sl->mem.addr); + } + return 0; +} + /* * Return a number identifying a color for the memory at * the given address (color identifies locality) and fill *sizep --- /sys/src/9k/k10/fns.h +++ /sys/src/9k/k10/fns.h @@ -131,6 +131,7 @@ void tssrsp0(u64int); void trapenable(int, void (*)(Ureg*, void*), void*, char*); void trapinit(void); int userureg(Ureg*); +void umeminit(void); void* vmap(uintmem, usize); void vsvminit(int); void vunmap(void*, usize); --- /sys/src/9k/k10/k10aoe +++ /sys/src/9k/k10/k10aoe @@ -149,6 +149,7 @@ port image latin1 page + pager parse pgrp portclock --- /sys/src/9k/k10/k10cpu +++ /sys/src/9k/k10/k10cpu @@ -143,6 +143,7 @@ port image latin1 page + pager parse pgrp portclock --- /sys/src/9k/k10/k10cpuf +++ /sys/src/9k/k10/k10cpuf @@ -153,6 +153,7 @@ port image latin1 page + pager parse pgrp portclock --- /sys/src/9k/k10/k10f +++ /sys/src/9k/k10/k10f @@ -163,6 +163,7 @@ port image latin1 page + pager parse pgrp portclock --- /sys/src/9k/k10/k10root +++ /sys/src/9k/k10/k10root @@ -145,6 +145,7 @@ port image latin1 page + pager parse pgrp portclock --- /sys/src/9k/k10/main.c +++ /sys/src/9k/k10/main.c @@ -213,6 +213,7 @@ main(u32int ax, u32int bx) meminit(); archinit(); mallocinit(); + umeminit(); trapinit(); /* @@ -392,7 +393,7 @@ userinit(void) */ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKTOP); p->seg[SSEG] = s; - pg = newpage(1, s, USTKTOP-segpgsize(s), 0); + pg = newpage(1, s, USTKTOP-segpgsize(s), PGSHFT, -1, 0); segpage(s, pg); k = kmap(pg); bootargs(VA(k)); @@ -404,7 +405,7 @@ userinit(void) s = newseg(SG_TEXT, UTZERO, UTZERO+PGSZ); s->flushme++; p->seg[TSEG] = s; - pg = newpage(1, s, UTZERO, 0); + pg = newpage(1, s, UTZERO, PGSHFT, -1, 0); mmucachectl(pg, PG_TXTFLUSH); segpage(s, pg); k = kmap(s->map[0]->pages[0]); --- /sys/src/9k/k10/memory.c +++ /sys/src/9k/k10/memory.c @@ -17,3 +17,11 @@ meminit(void) asmmeminit(); } + +void +umeminit(void) +{ + extern void asmumeminit(void); + + asmumeminit(); +} --- /sys/src/9k/port/cache.c +++ /sys/src/9k/port/cache.c @@ -356,7 +356,7 @@ cchain(uchar *buf, ulong offset, int len, Extent **tail) if(e == 0) break; - p = auxpage(); + p = auxpage(PGSHFT); if(p == 0) { extentfree(e); break; --- /sys/src/9k/port/devcons.c +++ /sys/src/9k/port/devcons.c @@ -826,7 +826,7 @@ consread(Chan *c, void *buf, long n, vlong off) { ulong l; Mach *mp; - char *b, *bp, ch; + char *b, *bp, ch, *s; char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */ int i, k, id, send; long offset; @@ -993,18 +993,12 @@ consread(Chan *c, void *buf, long n, vlong off) return n; case Qswap: - l = snprint(tmp, sizeof tmp, - "%llud memory\n" - "%d pagesize\n" - "%llud kernel\n" - "%lud/%lud user\n" - "0/0 swap\n", /* keep old 9 scripts happy */ - sys->pmoccupied, - PGSZ, - ROUNDUP(sys->vmend - KTZERO, PGSZ)/PGSZ, - palloc.user-palloc.freecount, palloc.user); + tmp[0] = 0; + s = seprintpagestats(tmp, tmp + sizeof tmp); + s = seprintphysstats(s, tmp + sizeof tmp); b = buf; - i = readstr(offset, b, n, tmp); + l = s - tmp; + i = readstr(offset, b, l, tmp); b += i; n -= i; if(offset > l) --- /sys/src/9k/port/devproc.c +++ /sys/src/9k/port/devproc.c @@ -1577,7 +1577,7 @@ procctlmemio(Proc *p, uintptr offset, int n, void *va, int read) s->steal--; nexterror(); } - if(fixfault(s, offset, read, 0) == 0) + if(fixfault(s, offset, read, 0, s->color) == 0) break; poperror(); s->steal--; --- /sys/src/9k/port/fault.c +++ /sys/src/9k/port/fault.c @@ -10,6 +10,7 @@ fault(uintptr addr, int read) { Segment *s; char *sps; + int i, color; if(up == nil) panic("fault: nil up"); @@ -21,7 +22,7 @@ fault(uintptr addr, int read) spllo(); m->pfault++; - for(;;) { + for(i = 0;; i++) { s = seg(up, addr, 1); /* leaves s->lk qlocked if seg != nil */ if(s == nil) { up->psstate = sps; @@ -34,7 +35,10 @@ fault(uintptr addr, int read) return -1; } - if(fixfault(s, addr, read, 1) == 0) /* qunlocks s->lk */ + color = s->color; + if(i > 3) + color = -1; + if(fixfault(s, addr, read, 1, color) == 0) /* qunlocks s->lk */ break; /* @@ -67,7 +71,7 @@ void (*checkaddr)(ulong, Segment *, Page *); ulong addr2check; int -fixfault(Segment *s, uintptr addr, int read, int dommuput) +fixfault(Segment *s, uintptr addr, int read, int dommuput, int color) { int type; int ref; @@ -100,7 +104,7 @@ fixfault(Segment *s, uintptr addr, int read, int dommuput) case SG_TEXT: /* Demand load */ if(pagedout(*pg)) - pio(s, addr, soff, pg); + pio(s, addr, soff, pg, color); mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID; (*pg)->modref = PG_REF; @@ -110,7 +114,7 @@ fixfault(Segment *s, uintptr addr, int read, int dommuput) case SG_SHARED: /* Zero fill on demand */ case SG_STACK: if(*pg == nil) { - new = newpage(1, s, addr, 1); + new = newpage(1, s, addr, s->lg2pgsize, color, 1); if(new == nil) return -1; @@ -121,7 +125,7 @@ fixfault(Segment *s, uintptr addr, int read, int dommuput) case SG_DATA: common: /* Demand load/pagein/copy on write */ if(pagedout(*pg)) - pio(s, addr, soff, pg); + pio(s, addr, soff, pg, color); /* * It's only possible to copy on write if @@ -147,7 +151,7 @@ fixfault(Segment *s, uintptr addr, int read, int dommuput) unlock(lkp); if(ref > 1) { - new = newpage(0, s, addr, 1); + new = newpage(0, s, addr, s->lg2pgsize, color, 1); if(new == nil) return -1; *pg = new; @@ -194,7 +198,7 @@ fixfault(Segment *s, uintptr addr, int read, int dommuput) } void -pio(Segment *s, uintptr addr, uintptr soff, Page **p) +pio(Segment *s, uintptr addr, uintptr soff, Page **p, int color) { Page *new; KMap *k; @@ -223,7 +227,7 @@ pio(Segment *s, uintptr addr, uintptr soff, Page **p) ask = pgsize; qunlock(&s->lk); - new = newpage(0, s, addr, 0); + new = newpage(0, s, addr, s->lg2pgsize, color, 0); if(new == nil) panic("pio"); /* can't happen, s wasn't locked */ --- /sys/src/9k/port/image.c +++ /sys/src/9k/port/image.c @@ -101,7 +101,7 @@ imagechanreclaim(void) } Image* -attachimage(int type, Chan *c, uintptr base, uintptr top) +attachimage(int type, Chan *c, int color, uintptr base, uintptr top) { Image *i, **l; @@ -150,6 +150,7 @@ attachimage(int type, Chan *c, uintptr base, uintptr top) i->qid = c->qid; i->mqid = c->mqid; i->mchan = c->mchan; + i->color = color; l = &ihash(c->qid.path); i->hash = *l; *l = i; @@ -164,6 +165,7 @@ found: } i->s = newseg(type, base, top); i->s->image = i; + i->s->color = color; i->ref++; poperror(); } --- /sys/src/9k/port/page.c +++ /sys/src/9k/port/page.c @@ -4,107 +4,43 @@ #include "dat.h" #include "fns.h" +enum +{ + Nfreepgs = 0, // 1*GiB/PGSZ +}; + #define pghash(daddr) palloc.hash[(daddr>>PGSHFT)&(PGHSIZE-1)] struct Palloc palloc; static uint highwater; /* TO DO */ -/* - * Split palloc.mem[i] if it's not all of the same color and we can. - * Return the new end of the known banks. - */ -static int -splitbank(int i, int e) +char* +seprintpagestats(char *s, char *e) { - Pallocmem *pm; - uintmem psz; + Pallocpg *pg; + int i; - if(e == nelem(palloc.mem)) - return 0; - pm = &palloc.mem[i]; - pm->color = memcolor(pm->base, &psz); - if(pm->color < 0){ - pm->color = 0; - if(i > 0) - pm->color = pm[-1].color; - return 0; + lock(&palloc); + for(i = 0; i < nelem(palloc.avail); i++){ + pg = &palloc.avail[i]; + if(pg->freecount != 0) + s = seprint(s, e, "%lud/%lud %dK user pages avail\n", + pg->freecount, + pg->count, (1<= (pm->limit - pm->base)) - return 0; - if(i+1 < e) - memmove(pm+2, pm+1, (e-i-1)*sizeof(Pallocmem)); - pm[1].base = pm->base + psz; - pm[1].limit = pm->limit; - pm->limit = pm[1].base; - DBG("palloc split[%d] col %d %#P %#P -> %#P\n", - i, pm->color, pm->base, pm[1].limit, pm->limit); - - return 1; + unlock(&palloc); + return s; } void pageinit(void) { - int e, i, j; - Page *p; - Pallocmem *pm; - uintmem np, pkb, kkb, kmkb, mkb; + uintmem avail; + uvlong pkb, kkb, kmkb, mkb; - for(e = 0; e < nelem(palloc.mem); e++){ - if(palloc.mem[e].base == palloc.mem[e].limit) - break; - } - - /* - * Split banks if not of the same color - * and the array can hold another item. - */ - np = 0; - for(i=0; icolor, pm->base, pm->limit); - -/* BUG; can't handle it all right now */ -if(pm->base > 3*600ull*MiB){ - pm->limit = pm->base; - continue; -} -if(pm->limit > 3*600ull*MiB) - pm->limit = 3*600ull*MiB; - - np += (pm->limit - pm->base)/PGSZ; - } - - palloc.pages = malloc(np*sizeof(Page)); - if(palloc.pages == nil) - panic("pageinit"); - - palloc.head = palloc.pages; - p = palloc.head; - for(i=0; ilimit - pm->base)/PGSZ; - for(j=0; jprev = p-1; - p->next = p+1; - p->pa = pm->base+j*PGSZ; - p->lg2size = PGSHFT; - p->color = pm->color; - palloc.freecount++; - p++; - } - } - palloc.tail = p - 1; - palloc.head->prev = nil; - palloc.tail->next = nil; - - palloc.user = p - palloc.pages; + avail = sys->pmpaged; + palloc.user = avail/PGSZ; /* user, kernel, kernel malloc area, memory */ pkb = palloc.user*PGSZ/KiB; @@ -118,60 +54,109 @@ if(pm->limit > 3*600ull*MiB) highwater = 64*MiB/PGSZ; print("%lldM memory: %lldK+%lldM kernel, %lldM user, %lldM lost\n", - mkb/KiB, kkb, kmkb/KiB, pkb/KiB, (mkb-kkb-kmkb-pkb)/KiB); + mkb/KiB, kkb, kmkb/KiB, pkb/KiB, (vlong)(mkb-kkb-kmkb-pkb)/KiB); +} + +Page* +pgalloc(uint lg2size, int color) +{ + Page *pg; + + if((pg = malloc(sizeof(Page))) == nil){ + DBG("pgalloc: malloc failed\n"); + return nil; + } + memset(pg, 0, sizeof *pg); + if((pg->pa = physalloc(1<lg2size = lg2size; + palloc.avail[pg->lg2size].count++; + pg->color = color; + return pg; +} + +void +pgfree(Page* pg) +{ + palloc.avail[pg->lg2size].count--; + physfree(pg->pa, pagesize(pg)); + free(pg); } -static void +void pageunchain(Page *p) { + Pallocpg *pg; + if(canlock(&palloc)) panic("pageunchain (palloc %#p)", &palloc); + pg = &palloc.avail[p->lg2size]; if(p->prev) p->prev->next = p->next; else - palloc.head = p->next; + pg->head = p->next; if(p->next) p->next->prev = p->prev; else - palloc.tail = p->prev; + pg->tail = p->prev; p->prev = p->next = nil; - palloc.freecount--; + pg->freecount--; } void pagechaintail(Page *p) { + Pallocpg *pg; + if(canlock(&palloc)) panic("pagechaintail"); - if(palloc.tail) { - p->prev = palloc.tail; - palloc.tail->next = p; + pg = &palloc.avail[p->lg2size]; + if(pg->tail) { + p->prev = pg->tail; + pg->tail->next = p; } else { - palloc.head = p; + pg->head = p; p->prev = nil; } - palloc.tail = p; + pg->tail = p; p->next = nil; - palloc.freecount++; + pg->freecount++; } void pagechainhead(Page *p) { + Pallocpg *pg; + if(canlock(&palloc)) panic("pagechainhead"); - if(palloc.head) { - p->next = palloc.head; - palloc.head->prev = p; + pg = &palloc.avail[p->lg2size]; + if(pg->head) { + p->next = pg->head; + pg->head->prev = p; } else { - palloc.tail = p; + pg->tail = p; p->next = nil; } - palloc.head = p; + pg->head = p; p->prev = nil; - palloc.freecount++; + pg->freecount++; +} + +static Page* +findpg(Page *pl, int color) +{ + Page *p; + + for(p = pl; p != nil; p = p->next) + if(color == NOCOLOR || p->color == color) + return p; + return nil; } /* @@ -179,21 +164,36 @@ pagechainhead(Page *p) * return nil iff s was locked on entry and had to be unlocked to wait for memory. */ Page* -newpage(int clear, Segment *s, uintptr va, int locked) +newpage(int clear, Segment *s, uintptr va, uint lg2pgsize, int color, int locked) { Page *p; KMap *k; uchar ct; - int i, hw, dontalloc, color; + Pallocpg *pg; + int i, hw, dontalloc; + static int once; lock(&palloc); - color = getpgcolor(va); + pg = &palloc.avail[lg2pgsize]; hw = highwater; - for(;;) { - if(palloc.freecount > hw) + for(i = 0;; i++) { + if(pg->freecount > hw) break; - if(up->kp && palloc.freecount > 0) + if(up != nil && up->kp && pg->freecount > 0) + break; + + if(i > 3) + color = NOCOLOR; + + p = findpg(pg->head, color); + if(p != nil) + break; + + p = pgalloc(lg2pgsize, color); + if(p != nil){ + pagechainhead(p); break; + } unlock(&palloc); dontalloc = 0; @@ -207,10 +207,8 @@ newpage(int clear, Segment *s, uintptr va, int locked) while(waserror()) /* Ignore interrupts */ ; - print("out of physical memory\n"); - pagereclaim(highwater/2); - - tsleep(&palloc.r, ispages, 0, 1000); + kickpager(lg2pgsize, color); + tsleep(&palloc.r, ispages, pg, 1000); poperror(); @@ -229,13 +227,13 @@ newpage(int clear, Segment *s, uintptr va, int locked) } /* First try for our colour */ - for(p = palloc.head; p; p = p->next) - if(p->color == color) + for(p = pg->head; p; p = p->next) + if(color == NOCOLOR || p->color == color) break; ct = PG_NOFLUSH; if(p == nil) { - p = palloc.head; + p = pg->head; p->color = color; ct = PG_NEWCOL; } @@ -264,14 +262,17 @@ newpage(int clear, Segment *s, uintptr va, int locked) } int -ispages(void*) +ispages(void *a) { - return palloc.freecount > highwater; + return ((Pallocpg*)a)->freecount > highwater; } void putpage(Page *p) { + Pallocpg *pg; + int rlse; + lock(&palloc); lock(p); @@ -284,26 +285,39 @@ putpage(Page *p) return; } + rlse = 0; if(p->image != nil) pagechaintail(p); - else - pagechainhead(p); + else{ + /* + * Free pages if we have plenty in the free list. + */ + pg = &palloc.avail[p->lg2size]; + if(pg->freecount > Nfreepgs) + rlse = 1; + else + pagechainhead(p); + } if(palloc.r.p != nil) wakeup(&palloc.r); unlock(p); + if(rlse) + pgfree(p); unlock(&palloc); } Page* -auxpage(void) +auxpage(uint lg2size) { Page *p; + Pallocpg *pg; lock(&palloc); - p = palloc.head; - if(palloc.freecount <= highwater) { + pg = &palloc.avail[lg2size]; + p = pg->head; + if(pg->freecount <= highwater) { /* memory's tight, don't use it for file cache */ unlock(&palloc); return nil; @@ -326,6 +340,7 @@ static int dupretries = 15000; int duppage(Page *p) /* Always call with p locked */ { + Pallocpg *pg; Page *np; int color; int retries; @@ -369,15 +384,16 @@ retry: goto retry; } + pg = &palloc.avail[p->lg2size]; /* No freelist cache when memory is relatively low */ - if(palloc.freecount <= highwater) { + if(pg->freecount <= highwater) { unlock(&palloc); uncachepage(p); return 1; } - color = getpgcolor(p->va); - for(np = palloc.head; np; np = np->next) + color = p->color; + for(np = pg->head; np; np = np->next) if(np->color == color) break; @@ -535,6 +551,7 @@ pagereclaim(int npages) { Page *p; uvlong ticks; + int i; lock(&palloc); ticks = fastticks(nil); @@ -544,15 +561,17 @@ pagereclaim(int npages) * end of the list (see putpage) so start there and work * backward. */ - for(p = palloc.tail; p != nil && p->image != nil && npages > 0; p = p->prev) { - if(p->ref == 0 && canlock(p)) { - if(p->ref == 0) { - npages--; - uncachepage(p); - pageunchain(p); - pagechainhead(p); + for(i = 0; i < nelem(palloc.avail); i++) { + for(p = palloc.avail[i].tail; p != nil && p->image != nil && npages > 0; p = p->prev) { + if(p->ref == 0 && canlock(p)) { + if(p->ref == 0) { + npages--; + uncachepage(p); + pageunchain(p); + pagechainhead(p); + } + unlock(p); } - unlock(p); } } ticks = fastticks(nil) - ticks; --- /dev/null +++ /sys/src/9k/port/pager.c @@ -0,0 +1,163 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +/* + * There's no pager process here. + * One process waiting for memory becomes the pager, + * during the call to kickpager() + */ + +static QLock pagerlck; +static struct +{ + ulong ntext; + ulong nbig; + ulong nall; +} pstats; + +static void +freepages(uint lg2size, int once) +{ + Pallocpg *pg; + Page *p; + int i; + + for(i = lg2size; i < nelem(palloc.avail); i++){ + pg = &palloc.avail[i]; + if(pg->freecount > 0){ + DBG("kickpager() up %#p: releasing %udK pages\n", + up, (1<freecount == 0){ + unlock(&palloc); + continue; + } + p = pg->head; + pageunchain(p); + unlock(&palloc); + if(p->ref != 0) + panic("freepages pa %#ullx", p->pa); + pgfree(p); + if(once) + break; + } + } +} + +static int +tryalloc(int lg2size, int color) +{ + Page *p; + + p = pgalloc(lg2size, color); + if(p != nil){ + lock(&palloc); + pagechainhead(p); + unlock(&palloc); + return 0; + } + return -1; +} + +static int +hascolor(Page *pl, int color) +{ + Page *p; + + lock(&palloc); + for(p = pl; p != nil; p = p->next) + if(color == NOCOLOR || p->color == color){ + unlock(&palloc); + return 1; + } + unlock(&palloc); + return 0; +} + +/* + * Someone couldn't find pages of the given size index and color. + * (color may be NOCOLOR if the caller is trying to get any page + * and is desperate). + * Many processes may be calling this at the same time, + * The first one operates as a pager and does what it can. + */ +void +kickpager(uint lg2size, int color) +{ + Pallocpg *pg; + + print("kickpager page size %dK color %d\n", (1<1) + DBG("kickpager() %#p\n", up); + if(waserror()) + panic("error in kickpager"); + qlock(&pagerlck); + pg = &palloc.avail[lg2size]; + + /* + * 1. did anyone else release one for us in the mean time? + */ + if(hascolor(pg->head, color)) + goto Done; + + /* + * 2. try allocating from physical memory + */ + tryalloc(lg2size, color); + if(hascolor(pg->head, color)) + goto Done; + + /* + * Try releasing memory from bigger pages. + */ + pstats.nbig++; + freepages(1<<(lg2size+1), 1); + tryalloc(lg2size, color); + if(hascolor(pg->head, color)){ + DBG("kickpager() found %uld free\n", pg->freecount); + goto Done; + } + + /* + * Really the last resort. Try releasing memory from all pages. + */ + pstats.nall++; + DBG("kickpager() up %#p: releasing all pages\n", up); + freepages(0, 0); + tryalloc(lg2size, color); + if(pg->freecount > 0){ + DBG("kickpager() found %uld free\n", pg->freecount); + goto Done; + } + + /* + * What else can we do? + * But don't panic if we are still trying to get memory of + * a particular color and there's none. We'll retry asking + * for any color. + */ + if(color == NOCOLOR){ + print("out of physical memory\n"); + killbig("out of physical memory"); + freebroken(); + } + +Done: + poperror(); + qunlock(&pagerlck); + if(DBGFLG>1) + DBG("kickpager() done %#p\n", up); +} + +void +pagersummary(void) +{ + print("ntext %uld nbig %uld nall %uld\n", + pstats.ntext, pstats.nbig, pstats.nall); + print("no swap\n"); +} --- /sys/src/9k/port/portdat.h +++ /sys/src/9k/port/portdat.h @@ -26,7 +26,7 @@ typedef struct Note Note; typedef struct Page Page; typedef struct Path Path; typedef struct Palloc Palloc; -typedef struct Pallocmem Pallocmem; +typedef struct Pallocpg Pallocpg; typedef struct Perf Perf; typedef struct PhysUart PhysUart; typedef struct Pgrp Pgrp; @@ -340,6 +340,7 @@ struct Image Image *hash; /* Qid hash chains */ Image *next; /* Free list */ int notext; /* no file associated */ + int color; }; struct Pte @@ -390,12 +391,15 @@ struct Sema Sema* prev; }; +#define NOCOLOR -1 + struct Segment { Ref; QLock lk; ushort steal; /* Page stealer lock */ ushort type; /* segment type */ + int color; uintptr base; /* virtual base */ uintptr top; /* virtual top */ usize size; /* size in pages */ @@ -479,21 +483,18 @@ enum DELTAFD = 20 /* incremental increase in Fgrp.fd's */ }; -struct Pallocmem +struct Pallocpg { - uintmem base; - uintmem limit; - int color; + Page *head; /* most recently used */ + Page *tail; /* least recently used */ + ulong count; /* how many pages made */ + ulong freecount; /* how many pages on free list now */ }; struct Palloc { Lock; - Pallocmem mem[32]; - Page *head; /* most recently used */ - Page *tail; /* least recently used */ - ulong freecount; /* how many pages on free list now */ - Page *pages; /* array of all pages */ + Pallocpg avail[32]; /* indexed by log2 of page size (Page.lgsize) */ ulong user; /* how many user pages */ Page *hash[PGHSIZE]; Lock hashlock; @@ -740,6 +741,7 @@ struct Proc void *ureg; /* User registers for notes */ void *dbgreg; /* User registers for devproc */ + int color; Fastcall* fc; int fcount; --- /sys/src/9k/port/portfns.h +++ /sys/src/9k/port/portfns.h @@ -13,8 +13,8 @@ void alarmkproc(void*); Block* allocb(int); int anyhigher(void); int anyready(void); -Image* attachimage(int, Chan*, uintptr, uintptr); -Page* auxpage(void); +Image* attachimage(int, Chan*, int, uintptr, uintptr); +Page* auxpage(uint); Block* bl2mem(uchar*, Block*, int); int blocklen(Block*); void bootlinks(void); @@ -108,7 +108,7 @@ int fault(uintptr, int); void fdclose(int, int); Chan* fdtochan(int, int, int, int); int findmount(Chan**, Mhead**, int, uint, Qid); -int fixfault(Segment*, uintptr, int, int); +int fixfault(Segment*, uintptr, int, int, int); void fmtinit(void); void forceclosefgrp(void); void free(void*); @@ -142,7 +142,7 @@ int kbdcr2nl(Queue*, int); int kbdgetmap(uint, int*, int*, Rune*); int kbdputc(Queue*, int); void kbdputmap(ushort, ushort, Rune); -void kickpager(void); +void kickpager(uint, int); void killbig(char*); void kproc(char*, void(*)(void*), void*); void kprocchild(Proc*, void (*)(void*), void*); @@ -188,7 +188,7 @@ Chan* newchan(void); int newfd(Chan*); Mhead* newmhead(Chan*); Mount* newmount(Mhead*, Chan*, int, char*); -Page* newpage(int, Segment*, uintptr, int); +Page* newpage(int, Segment*, uintptr, uint, int, int); Path* newpath(char*); Pgrp* newpgrp(void); Rgrp* newrgrp(void); @@ -205,11 +205,14 @@ void pagechainhead(Page*); void pageinit(void); ulong pagenumber(Page*); uvlong pagereclaim(int); +void pageunchain(Page*); void panic(char*, ...); Cmdbuf* parsecmd(char *a, int n); void pathclose(Path*); ulong perfticks(void); void pexit(char*, int); +Page* pgalloc(uint, int); +void pgfree(Page*); void pgrpcpy(Pgrp*, Pgrp*); void pgrpnote(ulong, char*, long, int); uintmem physalloc(u64int, int*, void*); @@ -218,7 +221,7 @@ void physfree(uintmem, u64int); void physinit(uintmem, u64int); void* phystag(uintmem); int psindex(int); -void pio(Segment*, uintptr, uintptr, Page**); +void pio(Segment*, uintptr, uintptr, Page**, int); #define poperror() up->nerrlab-- int postnote(Proc*, int, char*, int); int pprint(char*, ...); @@ -305,6 +308,8 @@ long seconds(void); void segclock(uintptr); void segpage(Segment*, Page*); char* seprintmark(char *, char *, Watermark *); +char* seprintpagestats(char*, char*); +char* seprintphysstats(char*, char*); int setcolor(ulong, ulong, ulong, ulong); void setkernur(Ureg*, Proc*); int setlabel(Label*); --- /sys/src/9k/port/segment.c +++ /sys/src/9k/port/segment.c @@ -155,6 +155,7 @@ dupseg(Segment **seg, int segno, int share) n->fstart = s->fstart; n->flen = s->flen; n->lg2pgsize = s->lg2pgsize; + n->color = s->color; break; } size = s->mapsize; @@ -183,6 +184,9 @@ segpage(Segment *s, Page *p) uintptr soff; Page **pg; + if(s->color == NOCOLOR) + s->color = p->color; + if(p->va < s->base || p->va >= s->top) panic("segpage"); --- /sys/src/9k/port/sysproc.c +++ /sys/src/9k/port/sysproc.c @@ -206,6 +206,7 @@ sysrfork(Ar0* ar0, va_list list) strncpy((char*)&ptarg, p->text, sizeof ptarg); pt(p, SName, 0, ptarg); } + p->color = up->color; ready(p); sched(); @@ -356,6 +357,8 @@ sysexec(Ar0* ar0, va_list list) || datalim < textlim || bsslim < datalim) error(Ebadexec); + up->color = corecolor(m->machno); + /* * The new stack is created in ESEG, temporarily mapped elsewhere. * The stack contains, in descending address order: @@ -378,6 +381,7 @@ sysexec(Ar0* ar0, va_list list) nexterror(); } up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, TSTKTOP); + up->seg[ESEG]->color = up->color; /* * Stack is a pointer into the temporary stack @@ -541,17 +545,21 @@ sysexec(Ar0* ar0, va_list list) /* Text. Shared. Attaches to cache image if possible */ /* attachimage returns a locked cache image */ - img = attachimage(SG_TEXT|SG_RONLY, chan, UTZERO, textmin); + img = attachimage(SG_TEXT|SG_RONLY, chan, up->color, UTZERO, textmin); s = img->s; up->seg[TSEG] = s; s->flushme = 1; s->fstart = 0; s->flen = hdrsz+textsz; + if(img->color != up->color){ + up->color = img->color; + } unlock(img); /* Data. Shared. */ s = newseg(SG_DATA, textlim, datalim); up->seg[DSEG] = s; + s->color = up->color; /* Attached by hand */ incref(img); @@ -561,6 +569,7 @@ sysexec(Ar0* ar0, va_list list) /* BSS. Zero fill on demand */ up->seg[BSEG] = newseg(SG_BSS, datalim, bsslim); + up->seg[BSEG]->color= up->color; /* * Move the stack