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

📄 ck_checkpoint.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1998, 1999, 2001, 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>#include <kerninc/ObjectCache.hxx>#include <kerninc/Thread.hxx>#include <kerninc/CpuReserve.hxx>#include <kerninc/Depend.hxx>#include <kerninc/BlockDev.hxx>#include <kerninc/Check.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Machine.hxx>#include <kerninc/IRQ.hxx>#include <kerninc/Console.hxx>#include <arch-kerninc/PTE.hxx>#define dbg_ckpt	0x1	/* steps in taking snapshot */#define dbg_ckage	0x2	/* migration state machine */#define dbg_mig		0x4	/* migration state machine */#define dbg_ckdir	0x8	/* steps in ckdir reconstruction */#define dbg_reservation	0x10	/* reservation logic */#define dbg_wrckdir	0x20	/* writing ckdir */#define dbg_dirent	0x40	/* dirent manipulation */#define dbg_stabilize	0x80	/* stabilization */#define dbg_mignode	0x100	/* actual object migration */#define dbg_migpage	0x200	/* actual object migration */#define dbg_migfinish	0x400	/* actual object migration *//* Following should be an OR of some of the above */#define dbg_flags   ( dbg_migfinish | 0u )#define DBCOND(x) (dbg_##x & dbg_flags)#define DEBUG(x) if DBCOND(x)#define DEBUG2(x,y) if ((dbg_##x|dbg_##y) & dbg_flags)bool 		 Checkpoint::enabled = false;CoreGeneration   Checkpoint::coreGeneration[nGeneration];DiskCheckpoint  *Checkpoint::lastCkptHdr = 0;ObjectHeader    *Checkpoint::lastCkptObHdr = 0;lid_t            Checkpoint::lastCkptHdrLid = 0;DiskCheckpoint  *Checkpoint::nextCkptHdr = 0;ObjectHeader    *Checkpoint::nextCkptObHdr = 0;lid_t            Checkpoint::nextCkptHdrLid = 0;ObjectHeader    *Checkpoint::diskDirPageHdr = 0;ObjectHeader    *Checkpoint::threadDirHdr[nThreadDirPage];ThreadDirPage   *Checkpoint::threadDirPg[nThreadDirPage];lid_t            Checkpoint::lastThreadDirLid[nThreadDirPage];lid_t            Checkpoint::nextThreadDirLid[nThreadDirPage];ObjectHeader    *Checkpoint::reserveDirHdr[nReserveDirPage];ReserveDirPage  *Checkpoint::reserveDirPg[nReserveDirPage];lid_t            Checkpoint::lastReserveDirLid[nReserveDirPage];lid_t            Checkpoint::nextReserveDirLid[nReserveDirPage];ObjectHeader    *Checkpoint::nextDirPageHdr;CkptDirPage     *Checkpoint::nextDirPage;AllocMap         Checkpoint::allocMap;logframe_t       Checkpoint::LastAllocatedFrame = 0;uint32_t         Checkpoint::totLogFrame = 0;uint32_t         Checkpoint::nAvailLogFrame = 0;uint32_t         Checkpoint::nReservedLogFrame = 0;uint32_t         Checkpoint::nAllocatedLogFrame = 0;uint32_t         Checkpoint::nMasterPage = 0;Checkpoint::MigrationStatus                 Checkpoint::migrationStatus;uint32_t         Checkpoint::nCheckpointsCompleted = 0;uint32_t         Checkpoint::ckGenLimit;voidCheckpoint::SwapCheckpointHeaders(){  ObjectHeader *oldLastCkptObHdr = lastCkptObHdr;  DiskCheckpoint *oldLastCkptHdr = lastCkptHdr;  lid_t oldLastCkptHdrLid = lastCkptHdrLid;    lastCkptObHdr = nextCkptObHdr;  lastCkptHdr = nextCkptHdr;  lastCkptHdrLid = nextCkptHdrLid;    nextCkptObHdr = oldLastCkptObHdr;  nextCkptHdr = oldLastCkptHdr;  nextCkptHdrLid = oldLastCkptHdrLid;}voidCheckpoint::SwapThreadDirs(){  for (uint32_t i = 0; i < nThreadDirPage; i++) {    lid_t oldLid = lastThreadDirLid[i];    lastThreadDirLid[i] = nextThreadDirLid[i];    nextThreadDirLid[i] = oldLid;  }    for (uint32_t i = 0; i < nReserveDirPage; i++) {    lid_t oldLid = lastReserveDirLid[i];    lastReserveDirLid[i] = nextReserveDirLid[i];    nextReserveDirLid[i] = oldLid;  }}/* Unpreparing the dirty nodes will have the effect of flushing all of * the context caches. */voidCheckpoint::MarkDirtyNodesForCkpt(){  for (uint32_t nd = 0; nd < ObjectCache::TotalNodes(); nd++) {    Node *pNode = ObjectCache::GetCoreNodeFrame(nd);    if (pNode->IsDirty()) {      assert (pNode->GetFlags(OFLG_CKPT) == false);      for (unsigned i = 0; i < EROS_NODE_SIZE; i++)	if (pNode->slot[i].IsRdHazard())	  pNode->ClearHazard(i);      pNode->SetFlags(OFLG_CKPT);    }  }}/* Mark dirty pages for COW and ckpt, and disable write permissions on * all outstanding PTE's to such pages. */voidCheckpoint::MarkDirtyPagesForCkpt(){#ifdef OPTION_SMALL_SPACES  Process::WriteDisableSmallSpaces();#endif    for (uint32_t pg = 0; pg < ObjectCache::TotalPages(); pg++) {    ObjectHeader *pObj = ObjectCache::GetCorePageFrame(pg);    switch(pObj->obType) {    case ObType::PtDataPage:      if (pObj->GetFlags(OFLG_REDIRTY) && !pObj->GetFlags(OFLG_DIRTY))	MsgLog::dprintf(true, "Checkpointing redirtied page!!\n");            if (pObj->IsDirty()) {	assert (pObj->GetFlags(OFLG_CKPT) == 0);	pObj->SetFlags(OFLG_CKPT);      }      break;#ifdef USES_MAPPING_PAGES    case ObType::PtMappingPage:      Depend_WriteDisableProduct(pObj);      break;#endif    }  }#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("After marking pgs for ckpt");#endif}/* Initialize all fields of the soon-to-be-written checkpoint header * that we can.  We will update nDirPage, nThreadPage, and maxLogLoc * as we construct and write out the various directories. */  voidCheckpoint::InitNextCkptHdr(){  nextCkptHdr->nThreadPage = 0;  nextCkptHdr->nRsrvPage = 0;  nextCkptHdr->nDirPage = 0;  nextCkptHdr->hasMigrated = false;  nextCkptHdr->sequenceNumber = lastCkptHdr->sequenceNumber + 1;  nextCkptHdr->maxLogLid = 2 * EROS_OBJECTS_PER_FRAME;  nextCkptObHdr->SetDirtyFlag();}voidCheckpoint::SnapshotReserves(){  uint32_t r = 0;  coreGeneration[current].nReserve = 0;  while (r < MAX_CPU_RESERVE) {    ReserveDirPage* rdp = reserveDirPg[r / ReserveDirPage::maxDirEnt];    reserveDirHdr[r / ReserveDirPage::maxDirEnt]->SetDirtyFlag();    uint32_t count = 0;    for (; count < ReserveDirPage::maxDirEnt && r < MAX_CPU_RESERVE;	 count++, r++) {      CpuReserve& rsrv = CpuReserve::CpuReserveTable[r];            CpuReserveInfo& ckrsrv = rdp->entry[count];      ckrsrv.index = r;      ckrsrv.quanta = rsrv.quanta;      ckrsrv.duration = rsrv.duration;      ckrsrv.period = rsrv.period;      ckrsrv.start = rsrv.start;      ckrsrv.normPrio = rsrv.normPrio;      ckrsrv.rsrvPrio = rsrv.rsrvPrio;      coreGeneration[current].nReserve++;    }    rdp->nDirent = count;    assert(nextReserveDirLid[nextCkptHdr->nRsrvPage]);    nextCkptHdr->dirPage[nextCkptHdr->nRsrvPage] =      nextReserveDirLid[nextCkptHdr->nRsrvPage];    nextCkptHdr->nRsrvPage++;  }}voidCheckpoint::SnapshotThreads(){  uint32_t t = 0;  coreGeneration[current].nThread = 0;  while (t < KTUNE_NTHREAD) {    ThreadDirPage* tdp = threadDirPg[t / ThreadDirPage::maxDirEnt];    threadDirHdr[t / ThreadDirPage::maxDirEnt]->SetDirtyFlag();    uint32_t count = 0;          for (; count < ThreadDirPage::maxDirEnt && t < KTUNE_NTHREAD;	 t++) {      Thread& thrd = Thread::ThreadTable[t];            thrd.pageWriteCount = 0;      if (thrd.state == Thread::Free)	continue;      if (thrd.state != Thread::Free &&	  thrd.processKey.IsObjectKey() == false) {	/* This thread contained a key which was rescinded.  It has	 * been scheduled to run, and will die at that time.  Do not	 * bother to copy it.	 */	assert (thrd.state == Thread::Ready);	assert (thrd.processKey.IsVoidKey());#if 0	MsgLog::dprintf(true, "Non-free thread 0x%08x with non-object key!\n",			&thrd);#endif	continue;      }      #if 0      /* Now that we are allowing mapping tables to persist in       * read-only form, the thread no longer gets deprepared.       */            /* Thread must be in deprepared form: */      assert (thrd.context == 0);#endif#if 0      /* Can the embodied domain key be prepared? -- I think probably so. */      assert (thrd.domainKey.IsPrepared() == false);#endif            tdp->entry[count].oid = thrd.processKey.GetKeyOid();      tdp->entry[count].allocCount = thrd.processKey.GetAllocCount();      tdp->entry[count].schedNdx =	thrd.cpuReserve - CpuReserve::CpuReserveTable;       coreGeneration[current].nThread++;      count++;      DEBUG(ckdir)	MsgLog::dprintf(false, "Add snap thrd 0x%08x%08x ac=0x%08x\n",			(uint32_t) (tdp->entry[count].oid >> 32),			(uint32_t) tdp->entry[count].oid,			tdp->entry[count].allocCount);    }    tdp->nDirent = count;    assert(nextThreadDirLid[nextCkptHdr->nThreadPage]);    nextCkptHdr->dirPage[nextCkptHdr->nThreadPage + nextCkptHdr->nRsrvPage] =      nextThreadDirLid[nextCkptHdr->nThreadPage];    nextCkptHdr->nThreadPage++;  }}voidCheckpoint::AgeGenerations(){  DEBUG(ckage) MsgLog::dprintf(true, "Enter AgeGenerations\n");  /* First, forget the oldest generation present. */  CoreGeneration *cg = &coreGeneration[nGeneration-1];  assert (cg->canReclaim);    DEBUG(ckage) MsgLog::dprintf(true, "Removing object entries\n");  cg->Reclaim();  assert(cg->alloc.nFrames == cg->rsrv.nFrames);  assert(cg->rsrv.nDirent == cg->alloc.nCoreDirent);    for (int g = last_ckpt; g < nGeneration; g++)    coreGeneration[g].CheckConsistency(true);  DEBUG(ckage) MsgLog::dprintf(true, "Shift Generations\n");  /* Next, age everything remaining one generation. */  for (int g = nGeneration - 2; g >= 0; g--) {    bcopy(&coreGeneration[g], &coreGeneration[g+1], sizeof(CoreGeneration));    coreGeneration[g+1].index = g+1;  }  coreGeneration[current].Init();  DEBUG(ckage) MsgLog::dprintf(true, "Exit AgeGenerations\n");}voidCheckpoint::TakeCheckpoint(){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top TakeCheckpoint()");#endif  if (migrationStatus != mg_Idle) {    ProcessMigration();    Thread::Current()->Yield();  }    MsgLog::dprintf(false,"!");    DEBUG(ckpt) MsgLog::dprintf(true, "Enter TakeCheckpoint()\n");  MsgLog::dprintf(true, "Checkpoint is declared\n");  MarkDirtyNodesForCkpt();  MarkDirtyPagesForCkpt();  DEBUG(ckpt) MsgLog::dprintf(true, "Everything is now marked for checkpoint\n");  /* Ensure that all the invalidated PTE's stay that way: */  Machine::FlushTLB();  DEBUG(ckpt) MsgLog::dprintf(true, "TLB is flushed\n");  InitNextCkptHdr();  DEBUG(ckpt) MsgLog::dprintf(true, "Next ckpt hdr valid\n");  SnapshotReserves();  DEBUG(ckpt) MsgLog::dprintf(true, "Rsrvs are snapshotted\n");  SnapshotThreads();  DEBUG(ckpt) MsgLog::dprintf(true, "Threads are snapshotted\n");  AgeGenerations();  DEBUG(ckpt) MsgLog::dprintf(true, "Generations have been aged\n");#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Bottom TakeCheckpoint()");#endif  DEBUG2(ckpt,migfinish) {	MsgLog::dprintf(false, "About to start migration()\n");        /* Check::Pages(); */  }  StartMigration(true);  /* Must yield, since current thread has been deprepared by the fact   * of having taken a checkpoint!   */  Thread::Current()->Yield();}/* Variables associated with stabilization and migration: */static uint32_t mg_nextCorePage;static uint32_t mg_nextCoreNode;static CoreDirent *mg_nextDirent;static uint32_t mg_nextThreadDirPg;static uint32_t mg_nextReserveDirPg;static OID mg_objectPotOID;static OID mg_tagPotOID;#ifndef NDEBUGstatic bool  mg_SanityChecked;#endifconst char *Checkpoint::MigStateName(){  static char *names[Checkpoint::mg_nState] = {    "Idle",    "StartCheckpoint",    "StabilizeNodes",    "StabilizePages",    "WriteDir",    "DrainCkpt",    "WriteHeader",    "StartMigration",    "MigrateObjects",    "DrainMigration",    "UpdateRangeHeaders",  };  return names[migrationStatus];}			  charCheckpoint::MigStateAbbrev(){  static char letters[Checkpoint::mg_nState] = {    ' ',			/* idle shows blank */    'C',			/* start checkpoitn */    'N',			/* stabilize nodes */    'P',			/* stabilize pages */    'D',			/* writing directory */    'W',			/* drain wait */    'H',			/* write header */    'm',			/* start migration */    'o',			/* migrate objects */    'w',			/* migrate drain wait */    'r',			/* update range headers */  };  return letters[migrationStatus];}

⌨️ 快捷键说明

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