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

📄 kern_objectcache.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
      if (pObj->IsUserPinned())	continue;      if (pObj->IsKernelPinned())	continue;    #ifdef USES_MAPPING_PAGES      /* Or because their producer is pinned -- these cannot go out       * because they are likely to be involved in page translation.       */      if (pObj->obType == ObType::PtMappingPage) {	assert(pObj->IsDirty() == false);	ObjectHeader * pProducer = pObj->producer;	if (pProducer->IsUserPinned())	  continue;	if (pProducer->IsKernelPinned())	  continue;      }#endif      if (pObj->age == Age::PageOut) {	/* Mapping pages should never make it to PageOut age, because	 * they should be zapped at the invalidate age. It's	 * relatively cheap to rebuild them, and zapping them eagerly	 * has the desirable consequence of keeping their associated	 * nodes in memory if the process is still active.	 */	assert(pObj->obType != ObType::PtMappingPage);	if (CleanFrame(pObj) == false)	  continue;    	assert (!pObj->IsDirty());	/* Remove this page from the cache and return it to the free page	 * list:	 */	curPage++;	ReleaseFrame(reclaimedObject);	return;      }            pObj->age++;      if (pObj->age == Age::Invalidate) {#ifdef USES_MAPPING_PAGES	/* It's a lot cheaper to regenerate a mapping page than to	 * read some other page back in from the disk...	 */	if (pObj->obType == ObType::PtMappingPage) {	  curPage++;	  ReleaseMappingFrame(pObj);	  return;	}#endif		CleanFrame(pObj, false);      }    }  } while (--nPasses);}voidObjectCache::WaitForAvailablePageFrame(){  assert (nFreePageFrames >= nReservedIoPageFrames);    if (nFreePageFrames == nReservedIoPageFrames)    AgePageFrames();  assert (nFreePageFrames > nReservedIoPageFrames);}ObjectHeader *ObjectCache::GrabPageFrame(){  WaitForAvailablePageFrame();  assert (nFreePageFrames > 0);  assert(firstFreePage);  ObjectHeader *pObHdr = firstFreePage;  GrabThisFrame(pObHdr);  return pObHdr;}voidObjectCache::RequireNodeFrames(uint32_t n){  while (nFreeNodeFrames < n)    AgeNodeFrames();}#if 0voidObjectCache::RequirePageFrames(uint32_t n){  while (nFreeNodeFrames < n)    AgePageFrames();}#endifboolObjectCache::GrabThisFrame(ObjectHeader *pObj){  if (pObj->obType == ObType::NtFreeFrame) {    Node *pNode = (Node *) pObj;    if (pNode == firstFreeNode) {      firstFreeNode = (Node *) firstFreeNode->next;    }    else {      Node *nodeChain = firstFreeNode;      while (nodeChain->next != pNode)	nodeChain = (Node *) nodeChain->next;            nodeChain->next = nodeChain->next->next;    }    nFreeNodeFrames--;    /* Rip it off the hash chain, if need be: */    pNode->Unintern();		/* Should it ever be interned? */    bzero(pNode, sizeof(ObjectHeader));    pNode->obType = ObType::NtUnprepared;    #ifndef NDEBUG    for (uint32_t i = 0; i < EROS_NODE_SIZE; i++) {      if (pNode->slot[i].IsUnprepared() == false)	dprintf(true, "Virgin node 0x%08x had prepared slot %d\n",			pNode, i);    }#endif    assert(ObjectCache::ValidNodePtr(pNode));    DEBUG(ndalloc)      printf("Allocated node=0x%08x nfree=%d\n", pNode, nFreeNodeFrames);  }  else if (pObj->obType == ObType::PtFreeFrame) {    if (pObj == firstFreePage) {      firstFreePage = firstFreePage->next;    }    else {      ObjectHeader *pgChain = firstFreePage;      while (pgChain->next != pObj)	pgChain = pgChain->next;            pgChain->next = pgChain->next->next;    }    nFreePageFrames--;    assert(pObj->kr.IsEmpty());    kva_t kva;    kva = pObj->pageAddr;    bzero(pObj, sizeof(*pObj));    pObj->pageAddr = kva;    pObj->obType = ObType::PtNewAlloc; /* until further notice */      assert ( PTE::ObIsNotWritable(pObj) );  }  else {    assertex(pObj, "GrabThisFrame() on non-free frame" && false);    return false;  }  pObj->age = Age::NewBorn;  pObj->ResetKeyRing();  return true;}Node *ObjectCache::GrabNodeFrame(){  Node *pNode = 0;  if (firstFreeNode == 0)    AgeNodeFrames();    assert(firstFreeNode);  assert(nFreeNodeFrames);    pNode = firstFreeNode;  GrabThisFrame(pNode);  return pNode;}voidObjectCache::ReleaseFrame(ObjectHeader *pObHdr){  assert(pObHdr);    assert(pObHdr->kr.IsEmpty());  /* Not certain that *anything* handed to ReleaseFrame() should be   * dirty, but...   */  if (pObHdr->GetFlags(OFLG_CKPT))    assert (!pObHdr->IsDirty());#ifndef NDEBUG  if (pObHdr->obType <= ObType::NtLAST_NODE_TYPE) {    Node *pNode = (Node *) pObHdr;    for (uint32_t i = 0; i < EROS_NODE_SIZE; i++)      assertex (pNode, pNode->slot[i].IsUnprepared());  }  else    assert ( PTE::ObIsNotWritable(pObHdr) );#endif  pObHdr->Unintern();      if (pObHdr->obType <= ObType::NtLAST_NODE_TYPE) {    pObHdr->obType = ObType::NtFreeFrame;    pObHdr->next = firstFreeNode;    firstFreeNode = (Node *) pObHdr;    nFreeNodeFrames++;  }  else {    pObHdr->obType = ObType::PtFreeFrame;    pObHdr->next = firstFreePage;    firstFreePage = pObHdr;      nFreePageFrames++;    PageAvailableQueue.WakeAll();  }}/**************************************************************** * * Interaction with object sources; * ****************************************************************/#define MAX_SOURCE (MAX_PRELOAD + 4)static ThreadPile SourceWait;static ObjectSource *sources[MAX_SOURCE];static uint32_t nSource = 0;voidObjectCache::InitObjectSources(){  ObjectSource *source = new (0) ObCacheSource();  AddSource(source);  for (unsigned i = 0; i < BootInfoPtr->nDivInfo; i++) {    DivisionInfo *di = &BootInfoPtr->divInfo[i];    assertex(di, di->flags & DF_PRELOAD);    assert(di->type == dt_Object);    source = new (0) PreloadObSource(di);        AddSource(source);  }  for (unsigned i = 0; i < PhysMem::nPmemInfo; i++) {    PmemInfo *pmi = &PhysMem::pmemInfo[i];    if (pmi->type == MI_MEMORY) {      source = new (0) PhysPageSource(pmi);      AddSource(source);    }  }  // Need to special case the publication of the BIOS ROM, as we need  // object cache entries for these. This must be done *after* the  // MI_MEMORY cases, because malloc() needs to work.  for (unsigned i = 0; i < PhysMem::nPmemInfo; i++) {    PmemInfo *pmi = &PhysMem::pmemInfo[i];    if (pmi->type == MI_BOOTROM) {      ObjectCache::AddDevicePages(pmi);      source = new (0) PhysPageSource(pmi);      AddSource(source);    }  }}voidObjectCache::WaitForSource(){  Thread::Current()->SleepOn(SourceWait);  Thread::Current()->Yield();}boolObjectCache::AddSource(ObjectSource *source){  if (nSource == MAX_SOURCE)    fatal("Limit on total object sources exceeded\n");    DEBUG(obsrc)    printf("New source: \"%s\" [0x%08x%08x,0x%08x%08x)\n",		   source->name,		   (unsigned) (source->start >> 32),		   (unsigned) (source->start),		   (unsigned) (source->end >> 32),		   (unsigned) (source->end));  /* First, verify that the new source does not overlap any existing   * source (except for the object cache, of course).   */  for (unsigned i = 1; i < nSource; i++) {    if (source->end <= sources[i]->start)      continue;    if (source->start >= sources[i]->end)      continue;    dprintf(true, "New source 0x%x overlaps existing source 0x%x\n",		    source, sources[i]);    return false;  }  sources[nSource++] = source;  SourceWait.WakeAll();  return true;}boolObjectCache::HaveSource(OID oid){  /* NOTE that this skips the ObCache */  for (unsigned i = 1; i < nSource; i++)    if (sources[i]->start <= oid && oid < sources[i]->end)      return true;  /* Until proven otherwise: */  return false;}ObjectHeader *ObjectCache::GetObject(OID oid, ObType::Type obType, 		       ObCount count, bool useCount){  ObjectHeader *pObj = 0;  if (!ObjectCache::HaveSource(oid)) {    dprintf(true, "No source for OID 0x%08x%08x...\n",		    (unsigned long) (oid >> 32),		    (unsigned long) (oid));    ObjectCache::WaitForSource();  }  for (unsigned i = 0; !pObj && i < nSource; i++) {    if (sources[i]->start <= oid && oid < sources[i]->end)      pObj = sources[i]->GetObject(oid, obType, count, useCount);  }  if (pObj) {#ifdef DBG_WILD_PTR    if (dbg_wild_ptr)      Check::Consistency("End GetObject()");#endif    if (useCount && pObj->ob.allocCount != count)      return 0;          return pObj;  }  inv.MaybeDecommit();  fatal("ObjecCache::GetObject(): oid 0x%08x%08x not found\n",		(unsigned) (oid >> 32),		(unsigned) oid);  return 0;}boolObjectCache::WriteBack(ObjectHeader *pObj, bool inBackground){  bool done = false;  for (unsigned i = 0; !done && i < nSource; i++)    if (sources[i]->start <= pObj->ob.oid && pObj->ob.oid < sources[i]->end)      done = sources[i]->WriteBack(pObj, inBackground);  return done;}boolObjectCache::Invalidate(ObjectHeader *pObj){  bool done = false;  for (unsigned i = 0; !done && i < nSource; i++)    if (sources[i]->start <= pObj->ob.oid && pObj->ob.oid < sources[i]->end)      done = sources[i]->Invalidate(pObj);  return done;}boolObjectCache::IsRemovable(ObjectHeader *pObj){  bool result = false;  for (unsigned i = 0; !result && i < nSource; i++)    if (sources[i]->start <= pObj->ob.oid && pObj->ob.oid < sources[i]->end)      result = sources[i]->IsRemovable(pObj);  /* Until proven otherwise: */  return result;}void ObjectCache::FindFirstSubrange(OID limStart, OID limEnd, 			       OID& subStart, OID& subEnd){  /* Bypass entry 0, because the object cache itself can of course   * represent anything representable. */  subStart = ~0llu;		/* until proven otherwise */  subEnd = ~0llu;  DEBUG(findfirst)    printf("ObCache::FindFirstSubrange(): limStart 0x%08x%08x, "		   "limEnd 0x%08x%08x  nSource %d\n",		   (unsigned long) (limStart >> 32),		   (unsigned long) (limStart),		   (unsigned long) (limEnd >> 32),		   (unsigned long) (limEnd),		   nSource);  /* ObjectSources (ignoring the object cache) implement disjoint   * ranges, but they do not necessarily implement fully populated   * ranges.    */  for (unsigned i = 1; i < nSource; i++) {    /* Check if the requested range and the source overlap: */    if (sources[i]->end <= limStart) {      DEBUG(findfirst)	printf("Reject %d: end 0x%08x%08x <= limStart\n",		       i,		       (unsigned long) (sources[i]->end >> 32),		       (unsigned long) (sources[i]->end));      continue;    }    if (sources[i]->start >= limEnd) {      DEBUG(findfirst)	printf("Reject %d: start 0x%08x%08x >= limStart\n",		       i,		       (unsigned long) (sources[i]->start >> 32),		       (unsigned long) (sources[i]->start));      continue;    }    /* If so, and if the answer could possibly be better than what we     * already have, ask the source: */    if (sources[i]->start < subStart) {      DEBUG(findfirst)	printf("Consulting source %d for [0x%08x%08x, 0x%08x%08x)\n",		       i,		       (unsigned long) (sources[i]->start >> 32),		       (unsigned long) (sources[i]->start),		       (unsigned long) (sources[i]->end >> 32),		       (unsigned long) (sources[i]->end));      sources[i]->FindFirstSubrange(limStart, limEnd, subStart, subEnd);    }  }}#ifdef OPTION_DDBvoidObjectCache::ddb_DumpSources(){  extern void db_printf(const char *fmt, ...);  for (unsigned i = 0; i < nSource; i++) {    ObjectSource *src = sources[i];    printf("[0x%08x%08x,0x%08x%08x): %s\n",	   (unsigned) (src->start >> 32),	   (unsigned) src->start,	   (unsigned) (src->end >> 32),	   (unsigned) src->end,	   src->name);  }  if (nSource == 0)    printf("No object sources.\n");}#endif

⌨️ 快捷键说明

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