📄 kern_objectheader.cxx
字号:
/* * 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 <kerninc/kernel.hxx>#include <kerninc/Check.hxx>#include <kerninc/ObjectHeader.hxx>#include <kerninc/ObjectCache.hxx>#include <kerninc/Thread.hxx>#include <kerninc/SegWalk.hxx>#include <kerninc/Depend.hxx>#include <arch-kerninc/PTE.hxx>#include <eros/memory.h>#define dbg_rescind 0x1 /* steps in taking snapshot *//* Following should be an OR of some of the above */#define dbg_flags (0)#define DBCOND(x) (dbg_##x & dbg_flags)#define DEBUG(x) if DBCOND(x)#define DEBUG2(x,y) if ((dbg_##x|dbg_##y) & dbg_flags)/* If MAX_PIN is changed, may need to check for overflow on user * thread invocation of Pin(). */uint8_t ObjectHeader::CurrentTransaction = 1; /* guarantee nonzero! */#ifdef OPTION_DDBconst char *ObType::ddb_name(uint8_t t){ const char * names[] = { "NtUnprep ", "NtSegment ", "NtProcRoot", "NtKeyRegs ", "NtRegAnnex", "NtFreeFrm ", "PtDataPage", "PtNewAlloc", "PtKernHeap",#ifdef USES_MAPPING_PAGES "PtMapPage ",#endif "PtDevPage ", "PtFreeFrm ", 0 }; return names[t];}#endifvoidObjectHeader::KernPin(){ assert(kernPin < BYTE_MAX); kernPin++;#ifdef OFLG_PIN SetFlags(OFLG_PIN);#endif}voidObjectHeader::KernUnpin(){ assert(kernPin); kernPin--;#ifdef OFLG_PIN if (kernPin == 0 && userPin == 0) ClearFlags(OFLG_PIN);#endif}/* Walk the node looking for an acceptable product: */ObjectHeader *ObjectHeader::FindProduct(SegWalk& wi, uint32_t ndx, bool rw, bool ca){ uint32_t blss = wi.segBlss;#if 0 printf("Search for product blss=%d ndx=%d, rw=%c producerTy=%d\n", blss, ndx, rw ? 'y' : 'n', obType);#endif /* #define FINDPRODUCT_VERBOSE */ ObjectHeader *product = 0; for (product = products; product; product = product->next) { if ((uint32_t) product->producerBlss != blss) {#ifdef FINDPRODUCT_VERBOSE printf("Producer BLSS not match\n");#endif continue; } if (product->mp.redSeg != wi.redSeg) {#ifdef FINDPRODUCT_VERBOSE printf("Red seg not match\n");#endif continue; } if (product->mp.redSeg) {#ifdef KT_Wrapper if (product->mp.wrapperProducer != wi.segObjIsWrapper) {#ifdef FINDPRODUCT_VERBOSE printf("redProducer not match\n"); #endif continue; }#else if (product->mp.redProducer != wi.segObjIsRed) {#ifdef FINDPRODUCT_VERBOSE printf("redProducer not match\n"); #endif continue; }#endif if (product->mp.redSpanBlss != wi.redSpanBlss) {#ifdef FINDPRODUCT_VERBOSE printf("redSpanBlss not match: prod %d wi %d\n", product->mp.redSpanBlss, wi.redSpanBlss);#endif continue; } } if ((uint32_t) product->producerNdx != ndx) {#ifdef FINDPRODUCT_VERBOSE printf("producerNdx not match\n");#endif continue; } if (product->rwProduct != (rw ? 1 : 0)) {#ifdef FINDPRODUCT_VERBOSE printf("rwProduct not match\n");#endif continue; } if (product->caProduct != (ca ? 1 : 0)) {#ifdef FINDPRODUCT_VERBOSE printf("caProduct not match\n");#endif continue; } /* WE WIN! */ break; } if (product) { assert(product->producer == this); assert(product->obType == ObType::PtMappingPage); }#if 0 if (wi.segBlss != wi.pSegKey->GetBlss()) dprintf(true, "Found product 0x%x segBlss %d prodKey 0x%x keyBlss %d\n", product, wi.segBlss, wi.pSegKey, wi.pSegKey->GetBlss());#endif#ifdef FINDPRODUCT_VERBOSE printf("0x%08x->FindProduct(blss=%d,ndx=%d,rw=%c,ca=%c," "producerTy=%d) => 0x%08x\n", this, blss, ndx, rw ? 'y' : 'n', ca ? 'y' : 'n', obType, product);#endif return product;}voidObjectHeader::AddProduct(ObjectHeader* product){ product->next = products; product->producer = this; products = product;}voidObjectHeader::DelProduct(ObjectHeader* product){ assert (product->producer == this); if (products == product) { products = product->next; } else { ObjectHeader *curProd = products; while (curProd->next) { if (curProd->next == product) { curProd->next = product->next; break; } curProd = curProd->next; } } product->next = 0; product->producer = 0;}#if 0voidObjectHeader::DoCopyOnWrite(){ assert (obType > ObType::NtLAST_NODE_TYPE);#if 0 dprintf(true, "Trying copy on write, ty %d oid 0x%08x%08x " "hdr 0x%08x\n", obType, (uint32_t) (oid >> 32), (uint32_t) (oid), this);#endif assert(GetFlags(OFLG_CKPT) && IsDirty()); ObjectHeader *pObj = ObjectCache::GrabPageFrame(); assert (pObj->kr.IsEmpty()); kva_t from = ObjectCache::ObHdrToPage(this); kva_t to = ObjectCache::ObHdrToPage(pObj); /* Copy the page data */ bcopy((const void *)from, (void *)to, EROS_PAGE_SIZE); /* FIX -- the header needs to be copied with care -- perhaps this * should be expanded in more explicit form? */ /* And the object header: */ bcopy(this, pObj, sizeof(ObjectHeader)); /* The key ring needs to be reset following the header bcopy */ pObj->kr.ResetRing(); /* Because the original may already be queued up for I/O, the copy * has to become the new version. This poses a problem: we may have * gotten here trying to mark an object dirty to satisfy a write * fault, in which event there are very likely outstanding prepared * capabilities to this object sitting on the stack somewhere. In * all such cases the object being copied will be pinned. If the * object being copied is pinned we Yield(), which will force the * whole chain of events to be re-executed, this time arriving at * the correct object. */ /* NOTE About the 'dirty' bit -- which I have 'fixed' twice now to * my regret. It really should be zero. We are only running this * code if the object was marked ckpt. In that event, the * checkpointed version of the object is dirty until flushed, but * the COW'd version of the object is not dirty w.r.t the next * checkpoint until something happens along to try and dirty it. We * are here because someone is trying to do that, but we must let * MakeObjectDirty() handle the marking rather than do it here. The * prolem is that we haven't reserved a directory entry for the * object. This can (and probably should) be resolved by calling * RegisterDirtyObject() from here to avoid the extra Yield(), but * for now be lazy, since I know that will actually work. */ assert(kernPin == 0); ClearFlags(OFLG_CURRENT); pObj->SetFlags(OFLG_CURRENT); pObj->ClearFlags(OFLG_CKPT|OFLG_IO|OFLG_DIRTY|OFLG_REDIRTY|OFLG_PIN);#ifdef DBG_CLEAN printf("Object 0x%08x ty %d oid=0x%08x%08x COW copy cleaned\n", pObj, pObj->obType, (uint32_t) (pObj->oid >> 32), (uint32_t) pObj->oid);#endif pObj->SetFlags(GetFlags(OFLG_DISKCAPS)); pObj->ioCount = 0; pObj->userPin = 0; pObj->prstPin = 0;#ifdef OPTION_OB_MOD_CHECK pObj->check = pObj->CalcCheck();#endif /* Switch the keyring to the new object, and update all of the keys * to point to the copy: */ kr.ObjectMoved(pObj); Unintern(); /* take us out of the hash chain */ pObj->Intern(); /* and put the copy in in our place. */ /* we must now re-insert the old page as a log page, because the new * page might conceivably get aged out before the old page, at which * point we would find the wrong one. */ #ifdef DBG_WILD_PTR if (dbg_wild_ptr) Check::Consistency("Bottom DoCopyOnWrite()");#endif /* Since we may have come here by way of the page fault code, we are * now forced to Yield(), because there are almost certainly * outstanding pointers to this object on the stack: */ Thread::Current()->Yield();}#endifvoidObjectHeader::FlushIfCkpt(){#ifdef OPTION_PERSISTENT#error "This needs an implementation." /* If this page is involved in checkpointing, run the COW logic. */ if (GetFlags(OFLG_CKPT) && IsDirty()) { assert (IsFree() == false); if (obType <= ObType::NtLAST_NODE_TYPE) { Checkpoint::WriteNodeToLog((Node *) this); assert (!IsDirty()); } else Persist::WritePage(this, true); }#else assert(!GetFlags(OFLG_CKPT));#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -