📄 swaparea.cxx
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "kernel.hxx"#include "CheckPoint.hxx"#include "kernel/DiskNode.hxx"#include "SwapArea.hxx"#include "CoreDivision.hxx"#include "UserMem.hxx"SwapArea::SwapArea(uint32_t idx){ divOne = 0; divTwo = 0; status = Available; availDirEnt = 0; availNodeEnt = 0; dirPageChain = 0; curDirEntNdx = 0; areaIndex = idx; nextLoc = 0; topLoc = 0; int i; for(i = 0; i < SWAP_DIR_HASH; i++) dirPtr[SWAP_DIR_HASH] = 0; for(i = 0; i < NUM_SLM_ROOT; i++) slmRoots[i] = 0;}intSwapArea::findSwapDivisions(){ uint32_t cd; if (!Persist::maxDiv()) return 0; if (divOne && divOne->availSwapFrames() == 0) divOne = 0; if (divTwo && divTwo->availSwapFrames() == 0) divTwo = 0; if (!divOne) { /* find first swap division - want the largest one. */ divOne = Persist::getcd(0); for (cd = 0; cd < Persist::maxDiv(); cd++) { CoreDivision *cur = Persist::getcd(cd); if (cur->cdalo != areaIndex) continue; if (cur->availSwapFrames() > divOne->availSwapFrames()) divOne = cur; } /* best may be empty - time to checkpoint! */ if (!divOne || !divOne->availSwapFrames()) { divOne = 0; return 0; } divTwo = 0; /* new div1 means need new div2 */ } if (!divTwo) { /* find second swap division. Want the smallest one not on the * same device as the first one. */ /* First try the paranoid strategy: */ for (cd = 0; cd < Persist::maxDiv(); cd++) { CoreDivision* cur = Persist::getcd(cd); if (cur->cdalo != areaIndex) continue; if (cur->device != divOne->device && cur->availSwapFrames()) { if (!divTwo || cur->availSwapFrames() < divTwo->availSwapFrames()) divTwo = cur; } } } #ifndef PARANOID_SWAP_ONLY /* There may not be one. Time to try the duplex strategy */ if (!divTwo) { for (cd = 0; cd < Persist::maxDiv(); cd++) { CoreDivision* cur = Persist::getcd(cd); if (cur->cdalo != areaIndex) continue; if (cur->availSwapFrames()) { if (!divTwo || cur->availSwapFrames() < divTwo->availSwapFrames()) divTwo = cur; } } }#endif if (!divTwo) { int count = 0; /* We now need to decide whether the return value is should be * bad or good. If there is more than one swap division in * our generation, this is a bad search. */ for (cd = 0; cd < Persist::maxDiv(); cd++) { CoreDivision* cur = Persist::getcd(cd); if (cur->cdalo != areaIndex) continue; } if (count > 1) return 0; } return 1;}/* reset() - checkpoint of current area has completed. This area was * migration area. Reset it to make it the current area. */int SwapArea::canMutateNode(){ /* we can safely mutate a node if there is room in the current * node pot and there is room in the directory. */ if (!allocSwapDirent()) return 0; if (availNodeEnt == 0) { if (allocSwapFrame()) availNodeEnt = DISK_NODES_PER_PAGE; else return 0; } availNodeEnt--; return 1;}int SwapArea::canMutatePage(CDA cda){ /* we can safely mutate a page if there is room in the current * node pot and there is room in the directory. */ /* it is also okay if we have already mutated this page. In * this case we know because we already have a CDA->swaploc * mapping for it. */ if (findPage(cda)) return 1; if (!allocSwapDirent()) return 0; return allocSwapFrame();}int SwapArea::allocSwapFrame(){ if (!findSwapDivisions()) return 0; if (topLoc >= MAX_SWAPLOC) return 0; assert(divOne); /* make sure we have a place to put the mapping we build: */ uint32_t slmRootNdx = topLoc / NUM_SLM_ROOT; uint32_t slmChildNdx = topLoc % NUM_SLM_ROOT; if (!slmRoots[slmRootNdx]) { CoreObject *pgco = UserMem.grabPage(); if (!pgco) return 0; slmRoots[slmRootNdx] = (SwapLocMapping*) UserMem.CTEtoPage(pgco); } SwapLocMapping& slm = slmRoots[slmRootNdx][slmChildNdx]; slm.where[0].divNdx = divOne->divisionID; slm.where[0].divFrame = divOne->nextSwapFrame++; if (divTwo) { slm.where[1].divNdx = divTwo->divisionID; slm.where[1].divFrame = divTwo->nextSwapFrame++; } else { slm.where[1].divFrame = 0; /* invalid value */ } topLoc++; return 1;}int SwapArea::allocSwapDirent(){ /* if we need to grow the on-disk directory, try to do so: */ if (availDirEnt == 0) { if (allocSwapFrame()) availDirEnt = DIRENT_PER_PAGE; else return 0; } availDirEnt--; return 1;}#if 0/* doAlloc() - allocate a new swap page frame. */int SwapArea::doAlloc(int numDirent){ assert(numDirent < DIRENT_PER_PAGE); int pagesNeeded = 1; /* for the node pot or data page */ if (nDirEnt + newDirent > DIRENT_PER_PAGE) pagesNeeded ++; if (freePages < pagesNeeded) return 0; freePages -= pagesNeeded; nDirEnt += newDirent; if (nDirEnt > DIRENT_PER_PAGE) nDirEnt -= DIRENT_PER_PAGE; return 1;}int SwapArea::allocNodePot(){ return doAlloc(DISK_NODES_PER_PAGE);}int SwapArea::allocPage(){ return doAlloc(1);}void SwapArea::init(CoreDivision* coreDiv){ cd = coreDiv; totPages = cd->nPages; clear();}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -