/* * called with s->lk locked */ void mfreeseg(Segment *s, ulong start, int pages) { int i, j, size; ulong soff; Page *pg; Page *list; soff = start-s->base; j = (soff&(PTEMAPMEM-1))/BY2PG; size = s->mapsize; list = nil; for(i = soff/PTEMAPMEM; i < size; i++) { if(pages <= 0) break; if(s->map[i] == 0) { pages -= PTEPERTAB-j; j = 0; continue; } while(j < PTEPERTAB) { pg = s->map[i]->pages[j]; /* * We want to zero s->map[i]->page[j] and putpage(pg), * but we have to make sure other processors flush the * entry from their TLBs before the page is freed. * We construct a list of the pages to be freed, zero * the entries, then (below) call procflushseg, and call * putpage on the whole list. * * Swapped-out pages don't appear in TLBs, so it's okay * to putswap those pages before procflushseg. */ if(pg){ if(onswap(pg)) putswap(pg); else{ pg->next = list; list = pg; } s->map[i]->pages[j] = 0; } if(--pages == 0) goto out; j++; } j = 0; } out: /* flush this seg in all other processes */ if(s->ref > 1) procflushseg(s); /* free the pages */ for(pg = list; pg != nil; pg = list){ list = list->next; putpage(pg); } }
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); }