diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index 2990430e1..aab8c226a 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -93,18 +93,10 @@ InOrderThreadContext::profileSample() 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 --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 0a8dfeb3e..6de5c5731 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -66,34 +66,10 @@ template void O3ThreadContext::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 --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 787680224..9cf8da7b4 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -107,49 +107,11 @@ SimpleThread::~SimpleThread() void SimpleThread::takeOverFrom(ThreadContext *oldContext) { - // some things should already be set up - if (FullSystem) - assert(system == oldContext->getSystemPtr()); - assert(process == oldContext->getProcessPtr()); - - 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; - } - } + ::takeOverFrom(*tc, *oldContext); + 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 --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index ee54850ae..6f1173b7f 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -146,8 +146,6 @@ class SimpleThread : public ThreadState void regStats(const std::string &name); - void copyTC(ThreadContext *context); - void copyState(ThreadContext *oldContext); void serialize(std::ostream &os); diff --git a/src/cpu/thread_context.cc b/src/cpu/thread_context.cc index 4a4038297..a5a05a264 100644 --- a/src/cpu/thread_context.cc +++ b/src/cpu/thread_context.cc @@ -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 @@ unserialize(ThreadContext &tc, Checkpoint *cp, const std::string §ion) // 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 --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index c54076c8a..dbe3c0ce8 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -481,4 +481,17 @@ void unserialize(ThreadContext &tc, Checkpoint *cp, const std::string §ion); /** @} */ + +/** + * 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