changeset 1133617844c8 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=1133617844c8
description:
        cpu: Fix broken thread context handover

        The thread context handover code used to break when multiple handovers
        were performed during the same quiesce period. Previously, the thread
        contexts would assign the TC pointer in the old quiesce event to the
        new TC. This obviously broke in cases where multiple switches were
        performed within the same quiesce period, in which case the TC pointer
        in the quiesce event would point to an old CPU.

        The new implementation deschedules pending quiesce events in the old
        TC and schedules a new quiesce event in the new TC. The code has been
        refactored to remove most of the code duplication.

diffstat:

 src/cpu/inorder/thread_context.cc |  10 +-------
 src/cpu/o3/thread_context_impl.hh |  30 ++-----------------------
 src/cpu/simple_thread.cc          |  44 ++------------------------------------
 src/cpu/simple_thread.hh          |   2 -
 src/cpu/thread_context.cc         |  37 ++++++++++++++++++++++++++++++++
 src/cpu/thread_context.hh         |  13 +++++++++++
 6 files changed, 57 insertions(+), 79 deletions(-)

diffs (206 lines):

diff -r fdc91cab5760 -r 1133617844c8 src/cpu/inorder/thread_context.cc
--- a/src/cpu/inorder/thread_context.cc Mon Jan 07 13:05:46 2013 -0500
+++ b/src/cpu/inorder/thread_context.cc Mon Jan 07 13:05:46 2013 -0500
@@ -93,18 +93,10 @@
 void
 InOrderThreadContext::takeOverFrom(ThreadContext *old_context)
 {
-    // some things should already be set up
-    assert(getSystemPtr() == old_context->getSystemPtr());
-    assert(getProcessPtr() == old_context->getProcessPtr());
-
-    // copy over functional state
-    setStatus(old_context->status());
-    copyArchRegs(old_context);
+    ::takeOverFrom(*this, *old_context);
 
     thread->funcExeInst = old_context->readFuncExeInst();
 
-    old_context->setStatus(ThreadContext::Halted);
-
     thread->noSquashFromTC = false;
     thread->trapPending = false;
 }
