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) {
267 static int dupretries = 15000;
270 duppage(Page *p) /* Always call with p locked */
278 /* don't dup pages that are shared or have no image */
279 if(p->ref != 1 || p->image == nil || p->image->notext)
282 if(retries++ > dupretries){
283 print("duppage %d, up %p\n", retries, up);
285 if(dupretries > 100000)
292 * normal lock ordering is to call
293 * lock(&palloc) before lock(p).
294 * To avoid deadlock, we have to drop
295 * our locks and try again. as the page
296 * is from the image cache, this might
297 * let someone else come in and grab it
298 * so we check page ref above.
300 if(!canlock(&palloc)){
308 /* No freelist cache when memory is very low */
309 if(palloc.freecount < swapalloc.highwater) {
315 color = getpgcolor(p->va);
316 for(np = palloc.head; np; np = np->next)
317 if(np->color == color)
320 /* No page of the correct color */
330 * XXX - here's a bug? - np is on the freelist but it's not really free.
331 * when we unlock palloc someone else can come in, decide to
332 * use np, and then try to lock it. they succeed after we've
333 * run copypage and cachepage and unlock(np). then what?
334 * they call pageunchain before locking(np), so it's removed
335 * from the freelist, but still in the cache because of
336 * cachepage below. if someone else looks in the cache
337 * before they remove it, the page will have a nonzero ref
338 * once they finally lock(np).
341 if(np->ref != 0) /* should never happen */
342 panic("duppage: np->ref %d != 0", np->ref);
345 /* Cache the new version */
348 np->daddr = p->daddr;
350 cachepage(np, p->image);
356 copypage(Page *f, Page *t)
362 memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
368 uncachepage(Page *p) /* Always called with a locked page */
375 lock(&palloc.hashlock);
376 l = &pghash(p->daddr);
377 for(f = *l; f; f = f->hash) {
384 unlock(&palloc.hashlock);
391 cachepage(Page *p, Image *i)
395 /* If this ever happens it should be fixed by calling
396 * uncachepage instead of panic. I think there is a race
397 * with pio in which this can happen. Calling uncachepage is
398 * correct - I just wanted to see if we got here.
404 lock(&palloc.hashlock);
406 l = &pghash(p->daddr);
409 unlock(&palloc.hashlock);
413 cachedel(Image *i, ulong daddr)
417 lock(&palloc.hashlock);
419 for(f = *l; f; f = f->hash) {
420 if(f->image == i && f->daddr == daddr) {
422 if(f->image == i && f->daddr == daddr){
433 unlock(&palloc.hashlock);
437 lookpage(Image *i, ulong daddr)
441 lock(&palloc.hashlock);
442 for(f = pghash(daddr); f; f = f->hash) {
443 if(f->image == i && f->daddr == daddr) {
444 unlock(&palloc.hashlock);
448 if(f->image != i || f->daddr != daddr) {
461 unlock(&palloc.hashlock);
473 dst = &new->pages[old->first-old->pages];
475 for(src = old->first; src <= old->last; src++, dst++)
496 new = smalloc(sizeof(Pte));
497 new->first = &new->pages[PTEPERTAB];
498 new->last = new->pages;
503 freepte(Segment *s, Pte *p)
507 Page *pt, **pg, **ptop;
509 switch(s->type&SG_TYPE) {
511 fn = s->pseg->pgfree;
512 ptop = &p->pages[PTEPERTAB];
514 for(pg = p->pages; pg < ptop; pg++) {
522 for(pg = p->pages; pg < ptop; pg++) {
534 for(pg = p->first; pg <= p->last; pg++)
546 return p-palloc.pages;
557 ref = malloc(np*sizeof ref[0]);
559 print("checkpagerefs: out of memory\n");
564 * This may not be exact if there are other processes
565 * holding refs to pages on their stacks. The hope is
566 * that if you run it on a quiescent system it will still
571 countpagerefs(ref, 0);
572 portcountpagerefs(ref, 0);
575 if(palloc.pages[i].ref != ref[i]){
576 iprint("page %#.8lux ref %d actual %lud\n",
577 palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
583 countpagerefs(ref, 1);
584 portcountpagerefs(ref, 1);
585 iprint("%lud mistakes found\n", nwrong);
591 portcountpagerefs(ulong *ref, int print)
593 ulong i, j, k, ns, n;
600 * Pages in segments. s->mark avoids double-counting.
604 for(i=0; i<conf.nproc; i++){
606 for(j=0; j<NSEG; j++){
612 for(i=0; i<conf.nproc; i++){
614 for(j=0; j<NSEG; j++){
616 if(s == nil || s->mark++)
619 for(k=0; k<s->mapsize; k++){
623 for(pg = pte->first; pg <= pte->last; pg++){
628 if(ref[pagenumber(entry)])
629 iprint("page %#.8lux in segment %#p\n", entry->pa, s);
632 if(ref[pagenumber(entry)]++ == 0)
639 iprint("%lud pages in %lud segments\n", n, ns);
640 for(i=0; i<conf.nproc; i++){
642 for(j=0; j<NSEG; j++){
646 if(s->ref != s->mark){
647 iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
648 s, i, p->pid, s->ref, s->mark);