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

📄 pk_processkey.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 <kerninc/Key.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Node.hxx>#include <kerninc/Process.hxx>#include <kerninc/Thread.hxx>#include <kerninc/CpuReserve.hxx>#include <eros/Invoke.h>#include <eros/StdKeyType.h>#include <eros/ProcessKey.h>#include <eros/machine/Registers.h>/* #define DEBUG */voidMaybeRepairCpuReserveLinkages(Node *theNode, CpuReserve* oldReserve,			      const Key &newKey) {  /* We may have just changed the reserve of a domain.   * Unfortunately, reserve pointers are kept in the thread   * structure.  We only need to check if the previous key was a   * schedule key.  If so, the thread we want (if any) is   * somewhere on the thread chain of the old reserve, else it   * doesn't exist.   */  Thread *pThrd = 0;#ifdef DEBUG	  printf("Hunting down threads for cpuReserve %d (0x%08x)\n",		 oldKey.subType, oldReserve);#endif  Link *tlnk = oldReserve->threadChain.next;  while (tlnk) {    Thread *lThrd = Thread::ThreadFromCpuReserveLinkage(tlnk);#ifdef DEBUG    printf("Examine thread 0x%08x (tlnk 0x%08x)\n", lThrd, tlnk);#endif        if ( lThrd->IsUser() ) {      if (lThrd->context) {	if ( ((Process *) lThrd->context)->procRoot == theNode ) {	  pThrd = lThrd;	  break;	}      }      else if (lThrd->processKey.GetKeyOid() == theNode->ob.oid) {	pThrd = lThrd;	break;      }    }    tlnk = tlnk->next;  }#ifdef DEBUG  printf("Found thread 0x%08x\n", pThrd);#endif  if (pThrd) {    if ( newKey.IsType(KT_Sched) ) {      CpuReserve& newCpuReserve = CpuReserve::GetReserve(newKey);      newCpuReserve.AddUserThread(pThrd);    }    else {      pThrd->Unlink();		/* in case sleeping somewhere */      pThrd->MigrateTo(0);    }  }}voidProcessKey(Invocation& inv){  Node *theNode = (Node *) inv.key->GetObjectPtr();  if (inv.invokee && theNode == inv.invokee->procRoot      && OC_Process_Swap == inv.entry.code      && inv.entry.w1 != 2      && inv.entry.w1 != 4)    dprintf(true, "Modifying invokee domain root\n");  if (inv.invokee && theNode == inv.invokee->keysNode      && OC_Process_SwapKeyReg == inv.entry.code)    dprintf(true, "Modifying invokee keys node\n");  switch (inv.entry.code) {  case OC_KeyType:    {      COMMIT_POINT();      inv.exit.code = RC_OK;      inv.exit.w1 = AKT_Process;      return;    }  case OC_Process_Copy:    {      uint32_t slot = inv.entry.w1;      COMMIT_POINT();      if (slot >= EROS_NODE_SIZE)	dprintf(true, "Copy slot out of range\n");      if (slot == ProcBrand || slot >= EROS_NODE_SIZE) {	inv.exit.code = RC_RequestError;	return;      }      /* All of these complete ok. */      inv.exit.code = RC_OK;            if ((*theNode)[slot].IsRdHazard())	theNode->ClearHazard(slot);      inv.SetExitKey(0, theNode->slot[slot]);      return;    }        case OC_Process_Swap:    {      if (theNode == Thread::CurContext()->keysNode)	dprintf(true, "Swap involving sender keys\n");      uint32_t slot = inv.entry.w1;      if (slot == ProcBrand || slot >= EROS_NODE_SIZE) {	COMMIT_POINT();	inv.exit.code = RC_RequestError;	return;      }      /* All of these complete ok. */      inv.exit.code = RC_OK;            theNode->MakeObjectDirty();      COMMIT_POINT();            theNode->ClearHazard(slot);      CpuReserve *oldReserve = 0;      if ( slot == ProcSched && theNode->slot[slot].IsType(KT_Sched) )	oldReserve = &CpuReserve::GetReserve(theNode->slot[slot]);	      {	Key k;			/* temporary in case send and receive */				/* slots are the same. */	k.IKS_Set(theNode->slot[slot]);		(*theNode)[slot].NH_Set(*inv.entry.key[0]);	inv.SetExitKey(0, k);	/* Unchain, but do not unprepare -- the objects do not have	 * on-disk keys. 	 */	k.NH_Unchain();      }      if (oldReserve)	MaybeRepairCpuReserveLinkages(theNode, oldReserve,				      theNode->slot[slot]);            Thread::Current()->Prepare();      inv.nextPC = ((Process *) Thread::CurContext())->GetPC();            return;    }        case OC_Process_CopyKeyReg:    {      Process* ac = theNode->GetDomainContext();      ac->Prepare();      COMMIT_POINT();      uint32_t slot = inv.entry.w1;      if (slot < EROS_NODE_SIZE) {	inv.SetExitKey(0, ac->keyReg[slot]);	inv.exit.code = RC_OK;      }      else {	inv.exit.code = RC_RequestError;      }      return;    }  case OC_Process_SwapKeyReg:    {      if (theNode == Thread::CurContext()->keysNode)	dprintf(true, "Swap involving sender keys\n");      Process* ac = theNode->GetDomainContext();      ac->Prepare();      COMMIT_POINT();      uint32_t slot = inv.entry.w1;      if (slot >= EROS_NODE_SIZE) {	inv.exit.code = RC_RequestError;	return;      }      inv.SetExitKey(0, ac->keyReg[slot]);      if (slot != 0) {	/* FIX: verify that the damn thing HAD key registers?? */	ac->keyReg[slot].NH_Set(*inv.entry.key[0]);#if 0	printf("set key reg slot %d to \n", slot);	inv.entry.key[0].Print();#endif      }      inv.exit.code = RC_OK;      return;    }#if 0  case OC_Process_GetCtrlInfo32:    {      DomCtlInfo32_s info;      Node *domRoot = (Node *) inv.key->GetObjectPtr();            inv.exit.code = RC_OK;      ArchContext* ac = domRoot->GetDomainContext();      ac->Prepare();            COMMIT_POINT();            if (ac->GetControlInfo32(info) == false)	inv.exit.code = RC_Process_Malformed;      inv.CopyOut(sizeof(info), &info);      return;    }#endif      case OC_Process_GetRegs32:    {      Registers regs;            /* GetRegs32 length is machine specific, so it does its own copyout. */      inv.exit.code = RC_OK;      assert( inv.invokee->IsRunnable() );#if 0      printf("GetRegs32: invokee is 0x%08x, IsActive? %c\n",		     inv.invokee, inv.IsActive() ? 'y' : 'n');#endif      Process* ac = theNode->GetDomainContext();      ac->Prepare();#ifndef OPTION_PURE_EXIT_STRINGS      inv.invokee->SetupExitString(inv, sizeof(regs));#endif      COMMIT_POINT();            if (ac->GetRegs32(regs) == false)	inv.exit.code = RC_Process_Malformed;      inv.CopyOut(sizeof(regs), &regs);      return;    }#if 0      case OC_Process_SetCtrlInfo32:    {      DomCtlInfo32_s info;      if ( inv.entry.len != sizeof(info) ) {	inv.exit.code = RC_RequestError;	COMMIT_POINT();      	return;      }            inv.exit.code = RC_OK;      ArchContext* ac = theNode->GetDomainContext();      ac->Prepare();      #ifndef OPTION_PURE_ENTRY_STRINGS      Thread::CurContext()->SetupEntryString(inv);#endif      COMMIT_POINT();      inv.CopyIn(sizeof(info), &info);      if (ac->SetControlInfo32(info) == false)	inv.exit.code = RC_Process_Malformed;      return;    }#endif    case OC_Process_SetRegs32:    {      Registers regs;            if ( inv.entry.len != sizeof(regs) ) {	inv.exit.code = RC_RequestError;	COMMIT_POINT();      	return;      }            /* FIX: check embedded length and arch type! */            /* GetRegs32 length is machine specific, so it does its own copyout. */      inv.exit.code = RC_OK;      Process* ac = theNode->GetDomainContext();      ac->Prepare();#ifndef OPTION_PURE_ENTRY_STRINGS      Thread::CurContext()->SetupEntryString(inv);#endif      COMMIT_POINT();      inv.CopyIn(sizeof(regs), &regs);      if (ac->SetRegs32(regs) == false)	inv.exit.code = RC_Process_Malformed;      return;    }  case OC_Process_SwapMemory32:    {      inv.exit.w1 = inv.entry.w1;      inv.exit.w2 = inv.entry.w2;      inv.exit.w3 = inv.entry.w3;            /* All of these complete ok. */      inv.exit.code = RC_OK;            Process* ac = theNode->GetDomainContext();      ac->Prepare();      COMMIT_POINT();      ac->SetPC(inv.entry.w1);            theNode->ClearHazard(ProcAddrSpace);      {	Key k;	k.IKS_Set(theNode->slot[ProcAddrSpace]);		(*theNode)[ProcAddrSpace].NH_Set(*inv.entry.key[0]);	inv.SetExitKey(0, k);	/* Unchain, but do not unprepare -- the objects do not have	 * on-disk keys. 	 */	k.NH_Unchain();      }      inv.nextPC = ((Process *) Thread::CurContext())->GetPC();      return;    }  case OC_Process_MkStartKey:    {      Process* p = theNode->GetDomainContext();      p->Prepare();      COMMIT_POINT();            uint32_t keyData = inv.entry.w1;            if ( keyData > EROS_KEYDATA_MAX ) {	inv.exit.code = RC_RequestError;	dprintf(true, "Value 0x%08x is out of range\n",	keyData);      	return;      }      /* All of these complete ok. */      inv.exit.code = RC_OK;            /* AAARRRGGGGGHHHH!!!!! This used to fabricate an unprepared       * key, which was making things REALLY slow.  We do need to be       * careful, as gate keys do not go on the same key chain as       * domain keys.  Still, it was just never THAT hard to get it       * right.  Grumble.       */            if (inv.exit.pKey[0]) {	Key &k = *inv.exit.pKey[0];	k.IKS_Unchain();	k.InitType(KT_Start);	k.keyData = keyData;	k.gk.pContext = p;	k.gk.next = p->kr.next;	k.gk.next->prev = (KeyRing *) &k;	p->kr.next = (KeyRing *) &k;	k.gk.prev = &p->kr;	k.SetPrepared();      }      return;    }  /* I'm holding off on these because they require killing the   * active thread, and I want to make sure I do that when I'm awake.   */  case OC_Process_MkProcessAvailable:  case OC_Process_MkProcessWaiting:    COMMIT_POINT();    inv.exit.code = RC_UnknownRequest;    return;  case OC_Process_MkResumeKey:  case OC_Process_MkFaultKey:    COMMIT_POINT();          inv.SetExitKey(0, *inv.key);    if (inv.exit.pKey[0]) {      inv.exit.pKey[0]->NH_Unprepare();      inv.exit.pKey[0]->InitType(KT_Resume);      inv.exit.pKey[0]->keyData =	(inv.entry.code == OC_Process_MkResumeKey) ? KsitResume : KsitFault;    }    inv.exit.code = RC_OK;    return;  case OC_Process_GetFloatRegs:  case OC_Process_SetFloatRegs:    COMMIT_POINT();          fatal("Domain key order %d ot yet implemented\n",		  inv.entry.code);      default:    COMMIT_POINT();          inv.exit.code = RC_UnknownRequest;    return;  }}

⌨️ 快捷键说明

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