diff -r fdc91cab5760 -r 1133617844c8 src/cpu/o3/thread_context_impl.hh
--- a/src/cpu/o3/thread_context_impl.hh Mon Jan 07 13:05:46 2013 -0500
+++ b/src/cpu/o3/thread_context_impl.hh Mon Jan 07 13:05:46 2013 -0500
@@ -66,34 +66,10 @@
 void
 O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context)
 {
-    // some things should already be set up
-    assert(getSystemPtr() == old_context->getSystemPtr());
-    assert(getProcessPtr() == old_context->getProcessPtr());
+    ::takeOverFrom(*this, *old_context);
 
-    // copy over functional state
-    setStatus(old_context->status());
-    copyArchRegs(old_context);
-    setContextId(old_context->contextId());
-    setThreadId(old_context->threadId());
-
-    if (FullSystem) {
-        EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
-        if (other_quiesce) {
-            // Point the quiesce event's TC at this TC so that it wakes up
-            // the proper CPU.
-            other_quiesce->tc = this;
-        }
-        if (thread->quiesceEvent) {
-            thread->quiesceEvent->tc = this;
-        }
-
-        // Transfer kernel stats from one CPU to the other.
-        thread->kernelStats = old_context->getKernelStats();
-    } else {
-        thread->funcExeInst = old_context->readFuncExeInst();
-    }
-
-    old_context->setStatus(ThreadContext::Halted);
+    thread->kernelStats = old_context->getKernelStats();
+    thread->funcExeInst = old_context->readFuncExeInst();
 
     thread->noSquashFromTC = false;
     thread->trapPending = false;
diff -r fdc91cab5760 -r 1133617844c8 src/cpu/simple_thread.cc
--- a/src/cpu/simple_thread.cc  Mon Jan 07 13:05:46 2013 -0500
+++ b/src/cpu/simple_thread.cc  Mon Jan 07 13:05:46 2013 -0500
@@ -107,49 +107,11 @@
 void
 SimpleThread::takeOverFrom(ThreadContext *oldContext)
 {
-    // some things should already be set up
-    if (FullSystem)
-        assert(system == oldContext->getSystemPtr());
-    assert(process == oldContext->getProcessPtr());
+    ::takeOverFrom(*tc, *oldContext);
 
-    copyState(oldContext);
-    if (FullSystem) {
-        EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
-        if (quiesce) {
-            // Point the quiesce event's TC at this TC so that it wakes up
-            // the proper CPU.
-            quiesce->tc = tc;
-        }
-        if (quiesceEvent) {
-            quiesceEvent->tc = tc;
-        }
-
-        TheISA::Kernel::Statistics *stats = oldContext->getKernelStats();
-        if (stats) {
-            kernelStats = stats;
-        }
-    }
-
+    kernelStats = oldContext->getKernelStats();
+    funcExeInst = oldContext->readFuncExeInst();
     storeCondFailures = 0;
-
-    oldContext->setStatus(ThreadContext::Halted);
-}
-
-void
-SimpleThread::copyTC(ThreadContext *context)
-{
-    copyState(context);
-
-    if (FullSystem) {
-        EndQuiesceEvent *quiesce = context->getQuiesceEvent();
-        if (quiesce) {
-            quiesceEvent = quiesce;
-        }
-        TheISA::Kernel::Statistics *stats = context->getKernelStats();
-        if (stats) {
-            kernelStats = stats;
-        }
-    }
 }
 
 void
diff -r fdc91cab5760 -r 1133617844c8 src/cpu/simple_thread.hh
--- a/src/cpu/simple_thread.hh  Mon Jan 07 13:05:46 2013 -0500
+++ b/src/cpu/simple_thread.hh  Mon Jan 07 13:05:46 2013 -0500
@@ -146,8 +146,6 @@
 
     void regStats(const std::string &name);
 
-    void copyTC(ThreadContext *context);
-
     void copyState(ThreadContext *oldContext);
 
     void serialize(std::ostream &os);
diff -r fdc91cab5760 -r 1133617844c8 src/cpu/thread_context.cc
--- a/src/cpu/thread_context.cc Mon Jan 07 13:05:46 2013 -0500
+++ b/src/cpu/thread_context.cc Mon Jan 07 13:05:46 2013 -0500
@@ -43,8 +43,11 @@
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "config/the_isa.hh"
+#include "cpu/base.hh"
+#include "cpu/quiesce_event.hh"
 #include "cpu/thread_context.hh"
 #include "debug/Context.hh"
+#include "sim/full_system.hh"
 
 void
 ThreadContext::compare(ThreadContext *one, ThreadContext *two)
@@ -136,3 +139,37 @@
 
     // thread_num and cpu_id are deterministic from the config
 }
+
+void
+takeOverFrom(ThreadContext &ntc, ThreadContext &otc)
+{
+    assert(ntc.getProcessPtr() == otc.getProcessPtr());
+
+    ntc.setStatus(otc.status());
+    ntc.copyArchRegs(&otc);
+    ntc.setContextId(otc.contextId());
+    ntc.setThreadId(otc.threadId());
+
+    if (FullSystem) {
+        assert(ntc.getSystemPtr() == otc.getSystemPtr());
+
+        BaseCPU *ncpu(ntc.getCpuPtr());
+        assert(ncpu);
+        EndQuiesceEvent *oqe(otc.getQuiesceEvent());
+        assert(oqe);
+        assert(oqe->tc == &otc);
+
+        BaseCPU *ocpu(otc.getCpuPtr());
+        assert(ocpu);
+        EndQuiesceEvent *nqe(ntc.getQuiesceEvent());
+        assert(nqe);
+        assert(nqe->tc == &ntc);
+
+        if (oqe->scheduled()) {
+            ncpu->schedule(nqe, oqe->when());
+            ocpu->deschedule(oqe);
+        }
+    }
+
+    otc.setStatus(ThreadContext::Halted);
+}
diff -r fdc91cab5760 -r 1133617844c8 src/cpu/thread_context.hh
--- a/src/cpu/thread_context.hh Mon Jan 07 13:05:46 2013 -0500
+++ b/src/cpu/thread_context.hh Mon Jan 07 13:05:46 2013 -0500
@@ -481,4 +481,17 @@
 
 /** @} */
 
+
+/**
+ * Copy state between thread contexts in preparation for CPU handover.
+ *
+ * @note This method modifies the old thread contexts as well as the
+ * new thread context. The old thread context will have its quiesce
+ * event descheduled if it is scheduled and its status set to halted.
+ *
+ * @param new_tc Destination ThreadContext.
+ * @param old_tc Source ThreadContext.
+ */
+void takeOverFrom(ThreadContext &new_tc, ThreadContext &old_tc);
+
 #endif
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to