📄 kern_objectcache.cxx
字号:
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 + -