Make it so that all thread contexts are registered with the System, even in
authorLisa Hsu <hsul@eecs.umich.edu>
Mon, 3 Nov 2008 02:57:06 +0000 (21:57 -0500)
committerLisa Hsu <hsul@eecs.umich.edu>
Mon, 3 Nov 2008 02:57:06 +0000 (21:57 -0500)
SE.  Process still keeps track of the tc's it owns, but registration occurs
with the System, this eases the way for system-wide context Ids based on
registration.

src/arch/alpha/process.cc
src/arch/sparc/process.cc
src/arch/x86/process.cc
src/cpu/base.cc
src/kern/tru64/tru64.hh
src/sim/process.cc
src/sim/process.hh
src/sim/system.cc
src/sim/system.hh

index 380e0e18efa02b6fcac8634572a18e1e9c25b5a7..28e8df308ef94642601c6bf8f7e8be5c4c9396d4 100644 (file)
@@ -67,12 +67,13 @@ AlphaLiveProcess::startup()
 
     argsInit(MachineBytes, VMPageSize);
 
-    threadContexts[0]->setIntReg(GlobalPointerReg, objFile->globalPointer());
-    //Opperate in user mode
-    threadContexts[0]->setMiscRegNoEffect(IPR_ICM, 0x18);
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
+    tc->setIntReg(GlobalPointerReg, objFile->globalPointer());
+    //Operate in user mode
+    tc->setMiscRegNoEffect(IPR_ICM, 0x18);
     //No super page mapping
-    threadContexts[0]->setMiscRegNoEffect(IPR_MCSR, 0);
+    tc->setMiscRegNoEffect(IPR_MCSR, 0);
     //Set this to 0 for now, but it should be unique for each process
-    threadContexts[0]->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
+    tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
 }
 
index a8fda04eb1834a00ddae6c557f032e9ca6acb9d2..987e0465e6e50a395a8a8548a0f52eba3ea80177 100644 (file)
@@ -112,44 +112,45 @@ SparcLiveProcess::startup()
 {
     Process::startup();
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //From the SPARC ABI
 
     //Setup default FP state
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
+    tc->setMiscRegNoEffect(MISCREG_FSR, 0);
 
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
+    tc->setMiscRegNoEffect(MISCREG_TICK, 0);
 
     /*
      * Register window management registers
      */
 
     //No windows contain info from other programs
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
+    //tc->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
+    tc->setIntReg(NumIntArchRegs + 6, 0);
     //There are no windows to pop
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
+    //tc->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
+    tc->setIntReg(NumIntArchRegs + 4, 0);
     //All windows are available to save into
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
+    //tc->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
+    tc->setIntReg(NumIntArchRegs + 3, NWindows - 2);
     //All windows are "clean"
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
+    //tc->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
+    tc->setIntReg(NumIntArchRegs + 5, NWindows);
     //Start with register window 0
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
+    tc->setMiscRegNoEffect(MISCREG_CWP, 0);
     //Always use spill and fill traps 0
-    //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
-    threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
+    //tc->setMiscRegNoEffect(MISCREG_WSTATE, 0);
+    tc->setIntReg(NumIntArchRegs + 7, 0);
     //Set the trap level to 0
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
+    tc->setMiscRegNoEffect(MISCREG_TL, 0);
     //Set the ASI register to something fixed
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
+    tc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
 
     /*
      * T1 specific registers
      */
     //Turn on the icache, dcache, dtb translation, and itb translation.
-    threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
+    tc->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
 }
 
 void
@@ -160,8 +161,9 @@ Sparc32LiveProcess::startup()
 
     SparcLiveProcess::startup();
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //The process runs in user mode with 32 bit addresses
-    threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
+    tc->setMiscReg(MISCREG_PSTATE, 0x0a);
 
     argsInit(32 / 8, VMPageSize);
 }
@@ -174,8 +176,9 @@ Sparc64LiveProcess::startup()
 
     SparcLiveProcess::startup();
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //The process runs in user mode
-    threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
+    tc->setMiscReg(MISCREG_PSTATE, 0x02);
 
     argsInit(sizeof(IntReg), VMPageSize);
 }
