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

📄 usercontext.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
  if (dbg_wild_ptr)    if (Check::Contexts("before unload") == false)      halt('a');#endif  if (curThread) {    SyncThread();    curThread->ZapContext();  }#if defined(DBG_WILD_PTR)  if (dbg_wild_ptr)    if (Check::Contexts("after syncthread") == false)      halt('b');#endif    fixRegs.MappingTable = 0;  saveArea = 0;  curThread = 0;#ifdef EROS_HAVE_FPU  if ( (hazards & hz::FloatRegs) == 0)    FlushFloatRegs();#endif  if ((hazards & hz::KeyRegs) == 0)    FlushKeyRegs();    if ((hazards & hz::DomRoot) == 0)    FlushFixRegs();    if ( (*procRoot)[ProcAddrSpace].IsHazard() ) {    Depend_InvalidateKey(&(*procRoot)[ProcAddrSpace]);    (*procRoot)[ProcAddrSpace].UnHazard();    hazards |= hz::AddrSpace;  }  procRoot->context = 0;  procRoot->obType = ObType::NtUnprepared;  assert(procRoot);    kr.UnprepareAll();  hazards = 0;  procRoot = 0;  saveArea = 0;  stallQ.WakeAll();}/* If the process has an invalid address space slot, it would probably * be more efficient to simply invoke the keeper right here rather * than start up a thread we know will fault.  There are three reasons * not to do so: *  * 1. It might get fixed before it runs. * 2. It is more modular to let the pagefault handler do it, since *    that handler needs to deal with this situation already. * 3. This code is goddamn well hairy enough as it is. *  * To load the mapping table pointer, we walk down the address space * segment looking for a node spanning 2^32 bits (blss=7).  We then * examine it's products looking for a suitable mapping table. *  * If we do not find one, we can't just build one on the spot, because * we must fabricate suitable depend entries for the new mapping * table. *//* This is somewhat misnamed, as loading the address space on the x86 * doesn't really load the address space at all -- it locates and * loads the page directory, which need not contain any valid entries. * Further faults will be handled in the page fault path. *  * In loading the page directory, the LoadAddressSpace logic does not * need to construct any dependency table entries for the BLSS::bit32 * node.  That node is a producer, and if it is taken out of core or * its keys are deprepared we can (and must) walk the producer chain * in any case. *  * The address space segment slot may contain a segment key to a * segment whose span is larger than the span of the hardware address * space.  For example, the segment might span 2^40 bits while the * hardware address space is only 2^32 bits.  In interpreting such a * segment, we take the view that the address space of the process * starts at offset 0 in the larger segment, and is only as big as the * hardware will support. *  * In the event that the address space segment is oversized in this * way, however, LoadAddressSpace() must create depend entries for all * nodes whose BLSS is > BLSS::bit32.  We commit a slight bit of * silliness in doing this, which in practice works out okay.  A page * directory holds 1024 entries.  For nodes whose BLSS is > * BLSS::bit32, we know that the only key acting in a memory context * is the key in slot 0.  We therefore claim (lying through our teeth) * that these nodes span a range of 16 * 1024 == 16k entries in the * page directory.  We check for out of range invalidation in the * invalidate logic, so we never get caught by this.  Also, the * invalidate logic knows the difference between page directories and * page tables, and never zaps the kernel entries. *  */voidProcess::LoadAddressSpace(bool prompt){  assert (hazards & hz::AddrSpace);    /* It's possible that we will end up invalidating exactly the   * entries we are after!   */  if ( proc_DoPageFault(this, fixRegs.EIP, false, prompt) ) {    hazards &= ~hz::AddrSpace;  }}/* Fault code is tricky.  It is conceivable that the process does not * posess a number key in the fault code slot.  In that event we set * the fault code to FC_MalformedProcess.  Unless the process node * posesses a number key in the fault code slot, the fault code will * not be written back to the process root.  Note that it is not * possible for a process with faultCode = FC_MalformedProcess to * achieve any other fault code without first resolving that one, so * it is okay to fail to write FC_MalformedProcess back to the process * root. *  * Note the runstate is not loaded here.  If the process root is * malformed it's runstate is intrinsically undefined.  Such a process * cannot execute instructions.  It's malformedness is discovered in * one of two ways: *  *   1. It was running and somehow became malformed, in which case it *      invokes it's keeper on it's own behalf. *   2. It was invoked by a third party, who is made to invoke its *      keeper on its behalf. *  * If the process root later becomes well formed we will be able to * load its run state at that time. */#if 0voidProcess::LoadFaultCode(){  assert (procRoot);    if ( procRoot->slot[ProcTrapCode].IsType(KT_Number) ) {    DomRegLayout* pDomRegs = (DomRegLayout*) & ((*procRoot)[0]);    faultCode = pDomRegs->faultCode;    faultInfo = pDomRegs->faultInfo;  }  else {    faultCode = FC_MalformedProcess;    faultInfo = 0;  }    hazards &= ~State::DomFaultCode;}#endif/* The DoPrepare() logic has changed, now that we have merged the * process prep logic into it... */voidProcess::DoPrepare(){  assert(procRoot);  assert (isUserContext);  procRoot->TransLock();  if (keysNode)    keysNode->TransLock();    hazards &= ~hz::Malformed;	/* until proven otherwise */    bool check_disjoint    = (hazards & (hz::DomRoot | hz::FloatRegs | hz::KeyRegs)); #if 0  printf("Enter Process::DoPrepare()\n");#endif  /* The order in which these are tested is important, because   * sometimes satisfying one condition imposes another (e.g. floating   * point bit set in the eflags register)   */  if (hazards & hz::DomRoot)    LoadFixRegs();  if (faultCode == FC_MalformedProcess) {    assert (processFlags & PF_Faulted);    return;  }  #ifdef EROS_HAVE_FPU  if (hazards & hz::FloatRegs)    LoadFloatRegs();  if (hazards & hz::NumericsUnit)    LoadFPU();#endif  if (hazards & hz::KeyRegs)    LoadKeyRegs();  if (check_disjoint) {    if ( procRoot == keysNode ) {      SetMalformed();    }  }    if (faultCode == FC_MalformedProcess) {    assert (processFlags & PF_Faulted);    return;  }    if (hazards & hz::Schedule) {    /* FIX: someday deal with schedule keys! */    Key& schedKey = (*procRoot)[ProcSched];    assert(schedKey.IsHazard() == false);        schedKey.SetWrHazard();    cpuReserve = &CpuReserve::GetReserve(schedKey);    hazards &= ~hz::Schedule;  }#if 0  /* This is wrong.  The original idea was that by prefaulting the EIP   * address we could avoid an unnecessary kernel reentry.   * Unfortunately, the prepare logic needs to be callable in order to   * load the 32 bit register set from InvokeProcessKeeper.  If no   * valid address space exists for the process, then trying to build the   * address space here causes a segment fault.  If the relevant   * segment has no keeper, this in turn yields in order to cause the   * process keeper (if any) to be invoked.  In that particular   * sequence of events, however, an infinite loop is created...   *    * Rather than try to automatically build the address space here, we   * go ahead with a zero mapping table and take the extra instruction   * fault.   */    if (fixRegs.MappingTable == 0) {    hazards |= hz::AddrSpace;  }    if (hazards & hz::AddrSpace)    LoadAddressSpace(false);#endif    if (hazards & hz::SingleStep) {    fixRegs.EFLAGS |= MASK_EFLAGS_Trap;    hazards &= ~hz::SingleStep;  }  ValidateRegValues();    /* Change: It is now okay for the context to carry a fault code   * and prepare correctly.   */  saveArea = &fixRegs;  stallQ.WakeAll();}voidProcess::InvokeProcessKeeper(){  Registers regs;#if 0  dprintf(false, "Fetching register values for InvokeProcessKeeper()\n");#endif  GetRegs32(regs);  /* Override the current domain state, as this is about to change in     the course of the invocation. */   regs.domState = RS_Waiting;#if 0  dprintf(false, "  ExNo: 0x%08x, Error: 0x%08x  Info: 0x%08x  FVA 0x%08x\n",		  fixRegs.ExceptNo,		  fixRegs.Error,		  faultInfo,		  fixRegs.ExceptAddr);#endif  /* Must be unprepared in case we throw()! */    Key processKey;  processKey.InitType(KT_Process);  processKey.unprep.oid = procRoot->ob.oid;  processKey.unprep.count = procRoot->ob.allocCount;  /* Guarantee that prepared resume key will be in dirty object -- see   * comment in kern_Invoke.cxx:   */  assert (procRoot->IsDirty());    InvokeMyKeeper(OC_PROCFAULT, 0, 0, 0, &procRoot->slot[ProcKeeper],		 &processKey, (uint8_t *) &regs, sizeof(regs));}voidProcess::FlushProcessSlot(uint32_t whichKey){  assert(procRoot);    switch (whichKey) {  case ProcGenKeys:    assert ((hazards & hz::KeyRegs) == 0);    FlushKeyRegs();    break;  case ProcAddrSpace:    Depend_InvalidateKey(&(*procRoot)[whichKey]);    (*procRoot)[whichKey].UnHazard();    hazards |= hz::AddrSpace;    assert(fixRegs.MappingTable == 0);    saveArea = 0;    break;  default:#ifdef EROS_HAVE_FPU    if ( (hazards & hz::FloatRegs) == 0 )      FlushFloatRegs();#endif        assert ((hazards & hz::DomRoot) == 0);    FlushFixRegs();    break;  }  saveArea = 0;}#ifdef OPTION_DDBvoidProcess::WriteBackKeySlot(uint32_t k){  /* Write back a single key in support of DDB getting the display correct */  assert ((hazards & hz::KeyRegs) == 0);  assert (keysNode->IsDirty());  keysNode->slot[k].UnHazard();  keysNode->slot[k].NH_Set(keyReg[k]);  keysNode->slot[k].SetRwHazard();}#endif#if 0voidProcess::SetFault(uint32_t code, uint32_t info, bool needRevalidate){  faultCode = code;  faultInfo = info;  /* For FC_MalformedProcess, should use SetMalformed() instead!! */  assert(faultCode != FC_MalformedProcess);  #if 1  if (faultCode)    processFlags |= PF_Faulted;  else    processFlags &= ~PF_Faulted;#endif  #if 0  printf("Fault code set to %d info=0x%x\n", code, info);#endif#if 0  /* It is now sufficient to set the PF_Faulted flag, which has the   * effect of rendering the process non-runnable without totally   * zapping the entire universe.   */    if (needRevalidate)    NeedRevalidate();#endif#if 0  Debugger();#endif}#endif/* On entry. inv.rcv.code == RC_OK */boolProcess::GetRegs32(struct Registers& regs){  assert (IsRunnable());  /* Following is x86 specific.  On architectures with more annex   * nodes this would need to check those too:   */    if (hazards & hz::DomRoot) {    return false;  }    regs.arch   = ARCH_I386;  regs.len    = sizeof(regs);  regs.pc     = fixRegs.EIP;  regs.sp     = fixRegs.ESP;  regs.faultCode = faultCode;  regs.faultInfo = faultInfo;  regs.domState = runState;  regs.domFlags = processFlags;  regs.EDI    = fixRegs.EDI;  regs.ESI    = fixRegs.ESI;  regs.EBP    = fixRegs.EBP;  regs.EBX    = fixRegs.EBX;  regs.EDX    = fixRegs.EDX;  regs.ECX    = fixRegs.ECX;  regs.EAX    = fixRegs.EAX;  regs.EFLAGS = fixRegs.EFLAGS;  regs.CS     = fixRegs.CS;  regs.SS     = fixRegs.SS;  regs.ES     = fixRegs.ES;  regs.DS     = fixRegs.DS;  regs.FS     = fixRegs.FS;  regs.GS     = fixRegs.GS;  return true;}/* On entry. inv.rcv.code == RC_OK */boolProcess::SetRegs32(Registers& regs){#if 0  dprintf(true, "ctxt=0x%08x: Call to SetRegs32\n", this);#endif  assert (IsRunnable());  if (hazards & hz::DomRoot) {    dprintf(true, "ctxt=0x%08x: No root regs\n", this);    return false;  }    /* Done with len, architecture */  fixRegs.EIP    = regs.pc;#if 0  nextPC         = regs.pc;#endif  fixRegs.ESP    = regs.sp;  faultCode      = regs.faultCode;  faultInfo      = regs.faultInfo;  runState       = regs.domState;  processFlags    = regs.domFlags;  fixRegs.EDI    = regs.EDI;  fixRegs.ESI    = regs.ESI;  fixRegs.EBP    = regs.EBP;  fixRegs.EBX    = regs.EBX;  fixRegs.EDX    = regs.EDX;  fixRegs.ECX    = regs.ECX;  fixRegs.EAX    = regs.EAX;  fixRegs.EFLAGS = regs.EFLAGS;  fixRegs.CS     = regs.CS;  fixRegs.SS     = regs.SS;  fixRegs.ES     = regs.ES;  fixRegs.DS     = regs.DS;  fixRegs.FS     = regs.FS;  fixRegs.GS     = regs.GS;#if 0  dprintf(true, "SetRegs(): ctxt=0x%08x: EFLAGS now 0x%08x\n", this, fixRegs.EFLAGS);#endif  NeedRevalidate();      return true;}

⌨️ 快捷键说明

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