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

📄 ck_retag.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>#include <kerninc/ObjectCache.hxx>#include <kerninc/Thread.hxx>#include <kerninc/CpuReserve.hxx>#include <kerninc/BlockDev.hxx>#include <kerninc/Check.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Machine.hxx>#include <eros/SysTraceKey.h>#include <arch-kerninc/PTE.hxx>#define dbg_retag	0x1	/* frame retag */#define dbg_frameinfo	0x2	/* frame info collection *//* Following should be an OR of some of the above */#define dbg_flags   ( 0u )#define DBCOND(x) (dbg_##x & dbg_flags)#define DEBUG(x) if DBCOND(x)#define DEBUGEX(x,y) if (((dbg_##x) & dbg_flags) && (y))/* This is a simplified version of the retag logic.  It is modestly * wasteful of CPU cycles, but considerably easier to understand than * the previous version. *  * Retag Strategy: *  * We must first bring in enough information to know the current frame  * type of the frame we are retagging.  If there is an object in * memory within the frame, or if there is a checkpoint directory * entry for some object in the frame in any generation, this is * sufficient to learn the frame type.  Otherwise we must bring in the  * tag pot associated with the frame. *  * We must then compute the largest allocation count (or in the case * of a node frame, the largest call count) presently associated with * this frame.  If the frame is a page or capability page, this can be * computed using the same information we used to get the frame type. * If it is a node frame, we must regrettably bring in all of the * member nodes, because the call count is not available from the tag * pot. *  * We now know all of the information needed to create the new objects  * associated with this frame.  We therefore reserve directory space * for all of the new objects. *  * We now blow away all of the in-core node pots and objects currently * associated with this frame.  We also RELEASE all current core * directory entries associated with this frame. *  * Finally, we create zero object directory entries for the new frame * type. */uint8_tCheckpoint::GetFrameInfo(FrameInfo& fi, PagePot *pagePot,			 ObCount& count, uint8_t newType){  CoreDirent *cde = CkNIL;    DEBUG(frameinfo)    MsgLog::dprintf(false, "Enter frameinfo. pgPot=0x%08x\n", pagePot);    /* If object has been modified, frame type is type associated with   * checkpoint directory entry of youngest matching generation.   * Otherwise frame type is as reported in the page pot.   */  for (uint8_t g = current; g < nGeneration; g++) {    cde = coreGeneration[g].FindFrame(fi.oid);    if (cde != CkNIL)      break;  }  count = 0;    uint8_t curType = pagePot->type[fi.tagEntry];  if (cde != CkNIL)    curType = cde->type;  DEBUG(frameinfo)    MsgLog::dprintf(false, "Current type is %d\n", cde->type);    /* Use the zero types here so that we can compare to the requested   * new type.   */  switch(curType) {  case FRM_TYPE_DPAGE:    curType = FRM_TYPE_ZDPAGE;    break;  case FRM_TYPE_NODE:    curType = FRM_TYPE_ZNODE;    break;  }    assert (curType != newType);    /* If the frame type is NODE, we might as well bring the objects in   * here.   */  if (curType == FRM_TYPE_ZNODE) {    for (uint32_t n = 0; n < DISK_NODES_PER_PAGE; n++) {      OID oid = fi.obFrameOid + n;      Node * pNode = Persist::GetNode(oid, 0, false);      assert(pNode);      pNode->TransLock();      if (pNode->callCount > count)	count = pNode->callCount;    }  }  else if (cde != CkNIL)	/* page or cap page in ckpt area */    count = cde->count;  else    count = pagePot->count[fi.tagEntry];  DEBUG(frameinfo)    MsgLog::dprintf(false, "Exit frameinfo. curType=%d\n",		    curType);   return curType;}/* If the in-core frames are associated with the last checkpoint, we * MUST write them to the disk, because the currently active * checkpoint might not complete, and we might subsequently need them * back. */voidCheckpoint::CleanCkptFrames(uint8_t curType, FrameInfo& fi){  ObType::Type ty = ObType::PtDataPage;    switch(curType) {  case FRM_TYPE_ZDPAGE:    {      ObjectHeader *pObj = ObjectHeader::Lookup(ty, fi.oid);      if (pObj)	pObj->FlushIfCkpt();      break;    }  case FRM_TYPE_ZNODE:    {      for (uint32_t n = 0; n < DISK_NODES_PER_PAGE; n++) {	OID oid = fi.obFrameOid + n;	Node * pNode = ObjectHeader::LookupNode(oid);	assert(pNode);		/* we pinned them previously! */	pNode->FlushIfCkpt();      }      break;    }  }}voidCheckpoint::RetagFrame(OID oid, uint8_t newType){  KernStats.nRetag++;  assert(newType == FRM_TYPE_ZNODE ||	 newType == FRM_TYPE_ZDPAGE);    DEBUGEX(retag, newType != FRM_TYPE_ZNODE)    MsgLog::dprintf(false, "Enter RetagFrame(0x%08x%08x, %d)\n",		    (uint32_t) (oid >> 32),		    (uint32_t) oid,		    newType);  #ifdef DBG_WILD_PTR  if (dbg_wild_ptr) {    Check::Consistency("Top RetagFrame()");    Checkpoint::CheckConsistency(false);  }#endif  FrameInfo fi(oid);  ObjectHeader *pPotHdr = Persist::GetTagPot(fi);  assert(pPotHdr);  pPotHdr->TransLock();		/* we will need this again... */  PagePot *pagePot = (PagePot *) ObjectCache::ObHdrToPage(pPotHdr);  ObCount count;  uint8_t curType = GetFrameInfo(fi, pagePot, count, newType);  assert (curType != newType);    assert(curType == FRM_TYPE_ZNODE ||	 curType == FRM_TYPE_ZDPAGE);    /* We now know everything we need to know about the current frame.   * Reserve space for the new objects:   */  uint32_t nObjects = (newType == FRM_TYPE_ZNODE) ? DISK_NODES_PER_PAGE : 1;  CleanCkptFrames(curType, fi);    /* Since we will be commited to making progress after we reserve the     log directories, ensure that any cached state associated with the     OLD object is killed before we reserve them. */    switch(curType) {  case FRM_TYPE_ZDPAGE:  case FRM_TYPE_DPAGE:    {      ObjectHeader *pObj = ObjectHeader::Lookup(ObType::PtDataPage, fi.oid);      if (pObj) {	if (pObj->GetFlags(OFLG_CKPT))	  assert(pObj->IsDirty() == false);      	pObj->kr.UnprepareAll(); /* This zaps any PTE's as a side effect. */	pObj->InvalidateProducts();	assert ( PTE::ObIsNotWritable(pObj) );      }      break;    }  case FRM_TYPE_ZNODE:  case FRM_TYPE_NODE:    {      for (uint32_t n = 0; n < DISK_NODES_PER_PAGE; n++) {	OID oid = fi.obFrameOid + n;	Node * pNode = ObjectHeader::LookupNode(oid);	assert(pNode);		/* we pinned them previously! */	if (pNode->GetFlags(OFLG_CKPT))	  assert(pNode->IsDirty() == false);	pNode->Unprepare(false);	pNode->kr.UnprepareAll();	for (uint32_t i = 0; i < EROS_NODE_SIZE; i++) {	  assert ( (*pNode)[i].IsHazard() == false );	  (*pNode)[i].NH_Unprepare();	  assert ( (*pNode)[i].IsUnprepared() );	}      }      break;    }  }  /* Make sure we have sufficient core and disk directory entries: */  if (CoreDirent::Require(nObjects) == false)    TakeCheckpoint();  /* Once we get the reserve on log directory entries we MUST go   * forward, as any yield from that point on cause them to be left   * dangling.  However, it is possible that we have zapped a PTE   * somewhere, and that the COMMIT_POINT() call will consequently   * fail when we make it.   *    * To make matters more interesting, reserving the log directory   * entries can fail, in which case we need to take a checkpoint and   * will yield as a result (which means we cannot commit yet).   *    * Make sure the commit will succeed before we attempt it.  The   * alternative is to unreserve them, but that is simply more hassle   * than it is worth.   */  inv.MaybeDecommit();    if (coreGeneration[current].ReserveDirent(nObjects) == false)    TakeCheckpoint();  assert (inv.CanCommit());  DEBUGEX(retag, newType != FRM_TYPE_ZNODE)    MsgLog::dprintf(false, "RetagFrame(0x%08x%08x, %d): got reserves\n",		    (uint32_t) (oid >> 32),		    (uint32_t) oid,		    newType);  /* Okay.  We are now free and clear to proceed.  Zap all in-core   * objects associated with the old frame, and also all associated   * directory entries in the current generation.   *    * As long as the objects are part of the current generation, it   * does not matter if they are dirty -- we can just blow them away.   * Unfortunately, it is possible that the object is:   *    *      Dirty, Marked for checkpoint, Not yet Writen.   *    * In that event we must force the object out before we kill it.   */    /* Since the objects are being destroyed, it does not matter if they   * are dirty.  Further, it does not matter if that log frame is   * actively being written, since we are about to blow away all   * references in the core directory to that frame (which will cause   * it to become free).   */  bool needBump = false;    switch(curType) {  case FRM_TYPE_ZDPAGE:    {      ObjectHeader *pObj = ObjectHeader::Lookup(ObType::PtDataPage, fi.oid);      if (pObj) {	if (pObj->GetFlags(OFLG_CKPT))	  assert(pObj->IsDirty() == false);      	assert ( pObj->kr.IsEmpty() );	assert ( pObj->products == 0 );	assert ( PTE::ObIsNotWritable(pObj) );#ifdef OFLG_PIN	pObj->ClearFlags(OFLG_PIN);#endif	pObj->ClearFlags(OFLG_CKPT|OFLG_DIRTY|OFLG_REDIRTY|OFLG_IO);	ObjectCache::ReleasePageFrame(pObj);      }      CoreDirent *cde = coreGeneration[current].FindObject(fi.oid);      assert(cde);      if (cde != CkNIL) {	coreGeneration[current].Release(cde);	coreGeneration[current].RemoveFromOidMap(cde);	coreGeneration[current].alloc.nCoreDirent--;	coreGeneration[current].UnreserveDirent();	delete cde;      }      break;    }  case FRM_TYPE_ZNODE:    {      for (uint32_t n = 0; n < DISK_NODES_PER_PAGE; n++) {	OID oid = fi.obFrameOid + n;	Node * pNode = ObjectHeader::LookupNode(oid);	assert(pNode);		/* we pinned them previously! */	if (pNode->GetFlags(OFLG_CKPT))	  assert(pNode->IsDirty() == false);	pNode->TransUnlock();	if (pNode->GetFlags(OFLG_DISKCAPS))	  needBump = true;	assert (pNode->obType == ObType::NtUnprepared);	assert (pNode->kr.IsEmpty());#ifndef NDEBUG	for (uint32_t i = 0; i < EROS_NODE_SIZE; i++) {	  assert ( (*pNode)[i].IsHazard() == false );	  assert ( (*pNode)[i].IsUnprepared() );	}#endif#ifdef OFLG_PIN	pNode->ClearFlags(OFLG_PIN);#endif	pNode->ClearFlags(OFLG_CKPT|OFLG_DIRTY|OFLG_REDIRTY|OFLG_IO);	ObjectCache::ReleaseNodeFrame(pNode);	CoreDirent *cde = coreGeneration[current].FindObject(oid);	assert(cde);	if (cde != CkNIL) {	  coreGeneration[current].Release(cde);	  coreGeneration[current].RemoveFromOidMap(cde);	  coreGeneration[current].alloc.nCoreDirent--;	  coreGeneration[current].UnreserveDirent();	  delete cde;	}      }      break;    }  }    if (needBump)    count++;    DEBUGEX(retag, newType != FRM_TYPE_ZNODE)    MsgLog::dprintf(false, "RetagFrame(0x%08x%08x, %d): zapped old residents\n",		    (uint32_t) (oid >> 32),		    (uint32_t) oid,		    newType);  /* So much for the old frame.  Now create a bunch of new, zero   * objects.   */  for (uint32_t n = 0; n < nObjects; n++) {    OID oid = fi.obFrameOid + n;    CoreDirent *cde = new CoreDirent;    assert(cde && cde != CkNIL);    cde->oid = oid;    cde->color = CoreDirent::red;    cde->count = count;    cde->lid = ZERO_LID;    cde->type = newType;    assert(cde->left == CkNIL);    assert(cde->right == CkNIL);    assert(cde->parent == CkNIL);    coreGeneration[current].alloc.nCoreDirent++;    coreGeneration[current].AddToOidMap(cde);  }  DEBUGEX(retag, newType != FRM_TYPE_ZNODE)    MsgLog::dprintf(newType != FRM_TYPE_ZNODE,		    "Exit RetagFrame(0x%08x%08x, %d)\n",		    (uint32_t) (oid >> 32),		    (uint32_t) oid,		    newType);}

⌨️ 快捷键说明

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