@@ -391,20 +394,21 @@ SparcLiveProcess::argsInit(int pageSize)
     fillStart = stack_base;
     spillStart = fillStart + sizeof(MachInst) * numFillInsts;
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //Set up the thread context to start running the process
     //assert(NumArgumentRegs >= 2);
-    //threadContexts[0]->setIntReg(ArgumentReg[0], argc);
-    //threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
-    threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
+    //tc->setIntReg(ArgumentReg[0], argc);
+    //tc->setIntReg(ArgumentReg[1], argv_array_base);
+    tc->setIntReg(StackPointerReg, stack_min - StackBias);
 
     // %g1 is a pointer to a function that should be run at exit. Since we
     // don't have anything like that, it should be set to 0.
-    threadContexts[0]->setIntReg(1, 0);
+    tc->setIntReg(1, 0);
 
     Addr prog_entry = objFile->entryPoint();
-    threadContexts[0]->setPC(prog_entry);
-    threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
-    threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+    tc->setPC(prog_entry);
+    tc->setNextPC(prog_entry + sizeof(MachInst));
+    tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
 
     //Align the "stack_min" to a page boundary.
     stack_min = roundDown(stack_min, pageSize);
index b62efd3cdd7c58eaf52b3c790b5213909562ee89..52933b7f43f22f9e265fb63890d254381a954b8b 100644 (file)
@@ -146,8 +146,8 @@ X86LiveProcess::startup()
 
     argsInit(sizeof(IntReg), VMPageSize);
 
-    for (int i = 0; i < threadContexts.size(); i++) {
-        ThreadContext * tc = threadContexts[i];
+    for (int i = 0; i < contextIds.size(); i++) {
+        ThreadContext * tc = system->getThreadContext(contextIds[i]);
 
         SegAttr dataAttr = 0;
         dataAttr.writable = 1;
@@ -458,14 +458,15 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
 
     initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
 
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
     //Set the stack pointer register
-    threadContexts[0]->setIntReg(StackPointerReg, stack_min);
+    tc->setIntReg(StackPointerReg, stack_min);
 
     Addr prog_entry = objFile->entryPoint();
     // There doesn't need to be any segment base added in since we're dealing
     // with the flat segmentation model.
-    threadContexts[0]->setPC(prog_entry);
-    threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+    tc->setPC(prog_entry);
+    tc->setNextPC(prog_entry + sizeof(MachInst));
 
     //Align the "stack_min" to a page boundary.
     stack_min = roundDown(stack_min, pageSize);
index 3e899d9936de851e56c1e55bbd2d887aad9520de..4845cbfaf7041c66a5c4910ffd3c8bf1a5aa1405 100644 (file)
@@ -285,10 +285,9 @@ BaseCPU::registerThreadContexts()
     for (int i = 0; i < threadContexts.size(); ++i) {
         ThreadContext *tc = threadContexts[i];
 
-#if FULL_SYSTEM
         system->registerThreadContext(tc);
-#else
-        tc->getProcessPtr()->registerThreadContext(tc);
+#if !FULL_SYSTEM
+        tc->getProcessPtr()->assignThreadContext(tc->cpuId());
 #endif
     }
 }
@@ -330,12 +329,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
         CpuEvent::replaceThreadContext(oldTC, newTC);
 
         assert(newTC->cpuId() == oldTC->cpuId());
-#if FULL_SYSTEM
         system->replaceThreadContext(newTC, newTC->cpuId());
-#else
-        assert(newTC->getProcessPtr() == oldTC->getProcessPtr());
-        newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->cpuId());
-#endif
 
         if (DTRACE(Context))
             ThreadContext::compare(oldTC, newTC);
index dfdb8524d6cc44fb7b5fb509cf7a0e466985d821..5f8307cd29f5684bb2514a13e36b1b48401a64b9 100644 (file)
@@ -789,21 +789,18 @@ class Tru64 : public OperatingSystem
             slot_state.copyOut(tc->getMemPort());
 
             // Find a free simulator thread context.
