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

📄 process.hxx

📁 C++ 编写的EROS RTOS
💻 HXX
字号:
#ifndef __MACHINE_PROCESS_HXX__#define __MACHINE_PROCESS_HXX__/* * 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 <arch-kerninc/PTE.hxx>#include <eros/Invoke.h>#include <kerninc/Invocation.hxx>/* This file requires #include <kerninc/Process.hxx> *//* This file requires #include <kerninc/Thread.hxx> *//* Machine-specific helper functions for process operations: */extern PTE*proc_BuildMapping(Process* p, ula_t ula, bool forWriting, bool prompt);/* Return 0 if no mapping can be found with the desired access, * otherwise return the kernel *virtual* PAGE address containing the * virtual BYTE address uva. *  * Note that successive calls to this, after inlining, should * successfully CSE the page directory part of the computation. */inline PTE*proc_TranslatePage(Process *p, ula_t ula, uint32_t mode, bool forWriting){#ifdef OPTION_SMALL_SPACES  if (p->fixRegs.MappingTable == KERNPAGEDIR && p->smallPTE == 0)    return 0;#else  if (p->fixRegs.MappingTable == KERNPAGEDIR)    return 0;#endif    assert(p->fixRegs.MappingTable);    if (p->fixRegs.MappingTable) {    PTE* pde = (PTE*) PTOV(p->fixRegs.MappingTable);    uint32_t ndx0 = (ula >> 22) & 0x3ffu;    uint32_t ndx1 = (ula >> 12) & 0x3ffu;    pde += ndx0;    if (PTE_IS(*pde, mode)) {      if (forWriting && PTE_ISNOT(*pde, PTE_W))	goto fail;      PTE *pte = (PTE*) PTOV( (pde->AsWord() & ~EROS_PAGE_MASK) );      pte += ndx1;        if (PTE_IS(*pte, mode)) {	if (forWriting && PTE_ISNOT(*pte, PTE_W))	  goto fail;	return pte;      }    }  }fail:  return 0;}boolproc_DoPageFault(Process * p, ula_t la, bool isWrite, bool prompt);#ifndef FAST_IPC_ARG_VALIDATEinline voidProcess::ValidateEntryBlock(){  /* Check valid invocation type field + uppermost part of control field: */  if (fixRegs.invType >= 0x3)    goto bogus;  if (fixRegs.invKey >= EROS_NODE_SIZE)    goto bogus;  if (fixRegs.sndKeys & 0xe0e0e0e0u) /* high bits must be clear */    goto bogus;  if (fixRegs.invType != IT_Send && fixRegs.rcvKeys & 0xe0e0e0e0u) /* high bits must be clear */    goto bogus;  /* Check valid string len: */  if (fixRegs.sndLen > EROS_MESSAGE_LIMIT)    goto bogus;  return;bogus:  SetFault(FC_BadEntryBlock, fixRegs.EIP);  Thread::Current()->Yield();}#endifinline voidProcess::SetupEntryBlock(Invocation& inv){#ifndef FAST_IPC_ARG_VALIDATE  ValidateEntryBlock();#endif    /* Not hazarded because invocation key */  inv.key = &keyReg[fixRegs.invKey];  inv.key->Prepare();  inv.keyType = inv.key->GetType();  inv.invType = fixRegs.invType;  inv.entry.code = fixRegs.EAX;  inv.entry.w1 = fixRegs.EBX;  inv.entry.w2 = fixRegs.ECX;  inv.entry.w3 = fixRegs.EDX;  uint8_t *sndKeys = (uint8_t *) &fixRegs.sndKeys;    /* Not hazarded because invocation key */  inv.entry.key[0] = &keyReg[sndKeys[0]];  inv.entry.key[1] = &keyReg[sndKeys[1]];  inv.entry.key[2] = &keyReg[sndKeys[2]];  inv.entry.key[3] = &keyReg[sndKeys[3]];  /* Figure out the string length: */    uint32_t len = fixRegs.sndLen;  inv.entry.len = len;}inline voidProcess::SetupExitBlock(Invocation& inv){  /* NOTE THAT THIS PROCEEDS EVEN IF THE EXIT BLOCK IS INVALID!!! */    /* inv.exit.code may be overwritten by the actual key handler: */  inv.exit.code = RC_OK;  inv.exit.w1 = 0;  inv.exit.w2 = 0;  inv.exit.w3 = 0;  inv.exit.len = 0;		/* setting this twice cheaper than branch */  inv.exit.pKey[0] = 0;  inv.exit.pKey[1] = 0;  inv.exit.pKey[2] = 0;  inv.exit.pKey[3] = 0;  uint8_t *rcvKeys = (uint8_t *) &fixRegs.rcvKeys;  if (fixRegs.rcvKeys) {    if (fixRegs.rcvKeys & 0xe0e0e0e0) {      SetFault(FC_BadExitBlock, 0, false);      inv.suppressXfer = true;    }    else {      if (rcvKeys[0])	inv.exit.pKey[0] = &keyReg[rcvKeys[0]];      if (rcvKeys[1])	inv.exit.pKey[1] = &keyReg[rcvKeys[1]];      if (rcvKeys[2])	inv.exit.pKey[2] = &keyReg[rcvKeys[2]];      if (rcvKeys[3])	inv.exit.pKey[3] = &keyReg[rcvKeys[3]];    }  }  #if 0  assert(inv.exit.key[0].IsPrepared() == false);  assert(inv.exit.key[1].IsPrepared() == false);  assert(inv.exit.key[2].IsPrepared() == false);  assert(inv.exit.key[3].IsPrepared() == false);#endif#if 0  /* We do not zero the keys here any longer.  Any exit keys that were used   * by the last invocation will have been rezeroed in the post-invocation   * cleanup logic in Invocation::Cleanup(), which is careful only to   * rezero the keys that were actually touched.  That makes a   * staggeringly big difference in performance.   */    /* Not hazarded because invocation key */  inv.exit.key[0].NH_VoidKey();  inv.exit.key[1].NH_VoidKey();  inv.exit.key[2].NH_VoidKey();  inv.exit.key[3].NH_VoidKey();#endif  /* This assumes that we do not remap it into the kernel map.  Logic   * here is that we switch into the recipient address space as our   * last action.   */    if (inv.suppressXfer || this == 0) {    inv.validLen = 0;    return;  }    inv.validLen = fixRegs.ESI;  /* Should this set a fault code? */  if (inv.validLen > EROS_MESSAGE_LIMIT)    inv.validLen = EROS_MESSAGE_LIMIT;  assert( IsRunnable() );}inline voidProcess::DeliverGateResult(Invocation& inv, bool wantFault){  /* No need to call Prepare() here -- it has already been  called in   * the invocation path.   */  /* There used to be a check of IsRunnable() here.  I removed it   * because if the recipient had a bad string a fault code was   * generated in SetupExitString, and as a consequence the recipient   * is no longer runnable.  It is guaranteed, however, that such a   * short string will not impede progress.   */    uint16_t keyData = inv.key->keyData;    if (fixRegs.rcvKeys) {    if (fixRegs.rcvKeys & 0x1f1f1fu) {      if (inv.exit.pKey[0])	inv.exit.pKey[0]->NH_Set(*inv.entry.key[0]);      if (inv.exit.pKey[1])	inv.exit.pKey[1]->NH_Set(*inv.entry.key[1]);      if (inv.exit.pKey[2])	inv.exit.pKey[2]->NH_Set(*inv.entry.key[2]);    }        if (inv.exit.pKey[3]) {      if (inv.invType == IT_Call) {	Thread::CurContext()->BuildResumeKey(*inv.exit.pKey[3]);	if (wantFault)	  inv.exit.pKey[3]->keyData = KsitFault;      }      else	inv.exit.pKey[3]->NH_Set(*inv.entry.key[3]);    }  }  /* copy return code and words */  fixRegs.EAX = inv.entry.code;  fixRegs.EBX = inv.entry.w1;  fixRegs.ECX = inv.entry.w2;  fixRegs.EDX = inv.entry.w3;#ifdef DDB  /* Duplicate here so that debugger reporting is accurate. */  inv.exit.code = inv.entry.code;  inv.exit.w1 = inv.entry.w1;  inv.exit.w2 = inv.entry.w2;  inv.exit.w3 = inv.entry.w3;#endif  uint32_t rcvBase = fixRegs.EDI;    fixRegs.EDI = keyData;  /* Data has already been copied out, so don't need to copy here.  DO   * need to deliver the data length, however:   */  fixRegs.ESI = inv.exit.len;  /* If the recipient specified an invalid receive area, though, they   * are gonna get FC_ParmLack:   */  if (inv.validLen < inv.exit.len)    SetFault(FC_ParmLack, rcvBase + inv.validLen, false);  /* Make sure it isn't later overwritten by the general delivery   * mechanism.   */  inv.suppressXfer = true;}#ifdef ASM_VALIDATE_STRINGS/* The reason to do this is that until OPTION_PURE_ENTRY_STRINGS is removed   there are a whole lot of places where this gets called.   The net effect is that ASM_VALIDATE_STRINGS implies   OPTION_PURE_ENTRY_STRINGS whether OPTION_PURE_ENTRY_STRINGS is set or not. */inline voidProcess::SetupEntryString(struct Invocation& inv){#ifndef OPTION_SMALL_SPACES  const uint32_t bias = 0;#endif        uint32_t addr = (uint32_t) fixRegs.sndPtr + bias + KUVA;    inv.entry.data = (uint8_t *) addr;}#endif#endif /* __MACHINE_PROCESS_HXX__ */

⌨️ 快捷键说明

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