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

📄 kern_keyring.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/KeyRing.hxx>#include <kerninc/Check.hxx>#include <kerninc/Key.hxx>#include <kerninc/Node.hxx>#include <kerninc/Thread.hxx>#include <kerninc/ObjectCache.hxx>#include <kerninc/Invocation.hxx>voidKeyRing::RescindAll(bool mustUnprepare){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top RescindAll");#endif#ifndef NDEBUG  if (IsValid(this) == false)    dprintf(true, "Keyring 0x%08x is invalid\n");#endif    while (next != (KeyRing*) this) {    Key *pKey = (Key *) next;#ifndef NDEBUG    if ( ObjectCache::ValidKeyPtr(pKey)  == false ) {      pKey->Print();      fatal("Invalid keyring ptr. Ring=0x%08x pKey=0x%08x\n",		    this, pKey);    }    if ( pKey->IsPreparedObjectKey() == false)      pKey->Print();    assert ( pKey->IsPreparedObjectKey() );#endif    #ifndef NDEBUG    /* Following works fine for gate keys too - representation pun! */    KeyRing *nxt = pKey->ok.next;#endif    /* Note that thread-embodied and process-embodied keys are never     * hazarded:     */    if ( pKey->IsHazard() ) {      assert ( Thread::IsThreadKey(pKey) == false );      assert ( Process::IsKeyReg(pKey) == false );      Node *pNode = ObjectCache::ContainingNode(pKey);      assert ( ObjectCache::ValidNodePtr(pNode) );      uint32_t slot = pKey - pNode->slot;      pNode->RescindHazardedSlot(slot, mustUnprepare);      /* Having cleared the hazard, the key we are presently examining 	 may not even be on this ring any more -- it may be a	 different key entirely.  We therefore restart the loop. */      if (pKey->IsUnprepared())	continue;    }    else {      assert (pKey->IsHazard() == false);      assert ( pKey->IsPreparedObjectKey() );      /* hazard has been cleared, if any */      if (mustUnprepare) {	pKey->NH_Unprepare();      }      else {	/* Note that we do NOT mark the object dirty.  If the object is	 * already dirty, then it will go out to disk with the key	 * zeroed.  Otherwise, the key will be stale when the node is	 * re-read, and will be zeroed on preparation.	 */	pKey->NH_RescindKey();		assert (nxt == next);      }    }    /* If the rescinded key is in a thread that is currently running,     * we cannot delete the thread.  The current domain may be     * committing sepuku, but it might be the case that the domain has     * contrived to return to someone else, and the *thread* will     * therefore survive. [See: there *is* an afterlife!] This can     * happen when the currently running domain calls "destroy this     * node and return to fred" where "this node" is the domain root     * of the currently running domain. Buggered completely, but in     * principle this can happen.     *      * Rather than test for that case, which is not MP compatible,     * simply wake up the thread.  If the thread is already awake no     * harm will ensue.  If the thread was asleep, we will attempt to     * run it, discover its demise, and that will be the end of it.     */    if (Thread::IsThreadKey(pKey)) {      Thread *containingThread = Thread::ContainingThread(pKey);      assert(containingThread);      Process *pContext = containingThread->context;      if (pContext) {	/* The key within the thread may not be current.  I learned	 * the hard way that it is possible for a live thread to have	 * a prepared key to the thing being destroyed -- it was	 * triggered by DCC.  This was hard to debug, as printing out	 * the thread caused the key to be deprepared.	 */	/* If the thread key is prepared, then the context is loaded,	 * which means we can rely on a valid domain root pointer:	 */	assert( pContext->procRoot );	assert ( pContext->procRoot->ob.oid != pKey->GetKeyOid() );	pContext->SyncThread();	continue;      }            else	containingThread->Wakeup();    }#ifdef OPTION_OB_MOD_CHECK    if ( !(inv.IsActive() && inv.IsInvocationKey(pKey)) && 	 !Thread::IsThreadKey(pKey) &&	 !Process::IsKeyReg(pKey) ) {      Node *pNode = ObjectCache::ContainingNode(pKey);      pNode->ob.check = pNode->CalcCheck();    }#endif  }#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Bottom RescindAll()");#endif}#if 0/* This is only called from the checkpoint code, and relies utterly on * the fact that it is never called for a node. */voidKeyRing::ObjectMoved(struct ObjectHeader *newObj){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top ObjectMoved");#endif  /* Algorithm below fails if the ring is empty */  if (next == (KeyRing*) this)    return;    KeyRing *nxt = next;    while (nxt != (KeyRing*) this) {    Key *pKey = (Key *) nxt;    assert (pKey->GetType() == KT_Page);    /* We need to ensure that any outstanding dependencies on the prior     * location of this page (as occurs in page table entries) will be     * reconstructed.  Actually, once we need to do this I'm half     * tempted to just deprepare all of the keys     */        /* Note that thread-embodied and process-embodied keys are never hazarded: */    if ( pKey->IsHazard() ) {      assert ( Thread::IsThreadKey(pKey) == false );      assert ( Process::IsKeyReg(pKey) == false );      Node *pNode = ObjectCache::ContainingNode(pKey);      assert ( ObjectCache::ValidNodePtr(pNode) );      uint32_t slot = pKey - pNode->slot;      pNode->ObMovedHazardedSlot(slot);      /* Having cleared the hazard, the key we are presently examining 	 may not even be on this ring any more -- it may be a	 different key entirely.  We therefore restart the loop. */      if (pKey->IsUnprepared())	continue;    }    else {      assert (pKey->IsHazard() == false);      assert ( pKey->IsPrepared() );      pKey->ok.pObj = newObj;      nxt = pKey->ok.next;    }    #ifdef OPTION_OB_MOD_CHECK    if ( !inv.IsInvocationKey(pKey) && 	 !Thread::IsThreadKey(pKey) &&	 !Process::IsKeyReg(pKey) ) {      Node *pNode = ObjectCache::ContainingNode(pKey);      pNode->ob.check = pNode->CalcCheck();    }#endif  }  newObj->kr.next = next;  newObj->kr.prev = prev;  newObj->kr.next->prev = &newObj->kr;  newObj->kr.prev->next = &newObj->kr;      ResetRing();#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Bottom ObjectMover()");#endif}#endif#ifndef NDEBUGboolKeyRing::IsValid(const void *pObj) const{  const KeyRing *cur = this;  const KeyRing *nxt = next;    while (nxt != this) {    assert ( (Key *) nxt );    if ( ! ObjectCache::ValidKeyPtr((Key *) nxt) ) {      dprintf(true, "Key 0x%08x is not valid in keyring 0x%08x\n",		    nxt, this);      return false;    }    if ( ((Key*)nxt)->IsUnprepared() ) {      dprintf(true, "Key 0x%08x is unprepared in keyring 0x%08x (cur 0x%08x)\n",		    nxt, this, cur);      return false;    }        if ( ((Key*)nxt)->IsPreparedObjectKey() == false) {      dprintf(true, "Key 0x%08x is not object key in keyring 0x%08x\n",		    nxt, this);      return false;    }        if (nxt->prev != cur) {      dprintf(true, "Prev of key 0x%08x is not cur in keyring 0x%08x (cur=0x%08x\n",		    nxt, this, cur);      return false;    }        if (cur->next != nxt) {      dprintf(true, "Next of key 0x%08x is not nxt in keyring 0x%08x\n",		    nxt, this);      return false;    }    if (((Key *)nxt)->ok.pObj!=pObj) {      dprintf(false,		      "nxt->ok.pObj=0x%08x pObj=0x%08x nxt=0x%08x\n",		      ((Key *)nxt)->ok.pObj, pObj, nxt);      return false;    }    cur = nxt;    nxt = nxt->next;  }  return true;}#endifboolKeyRing::HasResumeKeys() const{  const Key *pKey = (Key *) prev;    if ( pKey->IsPreparedResumeKey() )    return true;  return false;}voidKeyRing::ZapResumeKeys(){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top ZapResumeKeys");#endif  Key *pKey = (Key *) prev;  /* Prepared resume keys are never in a thread, so we do not need to   * check for that.  They cksum as zero, so we do not need to   * recompute the checksum.   *    * It used to be that they were never hazarded, but this is no   * longer true -- if a resume key is sitting in a key register that   * gets loaded into a process context it can become hazarded.  Note,   * however that this is the ONLY case in which a resume key can be   * hazarded, and in that case we are going to zap the copy in the   * context anyway, so it is okay to bash them both.  The catch   * (there is ALWAYS a catch) is that we must preserve the hazard   * bits correctly.   */    while ( prev != this && pKey->IsPreparedResumeKey() ) {#ifndef NDEBUG    if (pKey->IsHazard()) {      Node *pNode = ObjectCache::ContainingNode(pKey);      assert (pNode->obType == ObType::NtKeyRegs);    }#endif        uint8_t oflags = pKey->keyFlags & KFL_HAZARD_BITS;    prev = pKey->ok.prev;    /* We use KS_VoidInitKey here rather than KS_RescindKey     * to avoid doing unnecessary unchains.     * We patch the key chain at the bottom of the loop.     */        /* Note that we do NOT mark the object dirty.  If the object is     * already dirty, then it will go out to disk with the key     * voided.  Otherwise, the key will be stale when the node is     * re-read, and will be voided on preparation.     */    pKey->KS_VoidInitKey();    pKey->keyFlags = oflags;    pKey = (Key *) prev;  }  /* The following is a no-op if there is no resume key, and necessary   * to patch the chain if there is.   */  pKey->ok.next = (KeyRing*) this;#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Bottom ZapResumeKeys()");#endif}voidKeyRing::UnprepareAll(){#ifndef NDEBUG  if (IsValid(this) == false)    dprintf(true, "Keyring 0x%08x is invalid\n");#endif    while (next != (KeyRing*) this) {    Key *pKey = (Key *) next;#ifndef NDEBUG    if ( ObjectCache::ValidKeyPtr(pKey)  == false ) {      pKey->Print();      fatal("Invalid keyring ptr. Ring=0x%08x pKey=0x%08x\n",		    this, pKey);    }    if ( pKey->IsPrepared() == false)      pKey->Print();    assert ( pKey->IsPreparedObjectKey() );#endif    #ifndef NDEBUG    /* Following works fine for gate keys too - representation pun! */    KeyRing *nxt = pKey->ok.next;#endif#if 0    printf("UnprepareAll kr=0x%08x pKey=0x%08x *pKey=0x%08x\n",		   this, pKey, *((Word*) pKey)); #endif        if ( pKey->IsHazard() ) {      assert ( Thread::IsThreadKey(pKey) == false );      assert ( Process::IsKeyReg(pKey) == false );      Node *pNode = ObjectCache::ContainingNode(pKey);      assert ( ObjectCache::ValidNodePtr(pNode) );      uint32_t slot = pKey - pNode->slot;      pNode->UnprepareHazardedSlot(slot);      /* Having cleared the hazard, the key we are presently examining 	 may not even be on this ring any more -- it may be a	 different key entirely.  We therefore restart the loop. */      if (pKey->IsUnprepared())	continue;    }    else {      assert (pKey->IsHazard() == false);      assert ( pKey->IsPreparedObjectKey() );      /* If we are unpreparing a thread-resident key, and that thread       * has a context pointer, the key might be out of date.  It is       * perfectly okay to deprepare that key PROVIDED that we do not       * alter the thread's context pointer.  This is safe because of       * the sequence of conditions tested by Thread::IsRunnable() and       * Thread::Prepare().       */#ifndef NDEBUG      if ( pKey->ok.next != this &&	   ObjectCache::ValidKeyPtr((Key*)pKey->ok.next)  == false )	fatal("keyring 0x%08x: pKey 0x%08x w/ bad next ptr 0x%08x\n",		      this, pKey, pKey->ok.next);#endif      pKey->NH_Unprepare();#ifndef NDEBUG      if (nxt != next)	fatal("Depreparing key 0x%08x.  nxt was 0x%08x next now 0x%08x\n",		      pKey, nxt, next);#endif      assert (nxt == next);          assert ( pKey->IsUnprepared() );    }    #ifdef OPTION_OB_MOD_CHECK    if ( !(inv.IsActive() && inv.IsInvocationKey(pKey)) && 	 !Thread::IsThreadKey(pKey) &&	 !Process::IsKeyReg(pKey) ) {      Node *pNode = ObjectCache::ContainingNode(pKey);      pNode->ob.check = pNode->CalcCheck();    }#endif  }  assert ( IsEmpty() );#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Bottom UnprepareAll()");#endif}

⌨️ 快捷键说明

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