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)
126 int i, hw, dontalloc, color;
129 color = getpgcolor(va);
130 hw = swapalloc.highwater;
132 if(palloc.freecount > hw)
134 if(up->kp && palloc.freecount > 0)
140 qunlock(&((*s)->lk));
144 qlock(&palloc.pwait); /* Hold memory requesters here */
146 while(waserror()) /* Ignore interrupts */
150 tsleep(&palloc.r, ispages, 0, 1000);
154 qunlock(&palloc.pwait);
157 * If called from fault and we lost the segment from
158 * underneath don't waste time allocating and freeing
159 * a page. Fault will call newpage again when it has
160 * reacquired the segment locks
168 /* First try for our colour */
169 for(p = palloc.head; p; p = p->next)
170 if(p->color == color)
184 panic("newpage: p->ref %d != 0", p->ref);
190 for(i = 0; i < MAXMACH; i++)
197 memset((void*)VA(k), 0, BY2PG);
207 return palloc.freecount >= swapalloc.highwater;
230 if(p->image && p->image != &swapimage)
249 if(palloc.freecount < swapalloc.highwater) {
266 static int dupretries = 15000;
269 duppage(Page *p) /* Always call with p locked */
278 if(retries++ > dupretries){
279 print("duppage %d, up %p\n", retries, up);
281 if(dupretries > 100000)
288 /* don't dup pages with no image */
289 if(p->ref == 0 || p->image == nil || p->image->notext)
293 * normal lock ordering is to call
294 * lock(&palloc) before lock(p).
295 * To avoid deadlock, we have to drop
296 * our locks and try again.
298 if(!canlock(&palloc)){
306 /* No freelist cache when memory is very low */
307 if(palloc.freecount < swapalloc.highwater) {
313 color = getpgcolor(p->va);
314 for(np = palloc.head; np; np = np->next)
315 if(np->color == color)
318 /* No page of the correct color */
328 * XXX - here's a bug? - np is on the freelist but it's not really free.
329 * when we unlock palloc someone else can come in, decide to
330 * use np, and then try to lock it. they succeed after we've
331 * run copypage and cachepage and unlock(np). then what?
332 * they call pageunchain before locking(np), so it's removed
333 * from the freelist, but still in the cache because of
334 * cachepage below. if someone else looks in the cache
335 * before they remove it, the page will have a nonzero ref
336 * once they finally lock(np).
341 /* Cache the new version */
344 np->daddr = p->daddr;
346 cachepage(np, p->image);
354 copypage(Page *f, Page *t)
360 memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
366 uncachepage(Page *p) /* Always called with a locked page */
373 lock(&palloc.hashlock);
374 l = &pghash(p->daddr);
375 for(f = *l; f; f = f->hash) {
382 unlock(&palloc.hashlock);
389 cachepage(Page *p, Image *i)
393 /* If this ever happens it should be fixed by calling
394 * uncachepage instead of panic. I think there is a race
395 * with pio in which this can happen. Calling uncachepage is
396 * correct - I just wanted to see if we got here.
402 lock(&palloc.hashlock);
404 l = &pghash(p->daddr);
407 unlock(&palloc.hashlock);
411 cachedel(Image *i, ulong daddr)
415 lock(&palloc.hashlock);
417 for(f = *l; f; f = f->hash) {
418 if(f->image == i && f->daddr == daddr) {
420 if(f->image == i && f->daddr == daddr){
431 unlock(&palloc.hashlock);
435 lookpage(Image *i, ulong daddr)
439 lock(&palloc.hashlock);
440 for(f = pghash(daddr); f; f = f->hash) {
441 if(f->image == i && f->daddr == daddr) {
442 unlock(&palloc.hashlock);
446 if(f->image != i || f->daddr != daddr) {
459 unlock(&palloc.hashlock);
471 dst = &new->pages[old->first-old->pages];
473 for(src = old->first; src <= old->last; src++, dst++)
494 new = smalloc(sizeof(Pte));
495 new->first = &new->pages[PTEPERTAB];
496 new->last = new->pages;
501 freepte(Segment *s, Pte *p)
505 Page *pt, **pg, **ptop;
507 switch(s->type&SG_TYPE) {
509 fn = s->pseg->pgfree;
510 ptop = &p->pages[PTEPERTAB];
512 for(pg = p->pages; pg < ptop; pg++) {
520 for(pg = p->pages; pg < ptop; pg++) {
532 for(pg = p->first; pg <= p->last; pg++)
544 return p-palloc.pages;
555 ref = malloc(np*sizeof ref[0]);
557 print("checkpagerefs: out of memory\n");
562 * This may not be exact if there are other processes
563 * holding refs to pages on their stacks. The hope is
564 * that if you run it on a quiescent system it will still
569 countpagerefs(ref, 0);
570 portcountpagerefs(ref, 0);
573 if(palloc.pages[i].ref != ref[i]){
574 iprint("page %#.8lux ref %d actual %lud\n",
575 palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
581 countpagerefs(ref, 1);
582 portcountpagerefs(ref, 1);
583 iprint("%lud mistakes found\n", nwrong);
589 portcountpagerefs(ulong *ref, int print)
591 ulong i, j, k, ns, n;
598 * Pages in segments. s->mark avoids double-counting.
602 for(i=0; i<conf.nproc; i++){
604 for(j=0; j<NSEG; j++){
610 for(i=0; i<conf.nproc; i++){
612 for(j=0; j<NSEG; j++){
614 if(s == nil || s->mark++)
617 for(k=0; k<s->mapsize; k++){
621 for(pg = pte->first; pg <= pte->last; pg++){
626 if(ref[pagenumber(entry)])
627 iprint("page %#.8lux in segment %#p\n", entry->pa, s);
630 if(ref[pagenumber(entry)]++ == 0)
637 iprint("%lud pages in %lud segments\n", n, ns);
638 for(i=0; i<conf.nproc; i++){
640 for(j=0; j<NSEG; j++){
644 if(s->ref != s->mark){
645 iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
646 s, i, p->pid, s->ref, s->mark);