2 #include "../port/lib.h"
6 #include "../port/error.h"
18 if(palloc.pages == nil){
22 for(i=0; i<nelem(palloc.mem); i++){
26 palloc.pages = xalloc(np*sizeof(Page));
27 if(palloc.pages == nil)
34 for(i=0; i<nelem(palloc.mem); i++){
36 for(j=0; j<pm->npage; j++){
37 memset(p, 0, sizeof *p);
38 p->pa = pm->base+j*BY2PG;
40 color = (color+1)%NCOLOR;
46 palloc.user = p - palloc.pages;
47 u = palloc.user*BY2PG;
48 v = u + conf.nswap*BY2PG;
51 swapalloc.highwater = (palloc.user*5)/100;
52 swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
55 for(i=0; i<nelem(conf.mem); i++)
57 m += conf.mem[i].npage*BY2PG;
58 m += PGROUND(end - (char*)KTZERO);
60 print("%lldM memory: ", (m+1024*1024-1)/(1024*1024));
61 print("%lldM kernel data, ", (m-u+1024*1024-1)/(1024*1024));
62 print("%lldM user, ", u/(1024*1024));
63 print("%lldM swap\n", v/(1024*1024));
67 pagechainhead(Page *p)
69 p->next = palloc.head;
75 freepages(Page *head, Page *tail, int n)
78 tail->next = palloc.head;
80 palloc.freecount += n;
83 if(palloc.pwait[0].p != nil && wakeup(&palloc.pwait[0]) != nil)
85 if(palloc.pwait[1].p != nil)
86 wakeup(&palloc.pwait[1]);
90 pagereclaim(Image *i, int min)
92 Page **h, **l, **x, *p;
105 for(h = i->pghash; h < &i->pghash[PGHSIZE]; h++){
108 for(p = *l; p != nil; p = p->next){
136 freepages(fh, ft, n);
144 return palloc.freecount > swapalloc.highwater || up->noswap && palloc.freecount > 0;
148 newpage(int clear, Segment **s, uintptr va)
155 while(!ispages(nil)){
163 q = &palloc.pwait[!up->noswap];
167 sleep(q, ispages, nil);
175 * If called from fault and we lost the segment from
176 * underneath don't waste time allocating and freeing
177 * a page. Fault will call newpage again when it has
178 * reacquired the segment locks
187 /* First try for our colour */
188 color = getpgcolor(va);
190 for(p = *l; p != nil; p = p->next){
191 if(p->color == color)
213 memset((void*)VA(k), 0, BY2PG);
227 if(p->image != nil) {
236 copypage(Page *f, Page *t)
242 memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
248 cachepage(Page *p, Image *i)
254 h = &PGHASH(i, p->daddr);
277 l = &PGHASH(i, p->daddr);
278 for(x = *l; x != nil; x = x->next) {
295 lookpage(Image *i, uintptr daddr)
300 l = h = &PGHASH(i, daddr);
301 for(p = *l; p != nil; p = p->next){
302 if(p->daddr == daddr){
318 cachedel(Image *i, uintptr daddr)
322 while((p = lookpage(i, daddr)) != nil){
336 dst = &new->pages[old->first-old->pages];
338 for(src = old->first; src <= old->last; src++, dst++)
356 new = smalloc(sizeof(Pte));
357 new->first = &new->pages[PTEPERTAB];
358 new->last = new->pages;
363 freepte(Segment *s, Pte *p)
370 switch(s->type&SG_TYPE) {
373 if(*pg != nil && decref(*pg) == 0)
391 return p-palloc.pages;
402 ref = malloc(np*sizeof ref[0]);
404 print("checkpagerefs: out of memory\n");
409 * This may not be exact if there are other processes
410 * holding refs to pages on their stacks. The hope is
411 * that if you run it on a quiescent system it will still
416 countpagerefs(ref, 0);
417 portcountpagerefs(ref, 0);
420 if(palloc.pages[i].ref != ref[i]){
421 iprint("page %#p ref %ld actual %lud\n",
422 palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
428 countpagerefs(ref, 1);
429 portcountpagerefs(ref, 1);
430 iprint("%lud mistakes found\n", nwrong);
436 portcountpagerefs(ulong *ref, int print)
438 ulong i, j, k, ns, n;
445 * Pages in segments. s->mark avoids double-counting.
449 for(i=0; i<conf.nproc; i++){
451 for(j=0; j<NSEG; j++){
457 for(i=0; i<conf.nproc; i++){
459 for(j=0; j<NSEG; j++){
461 if(s == nil || s->mark++)
463 if((s->type&SG_TYPE) == SG_PHYSICAL)
466 for(k=0; k<s->mapsize; k++){
470 for(pg = pte->first; pg <= pte->last; pg++){
475 if(ref[pagenumber(entry)])
476 iprint("page %#p in segment %#p\n", entry->pa, s);
479 if(ref[pagenumber(entry)]++ == 0)
486 iprint("%lud pages in %lud segments\n", n, ns);
487 for(i=0; i<conf.nproc; i++){
489 for(j=0; j<NSEG; j++){
493 if(s->ref != s->mark){
494 iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
495 s, i, p->pid, s->ref, s->mark);