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

📄 kern_key.cxx

📁 C++ 编写的EROS RTOS
💻 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 <disk/DiskKey.hxx>#include <kerninc/Check.hxx>#include <kerninc/Process.hxx>#include <kerninc/Thread.hxx>#include <kerninc/Node.hxx>#include <kerninc/ObjectCache.hxx>#include <kerninc/util.h>#include <kerninc/StackTester.hxx>#include <kerninc/ObjectSource.hxx>#include <eros/SysTraceKey.h>#define dbg_prepare	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)ObjectHeader *Key::GetObjectPtr() const{  assert( IsPreparedObjectKey() );  if (IsGateKey())    return gk.pContext->procRoot;  else    return ok.pObj;}OIDKey::GetKeyOid() const{  assert (IsObjectKey());    if ( IsPreparedObjectKey() )    return GetObjectPtr()->ob.oid;  return unprep.oid;}uint32_tKey::GetAllocCount() const{  assert (GetType() > LAST_GATE_KEYTYPE);  assert (GetType() <= LAST_OBJECT_KEYTYPE);    if ( IsPreparedObjectKey() )    return GetObjectPtr()->ob.allocCount;  return unprep.count;}Key Key::VoidKey;	/* default constructor *//* NOTE: if we are running OB_MOD_CHECK, the key prepare logic does an * incremental recomputation on the check field in the containing object. */voidKey::DoPrepare(){  assert( IsUnprepared() );    assert ( NeedsPrepare() );  KernStats.nKeyPrep++;  #ifdef TEST_STACK  StackTester st;#endif #if 0  if (ktByte > UNPREPARED(LAST_PREPARED_KEYTYPE))    return;#endif#ifdef MEM_OB_CHECK  uint32_t ck = CalcCheck();#endif      ObjectHeader *pObj = 0;    switch(GetType()) {		/* not prepared, so not hazarded! */  case KT_Resume:  case KT_Start:    {      /* Gate keys are linked onto the context structure.  First, we       * need to validate the key:       */      Process * context = 0;      Node *pNode = (Node *) 	ObjectCache::GetObject(unprep.oid, ObType::NtUnprepared,			       unprep.count,			       IsType(KT_Resume) ? false : true);      if (IsType(KT_Resume) && pNode->callCount != unprep.count)	pNode = 0;      if (pNode == 0) {	DEBUG(prepare)	  printf("Voiding invalid gate key\n");	assert ( IsHazard() == false );	assert ( IsUnprepared() );	/* key was not prepared, so cannot be hazarded */	KS_RescindKey();	return;      }	      assertex(pNode, ObjectCache::ValidNodePtr(pNode));            pNode->TransLock();            context = pNode->GetDomainContext();      if (! context )		/* malformed domain */	fatal("Preparing gate key to malformed domain\n");      /* Okay, we prepared successfully. */      gk.pContext = context;      /* Link into context chain on left or right according to key       * type.       */      if ( IsType(KT_Resume) ) {	gk.prev = context->kr.prev;	gk.prev->next = (KeyRing *) this;	context->kr.prev = (KeyRing *) this;	gk.next = (KeyRing*) &context->kr;      }      else {	gk.next = context->kr.next;	gk.next->prev = (KeyRing *) this;	context->kr.next = (KeyRing *) this;	gk.prev = (KeyRing*) &context->kr;      }      SetPrepared();#if 0      printf("Prepared key ");      Print();#endif  #ifdef MEM_OB_CHECK      assert(ck == CalcCheck());#endif    #ifdef DBG_WILD_PTR      if (dbg_wild_ptr)	Check::Consistency("In Key::DoPrepare()");#endif#ifdef TEST_STACK      st.check();#endif      return;    }  case KT_Page:    {      pObj = ObjectCache::GetObject(unprep.oid, ObType::PtDataPage, 				    unprep.count, true);      if (pObj)	assertex(this, ObjectCache::ValidPagePtr(pObj));      break;    }      case KT_Node:  case KT_Segment:  case KT_Process:#ifdef KT_Wrapper  case KT_Wrapper:#endif    pObj = ObjectCache::GetObject(unprep.oid, ObType::NtUnprepared, 				  unprep.count, true);    break;  default:    SetPrepared();    return;  }    if (pObj == 0) {    DEBUG(prepare)      dprintf(true, "Voiding invalid key\n");    assert ( IsHazard() == false );    assert ( IsUnprepared() );    NH_RescindKey();#ifdef TEST_STACK    st.check();#endif    return;  }  /* It's definitely an object key.  Pin the object it names. */  pObj->TransLock();    /* Link as next key after object */  ok.pObj = pObj;    ok.next = pObj->kr.next;  ok.prev = (KeyRing *) pObj;    pObj->kr.next = (KeyRing*) this;  ok.next->prev = (KeyRing*) this;#ifdef MEM_OB_CHECK  assert(ck == CalcCheck());#endif      SetPrepared();#if 0  printf("Prepared key ");  Print();#endif#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("End Key::DoPrepare()");#endif#ifdef TEST_STACK  st.check();#endif  return;}#ifndef NDEBUGvoidKey::Prepare(){  extern bool InvocationCommitted;  assert (InvocationCommitted == false);  if (IsUnprepared())    DoPrepare();        if ( NeedsPin() )    ok.pObj->TransLock();}#endifboolKey::Prepare(KeyType ty){#ifndef NDEBUG  extern bool InvocationCommitted;#endif  assert (InvocationCommitted == false);  /* printf("Key::Prepare(ty) -- want ty %d\n", ty); */  if (IsType(ty) == false) {    Print();    fatal("Key::Prepare(kt) -- wrong keytype 0x%x (wanted 0x%x)\n",		  GetType(), ty);    return false;  }  if (NeedsPrepare())    DoPrepare();  if (NeedsPin())    ok.pObj->TransLock();    if (IsType(KT_Number) && (ty != KT_Number)) {    printf("Key::Prepare(ty) -- number key. Key rescinded?\n");    return false;  }  return true;}#define CAP_REGMOVE#ifdef CAP_REGMOVE/* save_key(from, to) -- given a key address /from/ that is within a * capability register, copy that key to the key address /to/, which * is a slot in a capability page. *  * Note that all functions called by save_key() are prompt and do not * yield.  This is important, as we are running on an interrupt stack. */extern "C" {  void copy_key(Key *fromKeyReg, Key *toKeyReg);  void xchg_key(Key *kr0, Key *kr1);}voidcopy_key(Key *from, Key *to){  if (to == &Thread::CurContext()->keyReg[0])    return;    /* Do not bother to deprepare dest key, as it isn't going to disk as   * a result of this operation.   */  to->NH_Set(*from);}voidxchg_key(Key *cr0, Key *cr1){  Key tmp;  tmp.NH_Set(*cr0);  if (cr0 != &Thread::CurContext()->keyReg[0]) {    cr0->NH_Set(*cr1);  }  if (cr1 != &Thread::CurContext()->keyReg[0]) {    cr1->NH_Set(tmp);  }    tmp.NH_Unchain();}#endif /* CAP_REGMOVE */voidKey::NH_Unprepare(){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top Key::NH_Unprepare()");#endif  /* fatal("Unprepare() called\n"); */  assert(IsHazard() == false);  if ( IsUnprepared() )    return;  if ( IsObjectKey() ) {    ObjectHeader *pObj = ok.pObj;      if ( IsGateKey() ) {#ifndef NDEBUG      extern bool ValidCtxtPtr(const Process *);      if (ValidCtxtPtr(gk.pContext) == false)	fatal("Key 0x%08x Kt %d, 0x%08x not valid ctxt ptr\n",		      this, GetType(), gk.pContext);#endif      pObj = gk.pContext->procRoot;    }#ifndef NDEBUG    if ( IsType(KT_Page) ) {      if ( ObjectCache::ValidPagePtr(pObj) == false )	fatal("Key 0x%08x Kt %d, 0x%08x not valid page ptr\n",		      this, GetType(), pObj);    }    else {      if ( ObjectCache::ValidNodePtr((Node *)pObj) == false )	fatal("Key 0x%08x Kt %d, 0x%08x not valid node ptr\n",		      this, GetType(), pObj);    }#endif    NH_Unchain();    pObj->SetFlags(OFLG_DISKCAPS);    unprep.oid = pObj->ob.oid;    if ( IsType(KT_Resume) )      unprep.count = ((Node *) pObj)->callCount;    else      unprep.count = pObj->ob.allocCount;  }  SetUnprepared();#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("End Key::NH_Unprepare()");#endif#if 0  printf("Deprepared key ");  Print();#endif}voidDiskKey::operator=(const Key& k){  assert ( k.IsValid() );  if ( k.IsPreparedObjectKey() ) {    ObjectHeader *pObj = k.ok.pObj;      if ( k.IsType(KT_Resume) || k.IsType(KT_Start) ) {#ifndef NDEBUG      extern bool ValidCtxtPtr(const Process *);      if (ValidCtxtPtr(k.gk.pContext) == false)	fatal("Kt %d, 0x%08x not valid ctxt ptr\n",		      k.GetType(),		      k.gk.pContext);#endif      pObj = k.gk.pContext->procRoot;    }#ifndef NDEBUG    if ( k.IsType(KT_Page) ) {      if ( ObjectCache::ValidPagePtr(pObj) == false )	fatal("Kt %d, 0x%08x not valid page ptr\n", k.GetType(),		      pObj);    }    else {      if ( ObjectCache::ValidNodePtr((Node *)pObj) == false )	fatal("Kt %d, 0x%08x not valid node ptr\n", k.GetType(),		      pObj);    }#endif    keyType = k.keyType;    keyFlags = k.keyFlags & ~KFL_HAZARD_BITS;    keyData = k.keyData;    SetUnprepared();        if ( k.IsType(KT_Resume) )      unprep.count = ((Node *) pObj)->callCount;    else      unprep.count = pObj->ob.allocCount;    unprep.oid = pObj->ob.oid;    pObj->SetFlags(OFLG_DISKCAPS);  }  else {    keyType = k.keyType;    keyFlags = k.keyFlags & ~KFL_HAZARD_BITS;    keyData = k.keyData;    SetUnprepared();    nk.value[0] = k.nk.value[0];    nk.value[1] = k.nk.value[1];    nk.value[2] = k.nk.value[2];  }}voidKey::Print() const{  uint32_t * pWKey = (uint32_t *) this;  if ( IsPreparedObjectKey() ) {    ObjectHeader * pObj = GetObjectPtr();        uint32_t * pOID = (uint32_t *) &pObj->ob.oid;    if (IsType(KT_Resume)) {#if 0      printf("rsm 0x%08x 0x%08x 0x%08x 0x%08x (obj=0x%08x)\n",		     pWKey[0], ((Node *)pObj)->callCount,		     pOID[0], pOID[1], pObj);      #else      printf("0x%08x rsm 0x%08x 0x%08x 0x%08x 0x%08x\n",		     this,		     pWKey[0], ((Node *)pObj)->callCount,		     pOID[0], pOID[1]);#endif    }    else {#if 0      printf("pob 0x%08x 0x%08x 0x%08x 0x%08x (obj=0x%08x)\n",		     pWKey[0], ok.pObj->allocCount,		     pOID[0], pOID[1], pObj);#else      printf("0x%08x pob 0x%08x 0x%08x 0x%08x 0x%08x\n",		     this,		     pWKey[0], ((Node *)pObj)->ob.allocCount,		     pOID[0], pOID[1]);#endif    }  }  else {#if 0    printf("ukt 0x%08x 0x%08x 0x%08x 0x%08x\n",		   pWKey[0], pWKey[1], pWKey[2], pWKey[3]);#else    printf("0x%08x ukt 0x%08x 0x%08x 0x%08x 0x%08x\n",		   this,		   pWKey[0], pWKey[1], pWKey[2], pWKey[3]);#endif  }}#ifdef OPTION_OB_MOD_CHECKuint32_tKey::CalcCheck(){  uint32_t ck = 0;  assert(this);  uint32_t *pWKey = (uint32_t *) this;  /* mask out prepared, hazard bits! */  uint32_t saveFirstWord = pWKey[0];  keyFlags &= ~KFL_ALL_FLAG_BITS;  ck ^= pWKey[0];  *pWKey = saveFirstWord;  if ( IsPreparedObjectKey() ) {    if (IsType(KT_Resume)) {      /* Inject the checksum for a void key instead so that       * zapping them won't change the checksum:       */      ck = VoidKey.CalcCheck();    }    else if (IsType(KT_Start)) {      /* This pointer hack is simply so that I don't have to remember       * machine specific layout conventions for long long       */          Node *pDomain = gk.pContext->procRoot;            ck ^= pDomain->ob.allocCount;      uint32_t * pOID = (uint32_t *) &pDomain->ob.oid;      ck ^= pOID[0];      ck ^= pOID[1];    }    else {      /* This pointer hack is simply so that I don't have to remember       * machine specific layout conventions for long long       */          ck ^= ok.pObj->ob.allocCount;      uint32_t * pOID = (uint32_t *) &ok.pObj->ob.oid;      ck ^= pOID[0];      ck ^= pOID[1];    }  }  else {    ck ^= pWKey[1];    ck ^= pWKey[2];    ck ^= pWKey[3];  }    return ck;}#endif/* New Key -- make it void, since in a couple of cases we do this on * the stack and there is no telling what garbage bits are sitting there. */Key::Key(){  KS_VoidInitKey();}#ifndef NDEBUGboolKey::IsValid() const{  if ( IsMiscKey() ) {    if (nk.value[0] || nk.value[1] || nk.value[2])      return false;  }#if defined(DBG_WILD_PTR)  /* Following is a debugging-only check. */  if (IsObjectKey() && GetKeyOid() > 0x100000000llu) {    OID oid = GetKeyOid();        printf("Key 0x%08x has invalid OID 0x%08x%08x\n",		   this, (uint32_t) (oid>>32), (uint32_t) oid);  }#endif        if ( IsPreparedObjectKey() ) {    extern bool ValidCtxtPtr(const Process *);    extern bool ValidCtxtKeyRingPtr(const KeyRing *);	#ifndef NDEBUG    if ( IsGateKey() ) {      Process *ctxt = gk.pContext;      if (ValidCtxtPtr(ctxt) == false)	return false;    }    else if ( IsType(KT_Page) ) {      ObjectHeader *pObject = ok.pObj;      if ( ObjectCache::ValidPagePtr(pObject) == false ) {	Print();	printf("Key 0x%08x has invalid pObject 0x%08x\n",		       this, pObject);	return false;      }      if ( pObject->IsFree() ) {	Print();	printf("Prepared key 0x%08x names free pObject 0x%08x\n",		       this, pObject);	return false;      }    }    else {      assertex (this, IsObjectKey() );      Node *pNode = (Node *) ok.pObj;      if ( ObjectCache::ValidNodePtr(pNode) == false ) {	printf("0x%x is not a valid node ptr\n", pNode);	return false;      }      if ( pNode->IsFree() ) {	Print();	printf("Prepared key 0x%08x names free pObject 0x%08x\n",		       this, pNode);	return false;      }    }#endif    if ( IsObjectKey() ) {      /* KeyRing pointers must either point to key slots or to       * object root.       */#ifndef NDEBUG      KeyRing * krn = ok.next;      KeyRing * krp = ok.prev;      if ( ! ( ObjectCache::ValidKeyPtr((Key *) krn) ||	       ObjectCache::ValidPagePtr((ObjectHeader*) krn) ||	       ObjectCache::ValidNodePtr((Node *) krn) ||	       ValidCtxtKeyRingPtr(krn) ) ) {	printf("key 0x%x nxt key 0x%x bogus\n", this, krn);	return false;      }            if ( ! ( ObjectCache::ValidKeyPtr((Key *) krp) ||	       ObjectCache::ValidPagePtr((ObjectHeader *) krp) ||	       ObjectCache::ValidNodePtr((Node *) krp) ||	       ValidCtxtKeyRingPtr(krp) ) ) {	printf("key 0x%x prv key 0x%x bogus\n", this, krp);	return false;      }      /* Prev and next pointers must be linked properly: */      if (krp->next != (KeyRing *) this) {	printf("Prepared key 0x%08x bad keyring links to prev\n",		       this);	return false;      }      if (krn->prev != (KeyRing *) this) {	printf("Prepared key 0x%08x bad keyring links to next\n",		       this);	return false;      }#endif    }  }  return true;}#endif

⌨️ 快捷键说明

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