void putpage(Page *p) { if(onswap(p)) { putswap(p); return; } lock(&palloc); lock(p); if(p->ref == 0) panic("putpage"); if(--p->ref > 0) { unlock(p); unlock(&palloc); return; } if(p->image && p->image != &swapimage) pagechaintail(p); else pagechainhead(p); if(palloc.r.p != 0) wakeup(&palloc.r); unlock(p); unlock(&palloc); }
void putpage(Page *p) { Pgsza *pa; int rlse; lock(&pga.l); lock(&p->l); if(p->ref == 0) panic("putpage"); if(--p->ref > 0) { unlock(&p->l); unlock(&pga.l); return; } rlse = 0; if(p->image != nil) pagechaintail(p); else{ /* * Free pages if we have plenty in the free list. */ pa = &pga.pgsza[p->pgszi]; if(pa->freecount > Nfreepgs) rlse = 1; else pagechainhead(p); } if(pga.rend.l.p != nil) wakeup(&pga.rend); unlock(&p->l); if(rlse) pgfree(p); unlock(&pga.l); }
int duppage(Page *p) /* Always call with p locked */ { Proc *up = externup(); Pgsza *pa; Page *np; int color; int retries; retries = 0; retry: if(retries++ > dupretries){ print("duppage %d, up %#p\n", retries, up); dupretries += 100; if(dupretries > 100000) panic("duppage\n"); uncachepage(p); return 1; } /* don't dup pages with no image */ if(p->ref == 0 || p->image == nil || p->image->notext) return 0; /* * normal lock ordering is to call * lock(&pga.l) before lock(&p->l). * To avoid deadlock, we have to drop * our locks and try again. */ if(!canlock(&pga.l)){ unlock(&p->l); if(up) sched(); lock(&p->l); goto retry; } pa = &pga.pgsza[p->pgszi]; /* No freelist cache when memory is very low */ if(pa->freecount < Nminfree){ unlock(&pga.l); uncachepage(p); return 1; } color = p->color; for(np = pa->head; np; np = np->next) if(np->color == color) break; /* No page of the correct color */ if(np == 0){ unlock(&pga.l); uncachepage(p); return 1; } pageunchain(np); pagechaintail(np); /* * XXX - here's a bug? - np is on the freelist but it's not really free. * when we unlock palloc someone else can come in, decide to * use np, and then try to lock it. they succeed after we've * run copypage and cachepage and unlock(np). then what? * they call pageunchain before locking(np), so it's removed * from the freelist, but still in the cache because of * cachepage below. if someone else looks in the cache * before they remove it, the page will have a nonzero ref * once they finally lock(np). * * What I know is that not doing the pagechaintail, but * doing it at the end, to prevent the race, leads to a * deadlock, even following the pga, pg lock ordering. -nemo */ lock(&np->l); unlock(&pga.l); /* Cache the new version */ uncachepage(np); np->va = p->va; np->daddr = p->daddr; copypage(p, np); cachepage(np, p->image); unlock(&np->l); uncachepage(p); return 0; }
int duppage(Page *p) /* Always call with p locked */ { Page *np; int color; int retries; retries = 0; retry: if(retries++ > dupretries){ print("duppage %d, up %p\n", retries, up); dupretries += 100; if(dupretries > 100000) panic("duppage\n"); uncachepage(p); return 1; } /* don't dup pages with no image */ if(p->ref == 0 || p->image == nil || p->image->notext) return 0; /* * normal lock ordering is to call * lock(&palloc) before lock(p). * To avoid deadlock, we have to drop * our locks and try again. */ if(!canlock(&palloc)){ unlock(p); if(up) sched(); lock(p); goto retry; } /* No freelist cache when memory is very low */ if(palloc.freecount < swapalloc.highwater) { unlock(&palloc); uncachepage(p); return 1; } color = getpgcolor(p->va); for(np = palloc.head; np; np = np->next) if(np->color == color) break; /* No page of the correct color */ if(np == 0) { unlock(&palloc); uncachepage(p); return 1; } pageunchain(np); pagechaintail(np); /* * XXX - here's a bug? - np is on the freelist but it's not really free. * when we unlock palloc someone else can come in, decide to * use np, and then try to lock it. they succeed after we've * run copypage and cachepage and unlock(np). then what? * they call pageunchain before locking(np), so it's removed * from the freelist, but still in the cache because of * cachepage below. if someone else looks in the cache * before they remove it, the page will have a nonzero ref * once they finally lock(np). */ lock(np); unlock(&palloc); /* Cache the new version */ uncachepage(np); np->va = p->va; np->daddr = p->daddr; copypage(p, np); cachepage(np, p->image); unlock(np); uncachepage(p); return 0; }