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;
39 if(cankaddr(p->pa) && (KADDR(p->pa) == nil || KADDR(p->pa) == (void*)-BY2PG))
42 color = (color+1)%NCOLOR;
48 palloc.user = p - palloc.pages;
49 u = palloc.user*BY2PG;
50 v = u + conf.nswap*BY2PG;
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 m += PGROUND(end - (char*)KTZERO);
62 print("%lldM memory: ", (m+1024*1024-1)/(1024*1024));
63 print("%lldM kernel data, ", (m-u+1024*1024-1)/(1024*1024));
64 print("%lldM user, ", u/(1024*1024));
65 print("%lldM swap\n", v/(1024*1024));
69 pagechainhead(Page *p)
71 p->next = palloc.head;
79 if(palloc.pwait[0].p != nil && wakeup(&palloc.pwait[0]) != nil)
81 if(palloc.pwait[1].p != nil)
82 wakeup(&palloc.pwait[1]);
86 freepages(Page *head, Page *tail, ulong np)
89 tail->next = palloc.head;
91 palloc.freecount += np;
97 pagereclaim(Image *i, ulong pages)
99 Page **h, **l, **x, *p;
115 for(h = i->pghash; h < &i->pghash[PGHSIZE]; h++){
118 for(p = *l; p != nil; p = p->next){
146 freepages(fh, ft, np);
154 return palloc.freecount > swapalloc.highwater || up->noswap && palloc.freecount > 0;
158 newpage(int clear, Segment **s, uintptr va)
165 while(!ispages(nil)){
173 q = &palloc.pwait[!up->noswap];
177 sleep(q, ispages, nil);
185 * If called from fault and we lost the segment from
186 * underneath don't waste time allocating and freeing
187 * a page. Fault will call newpage again when it has
188 * reacquired the segment locks
197 /* First try for our colour */
198 color = getpgcolor(va);
200 for(p = *l; p != nil; p = p->next){
201 if(p->color == color)
223 memset((void*)VA(k), 0, BY2PG);
237 if(p->image != nil) {
246 copypage(Page *f, Page *t)
252 memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
258 cachepage(Page *p, Image *i)
264 h = &PGHASH(i, p->daddr);
287 l = &PGHASH(i, p->daddr);
288 for(x = *l; x != nil; x = x->next) {
305 lookpage(Image *i, uintptr daddr)
310 l = h = &PGHASH(i, daddr);
311 for(p = *l; p != nil; p = p->next){
312 if(p->daddr == daddr){
328 cachedel(Image *i, uintptr daddr)
332 while((p = lookpage(i, daddr)) != nil){
346 dst = &new->pages[old->first-old->pages];
348 for(src = old->first; src <= old->last; src++, dst++)
366 new = smalloc(sizeof(Pte));
367 new->first = &new->pages[PTEPERTAB];
368 new->last = new->pages;
373 freepte(Segment *s, Pte *p)
380 switch(s->type&SG_TYPE) {
383 if(*pg != nil && decref(*pg) == 0)
401 return p-palloc.pages;
412 ref = malloc(np*sizeof ref[0]);
414 print("checkpagerefs: out of memory\n");
419 * This may not be exact if there are other processes
420 * holding refs to pages on their stacks. The hope is
421 * that if you run it on a quiescent system it will still
426 countpagerefs(ref, 0);
427 portcountpagerefs(ref, 0);
430 if(palloc.pages[i].ref != ref[i]){
431 iprint("page %#p ref %ld actual %lud\n",
432 palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
438 countpagerefs(ref, 1);
439 portcountpagerefs(ref, 1);
440 iprint("%lud mistakes found\n", nwrong);
446 portcountpagerefs(ulong *ref, int print)
448 ulong i, j, k, ns, n;
455 * Pages in segments. s->mark avoids double-counting.
459 for(i=0; i<conf.nproc; i++){
461 for(j=0; j<NSEG; j++){
467 for(i=0; i<conf.nproc; i++){
469 for(j=0; j<NSEG; j++){
471 if(s == nil || s->mark++)
473 if((s->type&SG_TYPE) == SG_PHYSICAL)
476 for(k=0; k<s->mapsize; k++){
480 for(pg = pte->first; pg <= pte->last; pg++){
485 if(ref[pagenumber(entry)])
486 iprint("page %#p in segment %#p\n", entry->pa, s);
489 if(ref[pagenumber(entry)]++ == 0)
496 iprint("%lud pages in %lud segments\n", n, ns);
497 for(i=0; i<conf.nproc; i++){
499 for(j=0; j<NSEG; j++){
503 if(s->ref != s->mark){
504 iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
505 s, i, p->pid, s->ref, s->mark);