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

📄 process.hxx

📁 C++ 编写的EROS RTOS
💻 HXX
字号:
#ifndef __PROCESS_HXX__#define __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. *//* This is the revised (improved?) process structure, with reduced * architecture-dependent complexity.  Note that we are moving towards * C-style architecture-dependent helper functions, so this is not a * class. *//* CHANGES TO THIS FILE ****MUST**** BE MADE IN THE * ARCHITECTURE-SPECIFIC LAYOUT FILES TOO!!!  When the kernel is * converted to C we will be switching to using the LAYOUT file as the * ``official'' source. */#include <eros/ProcessState.h>#include <eros/ProcStats.h>#include <eros/machine/SaveArea.h>#ifdef EROS_HAVE_FPU#include <eros/machine/floatregs.h>#endif#ifdef EROS_HAVE_ARCH_REGS#include <eros/machine/archregs.h>#endif/* This file requires #include <kerninc/kernel.hxx> */#include <kerninc/Node.hxx>#include <kerninc/ThreadPile.hxx>struct Thread;struct SegWalk;/* Every running thread has an associated process structure.  The * process structure for user threads has a lot more state.  Process * structures for kernel threads are dedicated to the thread.  Process * structures for user threads are caches of domain state.  A process * is in use if it has a non-zero procRoot pointer. *  * Every process has an associated save area pointer. *  * Processes are reallocated in round-robin order, which may well prove * to be a dumb thing to do.  Kernel processes are not reallocated. */struct Process {  /* Pieces of the currently loaded domain: */  union {    KeyRing	kr;    Node      	*procRoot;  };  ThreadPile   stallQ;		/* procs waiting for this to be available */    bool  isUserContext;  /* hazards are reasons you cannot run.  They generally devolve to   * being malformed or needing some functional unit loaded before you   * can make progress.   */    uint32_t  hazards;  /* MACHINE DEPENDENT */  struct hz {    enum {      Malformed    = 0x01u,      DomRoot      = 0x02u,      KeyRegs      = 0x04u,      FloatRegs    = 0x08u,      Schedule     = 0x10u,      AddrSpace    = 0x20u,#ifdef EROS_HAVE_FPU      NumericsUnit = 0x40u,	/* need to load FPU */#endif      SingleStep   = 0x80u,	/* requested single step status */    };  };  bool IsWellFormed()  {#ifndef NDEBUG    if (faultCode == FC_MalformedProcess) {      assert (processFlags & PF_Faulted);      assert (saveArea == 0);    }#endif    if (hazards & (hz::DomRoot|hz::KeyRegs|hz::FloatRegs|hz::Malformed)) {      assert (saveArea == 0);      return false;    }    return true;  }  /* END MACHINE DEPENDENT */  /* SaveArea is nonzero exactly when the context has a valid save   * image -- i.e. it is fully cached and the resulting context image   * is RUNNABLE (i.e. doesn't violate processor privilege constraints).   */  struct fixregs_t  *saveArea;  struct CpuReserve *cpuReserve;  /* Processor we last ran on, to recover FP regs   * Processor     *lastProcessor;   */  /* At most one thread in a given context at a time, which will be   * pointed to by the context:   */  Thread	    *curThread;  Key* GetSegRoot()    {      return & ((*procRoot)[ProcAddrSpace]);    }  fixregs_t 	    fixRegs;  /* This should immediately follow fixRegs: */  Key               keyReg[EROS_PROCESS_KEYREGS];  uint32_t          faultCode;  uint32_t          faultInfo;  uint8_t           runState;  uint8_t           processFlags;  #ifdef OPTION_SMALL_SPACES  uva_t             limit;  ula_t             bias;  struct PTE        *smallPTE;  static struct PTE *smallSpaces;  void              SwitchToLargeSpace()    {      smallPTE = 0;      bias = 0;      limit = UMSGTOP;      fixRegs.MappingTable = KERNPAGEDIR;    }#endif  #ifdef EROS_HAVE_FPU  /* FPU support: */  floatregs_t 	    fpuRegs;  static Process*   fpuOwner;	/* FIX: This is not SMP-feasible. */  void SaveFPU();  void LoadFPU();  void DumpFloatRegs();#endif  #ifdef EROS_HAVE_ARCH_REGS  archregs_t	    archRegs;#endif  Node              *keysNode;  char              arch[4];  /* Useful to have a name for diagnostic purposes. */  char              name[8];  ProcStat          stats;    Key		    XaddressSpace;  Key		    XioSpace;  Key		    XcpuReserveKey;  Key		    XworkingSet;  Key		    Xkeeper;  Key		    XsymbolTable;#ifndef NDEBUG  static bool ValidKeyReg(const Key *pKey);#endif  static bool IsKeyReg(const Key *pKey)    {      /* This isn't quite right, as it will return TRUE for any random       * pointer in to the process area, but that's good enough for all       * the places that we use it.       */          if ( ((uint32_t) pKey >= (uint32_t) ContextCache) &&	   ((uint32_t) pKey <	    (uint32_t) &ContextCache[KTUNE_NCONTEXT]) ) {	return true;      }      return false;    }  /* Returns true if the context has been successfully cached. A   * context can be successfully cached without being runnable.  If   * possible, sets the saveArea pointer to a valid save area.  The   * saveArea pointer cannot be set if (e.g.) it's privileged   * registers have improper values.   */  void DoPrepare();  /* Fast-path inline version.  See comment above on DoPrepare().   * MUST NOT yield if IsRunnable() would return true.   */  void Prepare()  {    /* Anything that invalidates the context will zap the saveArea     * pointer, so this is a quick test, which is useful for fast     * reload.     */    if (saveArea)      return;    DoPrepare();  }  void NeedRevalidate()  {    saveArea = 0;  }  /* USED ONLY BY INTERRUPT HANDLERS: */  void SetSaveArea(fixregs_t *sa)  {    saveArea = sa;  }  fixregs_t *UnsafeSaveArea()  {    return saveArea;  }    bool IsRunnable()  {    return saveArea ? true : false;  }    bool IsNotRunnable()  {    return (saveArea == 0) ? true : false;  }    void Unthread()  {    assert (isUserContext);    curThread = 0;  }    void SetThread(Thread *thread)  {    assert(curThread == 0 || curThread == thread);    curThread = thread;  }    void Resume() NORETURN;    bool IsUser()  {    return isUserContext;  }  bool IsKernel()  {    return !isUserContext;  }  const char* Name()  {    return name;  }  /* Called by checkpoint logic */  static void FlushAll();  static void AllocUserContexts(); /* machine dependent! */  void DumpFixRegs();    /* needRevalidate means that the fault is due to a structural   * problem in the process, and cannot be cleared without   * revalidating the context cache.  Another way to think about this   * is that any fault for which /needRevalidate/ is true is a fault   * that cannot be cleared on the fast path.   */  void SetFault(uint32_t code, uint32_t info, bool needRevalidate)  {    faultCode = code;    faultInfo = info;    assert(faultCode != FC_MalformedProcess);        if (faultCode)      processFlags |= PF_Faulted;    else      processFlags &= ~PF_Faulted;    if (needRevalidate)      NeedRevalidate();#ifdef OPTION_DDB    if (processFlags & PF_DDBTRAP)      dprintf(true, "Process 0x%08x has trap code set\n", this);#endif  }  void SetMalformed()  { SetFault(FC_MalformedProcess, 0, true);  hazards |= hz::Malformed; }  /* Generic keeper invoker: */  void InvokeMyKeeper(uint32_t oc,		      uint32_t warg1,		      uint32_t warg2,		      uint32_t warg3,		      Key *keeperKey, Key* keyArg2,		      uint8_t *data, uint32_t len);    bool InvokeSegmentKeeper(/*uint32_t code, */ SegWalk&);  void InvokeProcessKeeper();			     /******************************************************   * Begin new code in support of new invocation logic   ******************************************************/  void BuildResumeKey(Key& resumeKey);  void DoGeneralKeyInvocation();  void DoKeyInvocation();  /* Following is only needed if assembly code is not used to validate     the entry block. */#ifndef FAST_IPC_ARG_VALIDATE  inline void ValidateEntryBlock();	/* may throw */#endif#ifdef ASM_VALIDATE_STRINGS  inline#endif  void SetupEntryString(struct Invocation& inv);  void SetupExitString(struct Invocation& inv, uint32_t bound);  inline void SetupEntryBlock(struct Invocation& inv);  inline void SetupExitBlock(struct Invocation& inv);  void DeliverResult(struct Invocation& inv);  inline void DeliverGateResult(Invocation& inv, bool wantFault);  /******************************************************   * End new code in support of new invocation logic   ******************************************************/  /******************************************************   *  Code in support of emulated instructions:   ******************************************************/  void DoEmulatedInstr(const struct EmulatedInstr& instr);  /******************************************************   * End new code in support of emulated instructions   ******************************************************/  void LoadFixRegs();#ifdef EROS_HAVE_FPU  void LoadFloatRegs();#endif  void LoadKeyRegs();  void FlushFixRegs();#ifdef EROS_HAVE_FPU  void FlushFloatRegs();#endif  void FlushKeyRegs();  /* Following are machine generated because I got tired of making mistakes: */  void DoLoadFixRegs();  void DoFlushFixRegs();  void DoLoadFloatRegs();  void DoFlushFloatRegs();    void LoadAddressSpace(bool prompt);  void ValidateRegValues();	/* returns false if faulted */  bool HasDevicePriveleges();  void FlushProcessSlot(uint32_t whichKey);#ifdef OPTION_DDB  void WriteBackKeySlot(uint32_t whichKey);#endif  void SyncThread();  void Unload();  bool GetRegs32(struct Registers&);  bool SetRegs32(struct Registers&);  void SetPC(uint32_t oc)  {    fixRegs.EIP = oc;  }  /* Called before AdjustInvocationPC() to capture the address of the   * next instruction to run if the invocation is successful.   */  inline uint32_t CalcPostInvocationPC()  {    return fixRegs.EIP;  }  /* Called in the IPC path to reset the PC to point to the invocation   * trap instruction...   */  inline void AdjustInvocationPC()  {    fixRegs.EIP -= 2;  }  inline uint32_t GetPC()  {    return fixRegs.EIP;  }    void SetInstrSingleStep()  {    hazards |= hz::SingleStep;    saveArea = 0;  }  #ifdef EROS_HAVE_FPU  void ForceNumericsLoad()  {    hazards |= hz::NumericsUnit;    saveArea = 0;  }#endif  #ifdef OPTION_SMALL_SPACES  static void WriteDisableSmallSpaces();#endif  Process();  static Process *ContextCache;  static void Load(Node* procRoot);#if 0  /* Note protected constructor!! */  Context(bool isUser)  {    isUserContext = isUser;    cpuReserve = 0;    faultCode = FC_NoFault;    faultInfo = 0;    saveArea = 0;    hazards = 0u;	/* deriver should change this! */  }#endif};/* Walk a segment as described in WI until one of the following * occurs: *  *     You find a subsegment whose blss is <= STOPBLSS (walk *        succeeded, return true) *     You conclude that the desired type of access as described in *        ISWRITE cannot be satisfied in this segment (walk failed, *        return false) *  * At each stage in the walk, add dependency entries between the * traversed slots and the page table entries named by the passed * PTEs. *  * If 'prompt' is true, WalkSeg returns as described above.  If * prompt is false, WalkSeg invokes the prevailing keeper on error. *  * This routine is designed to be re-entered and cache it's * intervening state in the SegWalk structure so that the walk * does not need to be repeated. */  extern boolproc_WalkSeg(Process * p,SegWalk& wi, uint32_t stopBlss,	     PTE* pPTE0, PTE* pPTE1, bool canMerge);/* This may now be vestigial.... */struct KernProcess : public Process {#ifdef DBG_WILD_PTR  uint32_t *stackTop;  uint32_t *stackBottom;#endif#if 0  /* Following are for kernel threads: */  KernProcess(const char *myName, Thread& theThread);#endif  KernProcess(const char * name,	      Thread& theThread,	      void (*pc)(),	      uint32_t *StackBottom, uint32_t *StackTop);  void InitStack();#if 0  void SetStack(uint32_t */*stkBottom*/, uint32_t */*stkTop*/)  {    stackBottom = stkBottom;    stackTop = stkTop;  }#endif} ;#endif /* __PROCESS_HXX__ */

⌨️ 快捷键说明

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