-            for (int i = 0; i < process->numCpus(); ++i) {
-                ThreadContext *tc = process->threadContexts[i];
-
-                if (tc->status() == ThreadContext::Unallocated) {
-                    // inactive context... grab it
-                    init_thread_context(tc, attrp, uniq_val);
-
-                    // This is supposed to be a port number, but we'll try
-                    // and get away with just sticking the thread index
-                    // here.
-                    *kidp = htog(thread_index);
-                    kidp.copyOut(tc->getMemPort());
-
-                    return 0;
-                }
+            ThreadContext *tc = process->findFreeContext();
+            if (tc) {
+                // inactive context... grab it
+                init_thread_context(tc, attrp, uniq_val);
+
+                // This is supposed to be a port number, but we'll try
+                // and get away with just sticking the thread index
+                // here.
+                *kidp = htog(thread_index);
+                kidp.copyOut(tc->getMemPort());
+
+                return 0;
             }
 
             // fell out of loop... no available inactive context
index 23e890b06f0030531710a938aadeefd876e68702..50bc5e034b5cabc88372bce939cd1f8d75cf7052 100644 (file)
@@ -204,35 +204,29 @@ Process::openOutputFile(const string &filename)
     return fd;
 }
 
-
-int
-Process::registerThreadContext(ThreadContext *tc)
+ThreadContext *
+Process::findFreeContext()
 {
-    // add to list
-    int myIndex = threadContexts.size();
-    threadContexts.push_back(tc);
-
-    int port = getRemoteGDBPort();
-    if (port) {
-        RemoteGDB *rgdb = new RemoteGDB(system, tc);
-        GDBListener *gdbl = new GDBListener(rgdb, port + myIndex);
-        gdbl->listen();
-
-        remoteGDB.push_back(rgdb);
+    int size = contextIds.size();
+    ThreadContext *tc;
+    for (int i = 0; i < size; ++i) {
+        tc = system->getThreadContext(contextIds[i]);
+        if (tc->status() == ThreadContext::Unallocated) {
+            // inactive context, free to use
+            return tc;
+        }
     }
-
-    // return CPU number to caller
-    return myIndex;
+    return NULL;
 }
 
 void
 Process::startup()
 {
-    if (threadContexts.empty())
-        fatal("Process %s is not associated with any CPUs!\n", name());
+    if (contextIds.empty())
+        fatal("Process %s is not associated with any HW contexts!\n", name());
 
     // first thread context for this process... initialize & enable
-    ThreadContext *tc = threadContexts[0];
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
 
     // mark this context as active so it will start ticking.
     tc->activate(0);
@@ -245,17 +239,6 @@ Process::startup()
     initVirtMem->setPeer(mem_port);
 }
 
-void
-Process::replaceThreadContext(ThreadContext *tc, int tcIndex)
-{
-    if (tcIndex >= threadContexts.size()) {
-        panic("replaceThreadContext: bad tcIndex, %d >= %d\n",
-              tcIndex, threadContexts.size());
-    }
-
-    threadContexts[tcIndex] = tc;
-}
-
 // map simulator fd sim_fd to target fd tgt_fd
 void
 Process::dup_fd(int sim_fd, int tgt_fd)
@@ -624,16 +607,19 @@ LiveProcess::argsInit(int intSize, int pageSize)
     copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
 
     assert(NumArgumentRegs >= 2);
-    threadContexts[0]->setIntReg(ArgumentReg[0], argc);
-    threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
-    threadContexts[0]->setIntReg(StackPointerReg, stack_min);
+
+    ThreadContext *tc = system->getThreadContext(contextIds[0]);
+
+    tc->setIntReg(ArgumentReg[0], argc);
+    tc->setIntReg(ArgumentReg[1], argv_array_base);
+    tc->setIntReg(StackPointerReg, stack_min);
 
     Addr prog_entry = objFile->entryPoint();
-    threadContexts[0]->setPC(prog_entry);
-    threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+    tc->setPC(prog_entry);
+    tc->setNextPC(prog_entry + sizeof(MachInst));
 
 #if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc
-    threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+    tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
 #endif
 
     num_processes++;
index cb59fed6486f172e89612ae62958d758bf5717e0..d6ed59ced02da0893e642f34d6e94eb7143e8606 100644 (file)
@@ -77,7 +77,7 @@ class Process : public SimObject
     bool checkpointRestored;
 
     // thread contexts associated with this process
-    std::vector<ThreadContext *> threadContexts;
+    std::vector<int> contextIds;
 
     // remote gdb objects
     std::vector<TheISA::RemoteGDB *> remoteGDB;
@@ -85,7 +85,7 @@ class Process : public SimObject
     bool breakpoint();
 
     // number of CPUs (esxec contexts, really) assigned to this process.
-    unsigned int numCpus() { return threadContexts.size(); }
+    unsigned int numCpus() { return contextIds.size(); }
 
     // record of blocked context
     struct WaitRec
@@ -187,12 +187,15 @@ class Process : public SimObject
     // override of virtual SimObject method: register statistics
     virtual void regStats();
 
-    // register a thread context for this process.
-    // returns tc's cpu number (index into threadContexts[])
-    int registerThreadContext(ThreadContext *tc);
-
+    // After getting registered with system object, tell process which
+    // system-wide context id it is assigned.
+    void assignThreadContext(int context_id)
+    {
+        contextIds.push_back(context_id);
+    }
 
-    void replaceThreadContext(ThreadContext *tc, int tcIndex);
+    // Find a free context to use
+    ThreadContext * findFreeContext();
 
     // map simulator fd sim_fd to target fd tgt_fd
     void dup_fd(int sim_fd, int tgt_fd);
index 41075e9d06ef0850fd9e5e57529007ccf06f5b3f..8f25b4bb80b1ef76034a2b08a0d7a553adbbb25d 100644 (file)
@@ -208,22 +208,24 @@ System::registerThreadContext(ThreadContext *tc)
 void
 System::startup()
 {
+#if FULL_SYSTEM
     int i;
     for (i = 0; i < threadContexts.size(); i++)
         TheISA::startupCPU(threadContexts[i], i);
+#endif
 }
 
 void
-System::replaceThreadContext(ThreadContext *tc, int id)
+System::replaceThreadContext(ThreadContext *tc, int context_id)
 {
-    if (id >= threadContexts.size()) {
+    if (context_id >= threadContexts.size()) {
         panic("replaceThreadContext: bad id, %d >= %d\n",
-              id, threadContexts.size());
+              context_id, threadContexts.size());
     }
 
-    threadContexts[id] = tc;
-    if (id < remoteGDB.size())
-        remoteGDB[id]->replaceThreadContext(tc);
+    threadContexts[context_id] = tc;
+    if (context_id < remoteGDB.size())
+        remoteGDB[context_id]->replaceThreadContext(tc);
 }
 
 #if !FULL_SYSTEM
index f67d39c674c9f2a011e523d27b11c119b9b4fe4d..26cac714b0387cfb167b4540ba2907c5e4adf2d3 100644 (file)
@@ -89,6 +89,11 @@ class System : public SimObject
     std::vector<ThreadContext *> threadContexts;
     int numcpus;
 
+    ThreadContext * getThreadContext(int tid)
+    {
+        return threadContexts[tid];
+    }
+
     int getNumCPUs()
     {
         if (numcpus != threadContexts.size())
@@ -220,7 +225,7 @@ class System : public SimObject
 #endif // FULL_SYSTEM
 
     int registerThreadContext(ThreadContext *tc);
-    void replaceThreadContext(ThreadContext *tc, int tcIndex);
+    void replaceThreadContext(ThreadContext *tc, int context_id);
 
     void serialize(std::ostream &os);
     void unserialize(Checkpoint *cp, const std::string &section);