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

📄 ck_readwrite.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * 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/BlockDev.hxx>#include <kerninc/Check.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Machine.hxx>#define dbg_ckage	0x1	/* migration state machine */#define dbg_reservation	0x2	/* reservation logic */#define dbg_dirent	0x4	/* dirent manipulation */#define dbg_ndload      0x8/* 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 DEBUG2(x,y) if ((dbg_##x|dbg_##y) & dbg_flags)voidCheckpoint::AllocateMasterLid(lid_t ll){  logframe_t lf = (ll / EROS_OBJECTS_PER_FRAME);  allocMap.Allocate(lf);  nAvailLogFrame --;  nMasterPage ++;}voidCheckpoint::WriteNodeToLog(Node *pNode){#ifdef DBG_WILD_PTR  Check::Consistency("Top WriteNodeToLog()");#endif  assert(pNode->obType <= ObType::NtLAST_NODE_TYPE);  assert (pNode->IsDirty());  uint32_t gen = pNode->GetFlags(OFLG_CKPT) ? last_ckpt : current;  CoreGeneration *pGen = &coreGeneration[gen];  DEBUG(ckage)    MsgLog::dprintf(false, "Writing node 0x%08x%08x to log, generation %d\n",		    (uint32_t) (pNode->ob.oid > 32),		    (uint32_t) pNode->ob.oid,		    gen);#ifdef DBG_WILD_PTR  if (pNode->Validate() == false) {    MsgLog::printf("Node no good prior to hazard clearance\n");    Debugger();  }#endif  bool isZero = true;  for (uint32_t k = 0; k < EROS_NODE_SIZE; k++) {    if ( (*pNode)[k].IsRdHazard() )      pNode->ClearHazard(k);    isZero = isZero && pNode->slot[k].IsVoidKey();  }  #ifndef NDEBUG  if (pNode->Validate() == false) {    MsgLog::printf("Node no good post hazard clearance\n");    Debugger();  }#endif  CoreDirent *cde = FindObject(pNode->ob.oid, ObType::NtUnprepared, gen);  if (cde == 0 || cde == CkNIL)    MsgLog::dprintf(true, "Cleaning nd 0x%08x%08x -- cde=0x%08x not in cur dir\n",		    (uint32_t) (pNode->ob.oid >> 32),		    (uint32_t) pNode->ob.oid,		    cde);		      assert(cde && cde != CkNIL);  /* No ZNODE's here, as they should have been converted in   * RegisterDirtyObject()    */  assert (cde->type == FRM_TYPE_NODE);    ObjectHeader * pLogPageHdr = 0;  cde->count = pNode->ob.allocCount;#ifdef DBG_WILD_PTR  CheckConsistency(false);#endif  /* It would be nice if we could assume that /cde->lid == UNDEF_LID/.   * Regrettably, we can allocate a lid here in the call to   * pGen->Allocate() and then yield trying to fetch in that frame.   * When we subsequently try to rewrite the node, we will discover   * the previously allocated lid.  Note that we do not try to   * decommit the previously assigned location -- in all likelihood it   * was assigned very recently, and we do not want the effort to   * bring in the frame to be wasted.   *    * Just to make life interesting, however, it is possible that some   * other operation has zeroed the node in the interim.  In that   * case, we really do need to release the allocated storage.   */    if (isZero) {    pGen->Release(cde);    cde->type = FRM_TYPE_ZNODE;    cde->lid = ZERO_LID;    DEBUG(ckage)      MsgLog::dprintf(false, "    at lid=0x%08x\n", cde->lid);#ifdef DBG_WILD_PTR    CheckConsistency(false);#endif  }  else {    pGen->Allocate(cde);    DEBUG(ckage)      MsgLog::dprintf(false, "    at lid=0x%08x\n", cde->lid);  #ifdef DBG_WILD_PTR    CheckConsistency(false);#endif    pLogPageHdr = Persist::GetCkFrame(cde->lid);    assert(pLogPageHdr);    pLogPageHdr->TransLock();    assert( pLogPageHdr->GetFlags(OFLG_CKPT) == 0 );#ifdef DBG_CLEAN    MsgLog::printf("Object ty %d oid=0x%08x%08x marked dirty\n",		   pLogPageHdr->obType,		   (uint32_t) (pLogPageHdr->oid >> 32),		   (uint32_t) pLogPageHdr->oid);#endif    pLogPageHdr->SetDirtyFlag();    pLogPageHdr->age = Age::NewBorn;#ifdef DBG_WILD_PTR    CheckConsistency(false);#endif    DiskNode *potBase = (DiskNode *) ObjectCache::ObHdrToPage(pLogPageHdr);    DiskNode *pDiskNode = potBase + (cde->lid % EROS_OBJECTS_PER_FRAME);    DEBUG(ckage)      MsgLog::printf("WrNdToLg: lid=0x%x potBase=0x%x "		     "potHdr=0x%x pDiskNode=0x%x\n",		     cde->lid, potBase, pLogPageHdr, pDiskNode);        /* Copy the node to the log pot: */    *pDiskNode = *pNode;#ifdef DBG_WILD_PTR    CheckConsistency(false);#endif  }  #ifdef OPTION_OB_MOD_CHECK  pNode->ob.check = pNode->CalcCheck();#endif      pNode->ClearFlags(OFLG_DIRTY|OFLG_REDIRTY);#ifdef DBG_CLEAN  MsgLog::printf("Object 0x%08x ty %d oid=0x%08x%08x cleaned to node pot\n",		 pNode,		 pNode->obType,		 (uint32_t) (pNode->oid >> 32),		 (uint32_t) pNode->oid);#endif#ifdef DBG_WILD_PTR  CheckConsistency(false);    if (dbg_wild_ptr)    Check::Nodes();#endif  #if defined(DBG_WILD_PTR)  if (dbg_wild_ptr)    Check::Consistency("Bottom WriteNodeToLog()");#endif}lid_tCheckpoint::FindFreeFrame(){  logframe_t stop = LastAllocatedFrame;  logframe_t loc = LastAllocatedFrame + 1;  for (;loc != stop; loc++) {    if (loc == totLogFrame)      loc = 0;    if ( allocMap.IsFree(loc) ) {      LastAllocatedFrame = loc;      break;    }  }  if (loc == stop) {    MsgLog::fatal("loc: %d, lastAlloc: %d, totFrame: %d\n",		  loc, LastAllocatedFrame, totLogFrame);  }#if 0  MsgLog::dprintf(true, "Allocated log loc=%d\n", loc);#endif  /* If the log page exists in core, blow it away: */  lid_t ll = loc * EROS_OBJECTS_PER_FRAME;  #ifndef NDEBUG  ObjectHeader * pLogPageHdr =    ObjectHeader::Lookup(ObType::PtLogPage, ll);#endif  assert (pLogPageHdr == 0);#if 0  if (pLogPageHdr) {    /* It should not be involved in I/O -- if so, then it was not really     * free because migration was not done with it.     */    assert (pLogPageHdr->GetFlags(OFLG_IO) == 0);        ObjectCache::ReleasePageFrame(pLogPageHdr);  }#endif  return ll;}lid_tCheckpoint::AllocateLid(lid_t ll){  logframe_t frm = ll / EROS_OBJECTS_PER_FRAME;    assert (nReservedLogFrame >= nAllocatedLogFrame);  assert (CONTENT_LID(ll));    if (allocMap.IsFree(frm)) {    nAllocatedLogFrame++;    assert (nReservedLogFrame >= nAllocatedLogFrame);  }  allocMap.Allocate(frm);    return ll;}/* return true if log frame is now empty. */boolCheckpoint::DeallocateLid(lid_t ll){  logframe_t frm = ll / EROS_OBJECTS_PER_FRAME;  assert (nReservedLogFrame >= nAllocatedLogFrame);  assert (CONTENT_LID(ll));    allocMap.Deallocate(frm);    if (allocMap.IsFree(frm)) {    ll &= ~0xffu;        ObjectHeader * pLogPageHdr =      ObjectHeader::Lookup(ObType::PtLogPage, ll);    if (pLogPageHdr) {      assert(pLogPageHdr->IsDirty() == false);      pLogPageHdr->Unintern();      ObjectCache::ReleasePageFrame(pLogPageHdr);    }    nAllocatedLogFrame--;    nReservedLogFrame--;    return true;  }    return false;}boolCheckpoint::ReserveLogFrame(){  if (nReservedLogFrame == nAvailLogFrame) {    for (uint32_t g = nGeneration - 1; g >= first_migrated; g--) {      DEBUG(reservation)	MsgLog::printf("Reclaiming log frame from generation %d\n", g);      if (coreGeneration[g].ReclaimLogPage())	break;    }  }    if (nReservedLogFrame == nAvailLogFrame)    return false;  assert (nReservedLogFrame <= nAvailLogFrame);  nReservedLogFrame++;  return true;}/* We are making an object dirty.  If it is already dirty and non-zero * in the current checkpoint, do nothing and return. *  * If space is not already reserved for this object, See if we can * reserve space for the object in the log .  If so, reserve the * space. *  * If no directory entry exists, attempt to reserve a disk directory * entry for the object.  If that fails, declare a checkpoint. *  * If no directory entry exists, attempt to allocate and populate a * core directory entry for the object.  If that fails, declare a * checkpoint. */voidCheckpoint::RegisterDirtyObject(ObjectHeader *pObj){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top RegisterDirtyObject()");#endif  if (enabled == false)    return;#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Nodes();#endif  bool haveSpace = true;  if (migrationStatus != mg_Idle)    ProcessMigration();  /* RegisterDirtyObject() is called to tell the checkpoint logic that   * the object should be added to the checkpoint directory.   *    * It is possible that the object we are trying to make dirty was in   * core, and was just started on it's way to home location by the   * migrator.  If so, we must wait for the I/O to complete:   */  if (pObj->GetFlags(OFLG_IO)) {#if 0    if (pObj->GetFlags(OFLG_CKPT) == 0)      MsgLog::dprintf(true, "Object hdr 0x%x OFLG_IO but not OFLG_CKPT!\n",		      pObj);#endif        Thread::Current()->SleepOn(pObj->ObjectSleepQueue());    Thread::Current()->Yield();  }        assert (!pObj->IsDirty());    bool isNode = (pObj->obType <= ObType::NtLAST_NODE_TYPE);    CoreDirent* cde = coreGeneration[current].FindObject(pObj->ob.oid);  DEBUG(reservation)    MsgLog::dprintf(false, "Reserving space for %s 0x%08x%08x\n",		    isNode ? "Node" : "Page",		    (uint32_t) (pObj->ob.oid >> 32),		    (uint32_t) pObj->ob.oid);#ifdef DBG_WILD_PTR  Checkpoint::CheckConsistency(false);#endif  bool neededDirent = false;    /* Allocate the directory entry first, as this is easier to   * deallocate if we aren't able to get space for the actual object.   */  if (cde == CkNIL) {    neededDirent = true;    /* MUST grab the core dirent first, as allocating it might kick in     * the ageing mechanism, during which the reservation counts for     * core and disk dirents would disagree if we reserve the disk     * dirent first.  This in turn violates the consistency checker.     */        cde = new CoreDirent;    if (cde == 0 || cde == CkNIL) /* FIX: not sure */      goto take_checkpoint;        haveSpace = coreGeneration[current].ReserveDirent();    if (haveSpace == false) {      MsgLog::dprintf(true, "Could not reserve disk dirent\n");      goto release_core_dirent;    }        cde->oid = pObj->ob.oid;    cde->color = CoreDirent::red;    cde->count = pObj->ob.allocCount;    /* Note that we TEMPORARILY use VIRGIN_LID so that the Release()     * logic will know not to release any existing storage.     */    cde->lid = VIRGIN_LID;    cde->type = isNode ? FRM_TYPE_NODE : FRM_TYPE_DPAGE;    assert(cde->left == CkNIL);    assert(cde->right == CkNIL);    assert(cde->parent == CkNIL);    coreGeneration[current].alloc.nCoreDirent++;  }  /* Now reserve space for the actual object: */  if (isNode) {    if (! coreGeneration[current].ReserveNode() ) {      MsgLog::dprintf(true, "Could not reserve log space for node\n");      goto release_dirent;    }    coreGeneration[current].Release(cde);    cde->lid = UNDEF_LID;    cde->type = FRM_TYPE_NODE;

⌨️ 快捷键说明

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