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

📄 kern_persist.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
          return pPage;  }  FrameInfo fi(oid);  if (fi.cd == 0) {    fatal("pg oid= 0x%08x%08x.  Should sleep on mountwait queue here\n",		  (uint32_t)(oid>>32), (uint32_t) oid);    return 0;  }  assert (InvocationCommitted == false);    DEBUG(req)    dprintf(stop, "Page lookup failed\n");  CoreDirent* cde = Checkpoint::FindObject(oid, ObType::PtDataPage, Checkpoint::current);  if (cde == 0) {    DEBUG(req)      dprintf(true, "Wrong tag type\n");    return 0;  }    if (cde != CkNIL) {    if (useCount && cde->count != count)      return 0;    return Checkpoint::LoadCurrentPage(cde);  }  DEBUG(req)    dprintf(stop, "Loading home location of page\n");  ObjectHeader *pPot = GetTagPot(fi);  assert (pPot);  PagePot *pp = (PagePot *) ObjectCache::ObHdrToPage(pPot);  DEBUG(req)    dprintf(stop, "rel tag frame %d gives tag %d\n",		    fi.relTagFrame, pp->type[fi.tagEntry]);      switch (pp->type[fi.tagEntry]) {  case FRM_TYPE_ZDPAGE:    {      ObjectHeader* pPage = ObjectCache::GrabPageFrame();      uint8_t * pbuf = (uint8_t *) ObjectCache::ObHdrToPage(pPage);      bzero( (void*) pbuf, EROS_PAGE_SIZE);      pPage->ob.oid = oid;      pPage->ob.allocCount = pp->count[fi.tagEntry];      pPage->SetFlags(OFLG_CURRENT|OFLG_DISKCAPS);#ifdef OFLG_PIN      assert (pPage->GetFlags(OFLG_PIN) == 0);#endif      pPage->ClearFlags(OFLG_CKPT|OFLG_DIRTY|OFLG_REDIRTY|OFLG_IO);#ifdef DBG_CLEAN      printf("Object ty %d oid=0x%08x%08x loaded clean\n",		     pPage->obType,		     (uint32_t) (pPage->oid >> 32),		     (uint32_t) pPage->oid);#endif      pPage->ob.ioCount = 0;      pPage->obType = ObType::PtDataPage;      pPage->products = 0;#ifdef OPTION_OB_MOD_CHECK      pPage->ob.check = pPage->CalcCheck();#endif      pPage->ResetKeyRing();      pPage->Intern();#ifndef NDEBUG      ObjectHeader *npPage = ObjectHeader::Lookup(ObType::PtDataPage,oid);      assert(npPage == pPage);#endif      return pPage;    }  case FRM_TYPE_DPAGE:    ReadPageFrame(fi.cd, fi.relObFrame, ObType::PtDataPage,		  fi.obFrameOid, pp->count[fi.tagEntry]);     assert(false);    break;  default:    return 0;  }  /* If all of the above fail, page is for an out of range OID. */  printf("Out of range page OID ");  print(oid);  fatal("\n");  return 0;}/* Wrapper for GetCkFrame used in checkpoint load logic.  Catches the * yield thrown by the checkpoint logic, issues a DirectedYield(), and * retries on wakeup. */ObjectHeader *Persist::KernGetCkFrame(lid_t lid){#ifndef NDEBUG  extern uint32_t TrapDepth;  assert ( Thread::Current()->IsKernel() && TrapDepth == 0);#endif  Process *p = Thread::CurContext();  /* hand-construct a misc logpage key in slot 1: */  Key& k = p->keyReg[1];  k.NH_VoidKey();		/* restore slot to well-known state */  k.SetType(KT_LogFrame);  k.nk.value[0] = lid;  k.nk.value[1] = 0;  k.nk.value[2] = 0;  Message msg;  bzero(&msg, sizeof(msg));  msg.invType = IT_Call;  msg.snd_invKey = 1;  msg.snd_code = OC_KeyType;  msg.snd_w1 = 0;  msg.snd_w2 = 0;  msg.snd_w3 = 0;    msg.rcv_key0 = KR_VOID;  msg.rcv_key1 = KR_VOID;  msg.rcv_key2 = KR_VOID;  msg.rcv_key3 = KR_VOID;  msg.snd_key0 = KR_VOID;  msg.snd_key1 = KR_VOID;  msg.snd_key2 = KR_VOID;  msg.snd_key3 = KR_VOID;    CALL(&msg);    ObjectHeader * pLogPageHdr =    ObjectHeader::Lookup(ObType::PtLogPage, lid);  assert(pLogPageHdr);    DEBUG(req) printf("GetCkPage: pLogPageHdr = 0x%08x\n",			    pLogPageHdr);  assert (pLogPageHdr);  return pLogPageHdr;}ObjectHeader *Persist::ZeroCkFrame(lid_t lid){  ObjectHeader *pObj = ObjectCache::GrabPageFrame();  bzero( (void*) ObjectCache::ObHdrToPage(pObj), EROS_PAGE_SIZE );  pObj->ob.oid = lid;  pObj->ob.allocCount = 0;  pObj->SetFlags(OFLG_CURRENT|OFLG_DISKCAPS);#ifdef OFLG_PIN  assert (pObj->GetFlags(OFLG_PIN) == 0);#endif  pObj->ClearFlags(OFLG_CKPT|OFLG_IO);  pObj->SetFlags(OFLG_DIRTY|OFLG_REDIRTY);#ifdef DBG_CLEAN  printf("Object ty %d oid=0x%08x%08x loaded clean\n",		 pObj->obType,		 (uint32_t) (pObj->oid >> 32),		 (uint32_t) pObj->oid);#endif  pObj->ob.ioCount = 0;  pObj->obType = ObType::PtLogPage;  pObj->products = 0;#ifdef OPTION_OB_MOD_CHECK  pObj->ob.check = pObj->CalcCheck();#endif  pObj->ResetKeyRing();  pObj->Intern();  return pObj;}ObjectHeader *Persist::GetCkFrame(lid_t lid){  lid = EROS_FRAME_FROM_OID(lid);  DEBUG(req) printf("GetCkPage: lid = 0x%x\n", lid);    CoreDivision *pcd = FindDivision(dt_Log, lid);  if (!pcd)    return 0;  ObjectHeader * pLogPageHdr =    ObjectHeader::Lookup(ObType::PtLogPage, lid);  DEBUG(req) printf("GetCkPage: pLogPageHdr = 0x%08x\n",			    pLogPageHdr);  if (pLogPageHdr)    return pLogPageHdr;    assert (InvocationCommitted == false);    DEBUG(req) printf("GetCkPage: Reading page...\n");  /* If an I/O is already pending, wait for it.  If there are live   * objects in the frame, fetch it. Otherwise, allocate a new zero   * frame.    */  DuplexedIO *pDio = DuplexedIO::FindPendingIO(lid, ObType::PtLogPage);  if (pDio) {    DEBUG(req) printf("Thread 0x%08x Sleeps because I/O is "			      "already in progress\n");     DEBUG(req) dprintf(true, "DIO [0x%08x]: status %d nReq %d pObHdr=0x%08x\n",			       pDio, pDio->status, pDio->nRequest, pDio->pObHdr);    Thread::Current()->SleepOn(pDio->stallQ);    Thread::Current()->Yield();  }      if (Checkpoint::FrameIsEmpty(lid)) {    ObjectHeader *pObj = ZeroCkFrame(lid);    assert ( PTE::ObIsNotWritable(pObj) );    pObj->ClearFlags(OFLG_DIRTY|OFLG_REDIRTY);        return pObj;  }  else {    ReadLogFrame(lid);    return 0;			/* suppress GCC warning */  }}/* Return true if the passed division is a duplex of 'this', including * if it *is* this. */boolCoreDivision::IsDuplexOf(const CoreDivision *cd){  DEBUG(div)    if (cd->type != dt_Unused)      dprintf(true, "Check cd %d (type %s) start=0x%x, end=0x%x\n",		      cd - coreDivTbl,		      div_TypeName(cd->type),		      (uint32_t) cd->startOid,		      (uint32_t) cd->endOid);  if (cd->type != type)    return false;        if ( cd->startOid != startOid )    return false;  return true;}/* Write a page to the first sector of all object ranges... */voidPersist::WriteRangeHeaders(struct ObjectHeader *pObj){  Request::Require(KTUNE_NCOREDIV);  /* This must not be done lazily: */  DuplexedIO *dio = DuplexedIO::Grab(0, IoCmd::Write);   DEBUG(io) dprintf(true, "Setting up request (dt=ALL)...\n");  dio->pObHdr = pObj;  dio->completionCallBack = 0;    pObj->SetFlags(OFLG_IO);  pObj->ClearFlags(OFLG_REDIRTY);  pObj->ob.ioCount = 1;  dio->ioaddr = ObjectCache::ObHdrToPage(pObj);      for (uint32_t i = 0; i < KTUNE_NCOREDIV; i++) {    CoreDivision *cd = &coreDivTbl[i];    if (cd->type != dt_Object)      continue;        /* Found an object range. Queue the I/O on the device: */    Partition *part = cd->partition;    assert(part);    Request *req = new Request(part->unit,			       IoCmd::Write, cd->start,			       EROS_PAGE_SECTORS);    assert(req);    dio->AddRequest(req);    assert(req);    DEBUG(io) dprintf(true, "Insert request on %s%d-%d\n",			      part->ctrlr->name,			      part->unit,			      part->ndx);    part->InsertRequest(req);  }#if 0  /* There is never any need to wait for this I/O. */  if (synchronous)    Thread::Current()->SleepOn(dio.stallQ);#endif#if 0  dprintf(true, "Write dt=%s DIO 0x%08x pOb 0x%08x data 0x%08x ready to run\n",		  pcd->TypeName(), &dio, dio.pObHdr, dio.ioaddr);#endif  dio->Release();  assert(Thread::Current());  Thread::Current()->pageWriteCount++;#if 0  if (synchronous)    Thread::Current()->Yield();#endif}/* Write a page to a core division and all of it's duplexes, without * regard to the type of the page -- this is the bottom level write * implementation.  */voidPersist::WritePageTo(struct ObjectHeader *pObj, CoreDivision *pcd,		     uint32_t atSector, bool synchronous,		     void (*callBack)(DuplexedIO*)){  assert (pObj);  assert (pcd);  assert (pObj->obType > ObType::NtLAST_NODE_TYPE);#if defined(OPTION_OB_MOD_CHECK) && 0  if (pObj->IsDirty())    pObj->check = pObj->CalcCheck();#endif    if (pObj->GetFlags(OFLG_IO)) {    Thread::Current()->SleepOn(pObj->ObjectSleepQueue());    Thread::Current()->Yield();  }      assert ( PTE::ObIsNotWritable(pObj) );  Request::Require(KTUNE_MAXDUPLEX);  DuplexedIO *dio = DuplexedIO::Grab(pObj->ob.oid, IoCmd::Write);  DEBUG(io) dprintf(true, "Setting up request (dt=%s)...\n",			    div_TypeName(pcd->type));  dio->pObHdr = pObj;  dio->completionCallBack = callBack;    pObj->SetFlags(OFLG_IO);  pObj->ClearFlags(OFLG_REDIRTY);  pObj->ob.ioCount = 1;  dio->ioaddr = ObjectCache::ObHdrToPage(pObj);     for (uint32_t i = 0; i < KTUNE_NCOREDIV; i++) {    CoreDivision *cd = &coreDivTbl[i];    if (! cd->IsDuplexOf(pcd))      continue;        /* Found a replicate of the right range. Queue the I/O on the     * device:      */    Partition *part = cd->partition;    assert(part);    Request *req = new Request(part->unit,			       IoCmd::Write, atSector + cd->start,			       EROS_PAGE_SECTORS);    assert(req);    dio->AddRequest(req);    assert(req);    DEBUG(io) dprintf(true, "Insert request on %s%d-%d\n",			      part->ctrlr->name,			      part->unit,			      part->ndx);    part->InsertRequest(req);  }  if (synchronous)    Thread::Current()->SleepOn(dio->stallQ);#if 0  dprintf(true, "Write dt=%s DIO 0x%08x pOb 0x%08x data 0x%08x ready to run\n",		  pcd->TypeName(), dio, dio->pObHdr, dio->ioaddr);#endif  dio->Release();  assert(Thread::Current());  Thread::Current()->pageWriteCount++;  if (synchronous)    Thread::Current()->Yield();}voidPersist::WritePageToHome(struct ObjectHeader *pObj, OID oid){  assert (pObj->obType == ObType::PtLogPage ||	  pObj->obType == ObType::PtDataPage);  /* assert(pObj->IsDirty()); */  FrameInfo fi(oid);  if (fi.cd == 0)    fatal("Writing object to nonexistent range\n");  WritePageTo(pObj, fi.cd, fi.relObFrame * EROS_PAGE_SECTORS);}voidPersist::WritePageToLog(struct ObjectHeader *pObj, lid_t lid,			bool synchronous,			void (*callBack)(DuplexedIO*)){  assert (pObj->obType == ObType::PtLogPage	  || pObj->obType == ObType::PtDriverPage);  #ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top WritePageToLog()");#endif#ifndef NDEBUG  if ( pObj->obType == ObType::PtLogPage && pObj->IsDirty() == false )    dprintf(true, "Object (hdr=0x%08x) is not dirty in WritePageToLog()\n",		    pObj);  assert(pObj->obType == ObType::PtDriverPage || pObj->IsDirty());#endif  ObjectHeader * pLogPageHdr =    ObjectHeader::Lookup(ObType::PtLogPage, lid);  if (pLogPageHdr) {    assert (pLogPageHdr != pObj);    ObjectCache::ReleasePageFrame(pLogPageHdr);  }  CoreDivision * pcd = FindDivision(dt_Log, lid);  /* Do not deal with dismounted home ranges yet. */  assert (pcd);  uint64_t relativeOid = lid - pcd->startOid;  uint32_t relativePage = relativeOid / EROS_OBJECTS_PER_FRAME;  WritePageTo(pObj, pcd, relativePage * EROS_PAGE_SECTORS,	      synchronous, callBack);}/* WritePage() is called by the ageing logic to force pages to disk. * To my initial surprise, deciding where to put them is not * difficult: *  *   LogPage      written to the log *   UserPage     written to the log *   NodePot      written to home location -- node pots are ONLY *                dirtied by the migrator, so their content is safe. *   AllocPot     written to home location, as with NodePot. *  * Rewriting dirty pages back to home locations might seem a bit * tricky, but turns out to be very simple.  The page isn't migrated * unless it is current.  If it *is* current, the migrator brings it * in to core and then uses Persist::WritePageToHome() to force it to * go out to it's home location. *  * In general, the I/O subsystem allows a dirty page to be remodified * if it is in an outbound I/O queue.  Note that since it was current, * the user page going to home location CANNOT be dirty.  Attempts to * mutate it will therefore generate a fault, at which point we will * notice that this page is the checkpoint version and perform COW. *//* FIX: if page being written is ckpt and dirty, should retag as log frame. */voidPersist::WritePage(struct ObjectHeader *pObj, bool synchronous){  uint32_t relativePage = 0;  CoreDivision *cd = 0;  assert(pObj->IsDirty());  switch(pObj->obType) {  case ObType::PtAllocPot:    {      /* Going to home location.  OID == oid of first covered entry,       * so we don't need to round that.  We do need to adjust the       * offset by the overhead of intervening clusters, if any:       */            FrameInfo fi(pObj->ob.oid);      if (fi.cd == 0)	fatal("Writing object to nonexistent range\n");      relativePage = fi.relTagFrame;      cd = fi.cd;      break;    }  case ObType::PtObjectPot:     {      /* Going to home location.  OID == oid of first covered entry,       * so we don't need to round that, but the computation of       * relative page needs to be scaled by the cluster size:       */            FrameInfo fi(pObj->ob.oid);      if (fi.cd == 0)	fatal("Writing object to nonexistent range\n");      relativePage = fi.relObFrame;      cd = fi.cd;      break;    }  case ObType::PtDataPage:    {      lid_t where = Checkpoint::GetLidForPage(pObj);#if 1      if (where == ZERO_LID) {#ifdef OPTION_OB_MOD_CHECK	pObj->ob.check = pObj->CalcCheck();	assert(pObj->ob.check == 0);#endif	pObj->ClearFlags(OFLG_IO|OFLG_DIRTY|OFLG_REDIRTY);#ifdef DBG_CLEAN	printf("Object ty %d oid=0x%08x%08x written zero\n",		       pObj->obType,		       (uint32_t) (pObj->oid >> 32),		       (uint32_t) pObj->oid);#endif	pObj->ObjectSleepQueue().WakeAll();	return;      }#endif#if 0      /* FIX: this seems to be causing trouble, and it isn't       * necessary.       *        *        * If this is no longer the current version of the page, retag       * this object as a copy of the log frame so that the migrator       * will be able to find it later if it has not been aged out.       * Note that if we fail to get the proper I/O request structure,       * this write will recur properly, because StabilizePages()       * stabilizes dirty log frames as well.       */      if (pObj->flags.current == 0) {	assert (pObj->flags.ckpt);	pObj->flags.ckpt = 0;	pObj->obType = ObType::PtLogPage;	pObj->oid = where;	pObj->Intern();      }#endif            cd = FindDivision(dt_Log, where);      relativePage = where - (uint32_t) cd->startOid;      relativePage /= EROS_OBJECTS_PER_FRAME;      break;    }  case ObType::PtLogPage:    {      lid_t where = pObj->ob.oid;      cd = FindDivision(dt_Log, where);      relativePage = where - (uint32_t) cd->startOid;      relativePage /= EROS_OBJECTS_PER_FRAME;      break;    }  default:    fatal("Don't know how to write obtype=%d\n", pObj->obType);    break;  }  WritePageTo(pObj, cd, relativePage * EROS_PAGE_SECTORS, synchronous);}

⌨️ 快捷键说明

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