2 #include "../port/lib.h"
6 #include "../port/error.h"
8 #define pghash(daddr) palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]
18 ulong m, np, k, vkb, pkb;
21 for(i=0; i<nelem(palloc.mem); i++){
25 palloc.pages = xalloc(np*sizeof(Page));
30 palloc.head = palloc.pages;
32 for(i=0; i<nelem(palloc.mem); i++){
34 for(j=0; j<pm->npage; j++){
37 p->pa = pm->base+j*BY2PG;
40 color = (color+1)%NCOLOR;
45 palloc.head->prev = 0;
46 palloc.tail->next = 0;
48 palloc.user = p - palloc.pages;
49 pkb = palloc.user*BY2PG/1024;
50 vkb = pkb + (conf.nswap*BY2PG)/1024;
53 swapalloc.highwater = (palloc.user*5)/100;
54 swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
57 for(i=0; i<nelem(conf.mem); i++)
59 m += conf.mem[i].npage*BY2PG;
60 k = PGROUND(end - (char*)KTZERO);
61 print("%ldM memory: ", (m+k+1024*1024-1)/(1024*1024));
62 print("%ldM kernel data, ", (m+k-pkb*1024+1024*1024-1)/(1024*1024));
63 print("%ldM user, ", pkb/1024);
64 print("%ldM swap\n", vkb/1024);
71 panic("pageunchain (palloc %p)", &palloc);
73 p->prev->next = p->next;
75 palloc.head = p->next;
77 p->next->prev = p->prev;
79 palloc.tail = p->prev;
80 p->prev = p->next = nil;
85 pagechaintail(Page *p)
88 panic("pagechaintail");
90 p->prev = palloc.tail;
91 palloc.tail->next = p;
103 pagechainhead(Page *p)
106 panic("pagechainhead");
108 p->next = palloc.head;
109 palloc.head->prev = p;
121 newpage(int clear, Segment **s, ulong va)
129 color = getpgcolor(va);
130 hw = swapalloc.highwater;
132 if(palloc.freecount > hw)
134 if(up->kp && palloc.freecount > 0)
139 qunlock(&((*s)->lk));
142 eqlock(&palloc.pwait); /* Hold memory requesters here */
146 tsleep(&palloc.r, ispages, 0, 1000);
150 qunlock(&palloc.pwait);
156 * If called from fault and we lost the segment from
157 * underneath don't waste time allocating and freeing
158 * a page. Fault will call newpage again when it has
159 * reacquired the segment locks
169 /* First try for our colour */
170 for(p = palloc.head; p; p = p->next)
171 if(p->color == color)
185 panic("newpage: p->ref %d != 0", p->ref);
191 for(i = 0; i < MAXMACH; i++)
198 memset((void*)VA(k), 0, BY2PG);
208 return palloc.freecount >= swapalloc.highwater;
231 if(p->image && p->image != &swapimage)
250 if(palloc.freecount < swapalloc.highwater) {
268 duppage(Page *p) /* Always call with p locked */
274 * normal lock ordering is to call
275 * lock(&palloc) before lock(p).
276 * To avoid deadlock, we have to drop
277 * our locks and try again. as the page
278 * is from the image cache, this might
279 * let someone else come in and grab it
280 * so we check page ref below.
282 if(!canlock(&palloc)){
288 /* don't dup pages that are shared or have no image */
289 if(p->ref != 1 || p->image == nil || p->image->notext){
294 /* No freelist cache when memory is very low */
295 if(palloc.freecount < swapalloc.highwater) {
301 color = getpgcolor(p->va);
302 for(np = palloc.head; np; np = np->next)
303 if(np->color == color)
306 /* No page of the correct color */
316 * XXX - here's a bug? - np is on the freelist but it's not really free.
317 * when we unlock palloc someone else can come in, decide to
318 * use np, and then try to lock it. they succeed after we've
319 * run copypage and cachepage and unlock(np). then what?
320 * they call pageunchain before locking(np), so it's removed
321 * from the freelist, but still in the cache because of
322 * cachepage below. if someone else looks in the cache
323 * before they remove it, the page will have a nonzero ref
324 * once they finally lock(np). This does not happen because
325 * newpage, auxpage, duppage and lookpage all lock(&palloc)
326 * so while they hold it nobody is going to grab anything
330 if(np->ref != 0) /* should never happen */
331 panic("duppage: np->ref %d != 0", np->ref);
334 /* Cache the new version */
337 np->daddr = p->daddr;
339 cachepage(np, p->image);
345 copypage(Page *f, Page *t)
351 memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
357 uncachepage(Page *p) /* Always called with a locked page */
364 lock(&palloc.hashlock);
365 l = &pghash(p->daddr);
366 for(f = *l; f; f = f->hash) {
373 unlock(&palloc.hashlock);
380 cachepage(Page *p, Image *i)
384 /* If this ever happens it should be fixed by calling
385 * uncachepage instead of panic. I think there is a race
386 * with pio in which this can happen. Calling uncachepage is
387 * correct - I just wanted to see if we got here.
393 lock(&palloc.hashlock);
395 l = &pghash(p->daddr);
398 unlock(&palloc.hashlock);
402 cachedel(Image *i, ulong daddr)
407 lock(&palloc.hashlock);
408 for(f = pghash(daddr); f; f = f->hash) {
409 if(f->image == i && f->daddr == daddr) {
410 unlock(&palloc.hashlock);
413 if(f->image != i || f->daddr != daddr) {
423 unlock(&palloc.hashlock);
427 lookpage(Image *i, ulong daddr)
432 lock(&palloc.hashlock);
433 for(f = pghash(daddr); f; f = f->hash) {
434 if(f->image == i && f->daddr == daddr) {
435 unlock(&palloc.hashlock);
439 if(f->image != i || f->daddr != daddr) {
452 unlock(&palloc.hashlock);
464 dst = &new->pages[old->first-old->pages];
466 for(src = old->first; src <= old->last; src++, dst++)
487 new = smalloc(sizeof(Pte));
488 new->first = &new->pages[PTEPERTAB];
489 new->last = new->pages;
494 freepte(Segment *s, Pte *p)
498 Page *pt, **pg, **ptop;
500 switch(s->type&SG_TYPE) {
502 fn = s->pseg->pgfree;
503 ptop = &p->pages[PTEPERTAB];
505 for(pg = p->pages; pg < ptop; pg++) {
513 for(pg = p->pages; pg < ptop; pg++) {
525 for(pg = p->first; pg <= p->last; pg++)
537 return p-palloc.pages;
548 ref = malloc(np*sizeof ref[0]);
550 print("checkpagerefs: out of memory\n");
555 * This may not be exact if there are other processes
556 * holding refs to pages on their stacks. The hope is
557 * that if you run it on a quiescent system it will still
562 countpagerefs(ref, 0);
563 portcountpagerefs(ref, 0);
566 if(palloc.pages[i].ref != ref[i]){
567 iprint("page %#.8lux ref %d actual %lud\n",
568 palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
574 countpagerefs(ref, 1);
575 portcountpagerefs(ref, 1);
576 iprint("%lud mistakes found\n", nwrong);
582 portcountpagerefs(ulong *ref, int print)
584 ulong i, j, k, ns, n;
591 * Pages in segments. s->mark avoids double-counting.
595 for(i=0; i<conf.nproc; i++){
597 for(j=0; j<NSEG; j++){
603 for(i=0; i<conf.nproc; i++){
605 for(j=0; j<NSEG; j++){
607 if(s == nil || s->mark++)
610 for(k=0; k<s->mapsize; k++){
614 for(pg = pte->first; pg <= pte->last; pg++){
619 if(ref[pagenumber(entry)])
620 iprint("page %#.8lux in segment %#p\n", entry->pa, s);
623 if(ref[pagenumber(entry)]++ == 0)
630 iprint("%lud pages in %lud segments\n", n, ns);
631 for(i=0; i<conf.nproc; i++){
633 for(j=0; j<NSEG; j++){
637 if(s->ref != s->mark){
638 iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
639 s, i, p->pid, s->ref, s->mark);