/* allocate identity-mapped frame */ void * pagevalloc(void) { struct physpage *page; page = queuepop(&vmshmqueue); if (page) { return (void *)page->adr; } return NULL; }
/* allocate buffer entry */ struct bufblk * bufalloc(void) { struct bufblk *blk = NULL; mtxlk(&buffreelist.lk); blk = queuepop(&buffreelist.head); mtxunlk(&buffreelist.lk); if (!blk) { blk = bufevict(); } return blk; }
long taskgetid(void) { struct taskid *queue = &taskidqueue; struct taskid *taskid; long retval = -1; mtxlk(&queue->lk); taskid = queuepop(&queue); if (taskid) { retval = taskid->id; } mtxunlk(&taskid->lk); return retval; }
/* * TODO: evict pages from LRU if none free / low water */ struct physpage * pageallocphys(void) { struct physpage *page = NULL; struct physpage **queue; long found = 0; long qid; long q; mtxlk(&vmphyslk); page = queuepop(&vmphysqueue); mtxunlk(&vmphyslk); if (!page) { do { for (q = 0 ; q < LONGSIZE * CHAR_BIT ; q++) { mtxlk(&vmlrutab[q].lk); queue = &vmlrutab[q].list; page = queuegetlast(queue); if (page) { found++; page->nflt++; qid = pagecalcqid(page); if (qid != q) { mtxlk(&vmlrutab[q].lk); } queue = &vmlrutab[qid].list; queuepush(page, queue); if (qid != q) { mtxunlk(&vmlrutab[qid].lk); } break; } mtxunlk(&vmlrutab[q].lk); } if (found) { break; } } while (!found); } return page; }
/* evict buffer; write back to disk */ struct bufblk * bufevict(void) { struct bufblk *blk = NULL; do { mtxlk(&buflruqueue.lk); blk = queuepop(&buflruqueue.head); mtxunlk(&buflruqueue.lk); if (!blk) { /* TODO: wait for queuepop(&buflruqueue.head) */ } else { if (blk->flg & BUFDIRTY) { bufwrite(blk); } bufclr(blk); } } while (!blk); return blk; }