⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ck_generation.cxx

📁 C++ 编写的EROS RTOS
💻 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 <disk/DiskNode.hxx>#include <disk/PagePot.hxx>#include <kerninc/kernel.hxx>#include <kerninc/MsgLog.hxx>#include <kerninc/Check.hxx>#include <kerninc/Checkpoint.hxx>#include <kerninc/Persist.hxx>voidCoreGeneration::Init(){  bzero(this, sizeof(*this));  oidTree = CkNIL;  nextNodeLid = UNDEF_LID;}/************************** *  Log frame management **************************/boolCoreGeneration::ReserveFrame(){  /* If we have reserved enough already that we are over the limit,   * don't let us reserve any more:   */  if (rsrv.nFrames - release.nFrames >= Checkpoint::ckGenLimit)    return false;    /* If no space is currently available in the log, declare a checkpoint. */  if ( Checkpoint::ReserveLogFrame() == false )    return false;  rsrv.nFrames++;  return true;}boolCoreGeneration::ReserveDirent(uint32_t count){  assert ( count < CkptDirPage::maxDirEnt ) ;  assert ( count <= EROS_OBJECTS_PER_FRAME ) ;    if ((rsrv.nDirent + count) > (rsrv.nDirFrame * CkptDirPage::maxDirEnt)) {    if (ReserveFrame() == false)      return false;    rsrv.nDirFrame++;  }      assert(rsrv.nPage + rsrv.nDirFrame + rsrv.nNodeFrame	 == rsrv.nFrames);   assert( (rsrv.nDirent + count)	  <= (rsrv.nDirFrame * CkptDirPage::maxDirEnt) );  rsrv.nDirent += count;  return true;}boolCoreGeneration::ReserveNode(uint32_t count){  assert ( count <= DISK_NODES_PER_PAGE ) ;  assert ( count <= EROS_OBJECTS_PER_FRAME ) ;    if ((rsrv.nNode + count) > rsrv.nNodeFrame * DISK_NODES_PER_PAGE) {    if (ReserveFrame() == false)      return false;    rsrv.nNodeFrame++;  }      assert(rsrv.nPage + rsrv.nDirFrame + rsrv.nNodeFrame	 == rsrv.nFrames);   assert( (rsrv.nNode + count)	  <= (rsrv.nNodeFrame * DISK_NODES_PER_PAGE) );  rsrv.nNode += count;  return true;}bool CoreGeneration::ReserveDataPage(){  if (ReserveFrame()) {    rsrv.nPage++;    return true;  }  return false;}voidCoreGeneration::UnreserveFrame(){  Checkpoint::nReservedLogFrame--;  rsrv.nFrames--;}voidCoreGeneration::UnreservePage(){  UnreserveFrame();  rsrv.nPage--;}void CoreGeneration::UnreserveNode(){  rsrv.nNode--;    if (rsrv.nNode == (rsrv.nNodeFrame - 1) * DISK_NODES_PER_PAGE) {    UnreserveFrame();    rsrv.nNodeFrame--;  }}void CoreGeneration::UnreserveDirent(){  rsrv.nDirent--;    if (rsrv.nDirent == (rsrv.nDirFrame - 1) * CkptDirPage::maxDirEnt) {    UnreserveFrame();    rsrv.nDirFrame--;  }}lid_tCoreGeneration::AllocateLid(lid_t ll){  assert (rsrv.nFrames > alloc.nFrames);  if (ll == UNDEF_LID) {    ll = Checkpoint::FindFreeFrame();    assert (Checkpoint::FrameIsEmpty(ll));    alloc.nFrames++;  }  Checkpoint::AllocateLid(ll);    return ll;}boolCoreGeneration::DeallocateLid(lid_t ll){  if (Checkpoint::DeallocateLid(ll) == false)    return false;  release.nFrames++;  return true;}voidCoreGeneration::FinishActiveNodeFrame(){  if (nextNodeLid != UNDEF_LID) {    if (DeallocateLid(nextNodeLid))      release.nNodeFrame++;    nextNodeLid = UNDEF_LID;  }}/* Allocate storage for the object described by /CoreDirent/, if any * is needed.  Populate the CoreDirent with the resulting object * location. */voidCoreGeneration::Allocate(CoreDirent* cde){#ifndef NDEBUG  CheckConsistency(false);#endif  if (CONTENT_LID(cde->lid))	/* already allocated */    return;    switch(cde->type) {  case FRM_TYPE_NODE:    {      if (nextNodeLid == UNDEF_LID) {	/* This is the EXTRA allocation that will keep the frame from	 * being deallocated if all nodes in it are released before we 	 * are done with it.	 */	nextNodeLid = AllocateLid();	assert (nextNodeLid % EROS_OBJECTS_PER_FRAME == 0);	alloc.nNodeFrame++;	/* Zeroing the log frame is not necessary for correctness.	 * The purpose of doing so is to ensure that in most cases	 * fetching the frame will not entail a disk I/O operation.	 * The attempt to zero the page will occasionally cause the	 * ager to run, resulting in a yield.  In that event we will	 * re-enter WriteNodeToLog(), which will re-invoke this	 * routine.  We will conclude at that point that nextNodeLid	 * is not UNDEF_LID, proceed to stash the node in this frame,	 * and eat the extra I/O.	 */	Persist::ZeroCkFrame(nextNodeLid);      }      alloc.nNode++;            cde->lid = nextNodeLid;      nextNodeLid = AllocateLid(nextNodeLid);          nextNodeLid++;      if ((nextNodeLid % EROS_OBJECTS_PER_FRAME) == DISK_NODES_PER_PAGE) {	assertex ((void*)(this->index), (alloc.nNode % DISK_NODES_PER_PAGE) == 0);	FinishActiveNodeFrame();      }      break;    }      case FRM_TYPE_DPAGE:    {      alloc.nPage++;      cde->lid = AllocateLid();      /* We do not bother to zero this frame, as a complete page will       * be written.       */      break;    }  default:    /* Object is a zero object.  Allocate no storage for it. */    ;  }#ifndef NDEBUG  CheckConsistency(false);#endif}/* Release any allocated storage currently associated with this * object, but not the storage for the directory entry itself. */voidCoreGeneration::Release(CoreDirent* cde){#ifndef NDEBUG  CheckConsistency(false);#endif    assert(cde->lid != DEAD_LID);  if (!CONTENT_LID(cde->lid) && cde->lid != UNDEF_LID)    return;    switch(cde->type) {  case FRM_TYPE_NODE:    {      if (cde->lid == UNDEF_LID) {	UnreserveNode();      }      else {	release.nNode++;	if (DeallocateLid(cde->lid))	  release.nNodeFrame++;      }      break;    }      case FRM_TYPE_DPAGE:    {      if (cde->lid == UNDEF_LID) {	UnreservePage();      }      else {	release.nPage++;	DeallocateLid(cde->lid);      }      break;    }  default:    /* Object is a zero object.  There is no storage to release. */    assert(cde->lid == ZERO_LID);  }  cde->lid = DEAD_LID;	/* for paranoia's sake */#ifndef NDEBUG  CheckConsistency(false);#endif}boolCoreGeneration::ReclaimLogPage(){  if (canReclaim == false)    return false;  assert (alloc.nFrames == rsrv.nFrames);    if (alloc.nFrames == release.nFrames)    return false;  uint32_t curReleased = release.nFrames;    do {    if (oidTree != CkNIL) {      CoreDirent *cde = oidTree;      Release(cde);      RemoveFromOidMap(cde);      delete cde;    }  } while (release.nFrames == curReleased);  return true;}voidCoreGeneration::Reclaim(){  while (oidTree != CkNIL) {    CoreDirent *cde = oidTree;    Release(cde);    RemoveFromOidMap(cde);    delete cde;  }}/* Check the consistency of the per-generation variables, including * verifying that the reserved and allocated counts match if appropriate. */boolCoreGeneration::CheckConsistency(bool allAllocated){  bool ckresult = true;    REQUIRE(rsrv.nPage + rsrv.nDirFrame + rsrv.nNodeFrame	  == rsrv.nFrames);   REQUIRE(rsrv.nNode <= rsrv.nNodeFrame * DISK_NODES_PER_PAGE);  REQUIRE(rsrv.nNode + DISK_NODES_PER_PAGE >	  rsrv.nNodeFrame * DISK_NODES_PER_PAGE);  REQUIRE(rsrv.nDirent <= rsrv.nDirFrame * CkptDirPage::maxDirEnt);  REQUIRE(rsrv.nDirent + CkptDirPage::maxDirEnt > 	  rsrv.nDirFrame * CkptDirPage::maxDirEnt);  REQUIRE(alloc.nPage + alloc.nNodeFrame <= alloc.nFrames);   REQUIRE(alloc.nNode <= alloc.nNodeFrame * DISK_NODES_PER_PAGE);  /* Following is tricky.  Due to the extra allocation on the active   * node frame in the checkpoint area, it's actually possible for all    * of the contained nodes to get deallocated long before the node frame   * gets deallocated.  This only occurs when lastNodeLid !=   * UNDEF_LID.   */  if (nextNodeLid == UNDEF_LID)    REQUIRE(alloc.nNode + DISK_NODES_PER_PAGE >	    alloc.nNodeFrame * DISK_NODES_PER_PAGE);  else    REQUIRE(alloc.nNode + 2*DISK_NODES_PER_PAGE >	    alloc.nNodeFrame * DISK_NODES_PER_PAGE);  REQUIRE(alloc.nCoreDirent <= rsrv.nDirent);  REQUIRE(alloc.nNode <= rsrv.nNode);  REQUIRE(alloc.nPage <= rsrv.nPage);  REQUIRE(alloc.nNodeFrame <= rsrv.nNodeFrame);  REQUIRE(alloc.nFrames <= rsrv.nFrames);  REQUIRE(release.nNode <= alloc.nNode);  REQUIRE(release.nPage <= alloc.nPage);  REQUIRE(release.nDirFrame <= alloc.nDirFrame);  REQUIRE(release.nNodeFrame <= alloc.nNodeFrame);  REQUIRE(release.nFrames <= alloc.nFrames);  if (canReclaim)    REQUIRE(release.nDirFrame == alloc.nDirFrame);  if (canReclaim || allAllocated) {    REQUIRE(alloc.nCoreDirent == rsrv.nDirent);    REQUIRE(alloc.nNode == rsrv.nNode);    REQUIRE(alloc.nPage == rsrv.nPage);    REQUIRE(alloc.nNodeFrame == rsrv.nNodeFrame);    REQUIRE(alloc.nFrames == rsrv.nFrames);    REQUIRE(alloc.nPage + alloc.nNodeFrame +	    alloc.nDirFrame == alloc.nFrames);   }    return ckresult;}#ifdef OPTION_DDBvoidCoreGeneration::ddb_showalloc(){  extern void db_printf(const char *fmt, ...);  db_printf("Ck%d: Rsrv nNode=    %6d nPage=    %6d\n",	    index,	    rsrv.nNode,	    rsrv.nPage);  db_printf("     Rsrv nDirFrame=%6d nNdFrame= %6d nFrames=  %6d\n",	    rsrv.nDirFrame,	    rsrv.nNodeFrame,	    rsrv.nFrames);  db_printf("     Rsrv nDirent=  %6d\n",	    rsrv.nDirent);  db_printf("     Aloc nNode=    %6d nPage=    %6d\n",	    alloc.nNode,	    alloc.nPage);  db_printf("     Aloc nDirFrame=%6d nNdFrame= %6d nFrames=  %6d\n",	    alloc.nDirFrame,	    alloc.nNodeFrame,	    alloc.nFrames);  db_printf("     Aloc nCrDirent=%6d\n",	    alloc.nCoreDirent);  db_printf("     Rels nNode=    %6d nPage=    %6d\n",	    release.nNode,	    release.nPage);  db_printf("     Rels nDirFrame=%6d nNdFrame= %6d nFrames=  %6d\n",	    release.nDirFrame,	    release.nNodeFrame,	    release.nFrames);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -