sim: Move guts of quiesce and quiesceTick from ThreadContext to System.
The functions in ThreadContext are now just convenience wrappers. Change-Id: Ib56c4bdd27e611fb667a8056dfae37065f4034eb Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25145 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -129,30 +129,14 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
|
||||
void
|
||||
ThreadContext::quiesce()
|
||||
{
|
||||
DPRINTF(Quiesce, "%s: quiesce()\n", getCpuPtr()->name());
|
||||
|
||||
suspend();
|
||||
auto *workload = getSystemPtr()->workload;
|
||||
if (workload)
|
||||
workload->recordQuiesce();
|
||||
getSystemPtr()->threads.quiesce(contextId());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ThreadContext::quiesceTick(Tick resume)
|
||||
{
|
||||
BaseCPU *cpu = getCpuPtr();
|
||||
|
||||
EndQuiesceEvent *quiesceEvent = getQuiesceEvent();
|
||||
|
||||
cpu->reschedule(quiesceEvent, resume, true);
|
||||
|
||||
DPRINTF(Quiesce, "%s: quiesceTick until %lu\n", cpu->name(), resume);
|
||||
|
||||
suspend();
|
||||
auto *workload = getSystemPtr()->workload;
|
||||
if (workload)
|
||||
workload->recordQuiesce();
|
||||
getSystemPtr()->threads.quiesceTick(contextId(), resume);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -249,26 +233,8 @@ takeOverFrom(ThreadContext &ntc, ThreadContext &otc)
|
||||
ntc.setContextId(otc.contextId());
|
||||
ntc.setThreadId(otc.threadId());
|
||||
|
||||
if (FullSystem) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,32 @@ using namespace TheISA;
|
||||
|
||||
vector<System *> System::systemList;
|
||||
|
||||
void
|
||||
System::Threads::Thread::resume()
|
||||
{
|
||||
# if THE_ISA != NULL_ISA
|
||||
DPRINTFS(Quiesce, context->getCpuPtr(), "activating\n");
|
||||
context->activate();
|
||||
# endif
|
||||
}
|
||||
|
||||
std::string
|
||||
System::Threads::Thread::name() const
|
||||
{
|
||||
assert(context);
|
||||
return csprintf("%s.threads[%d]", context->getSystemPtr()->name(),
|
||||
context->contextId());
|
||||
}
|
||||
|
||||
void
|
||||
System::Threads::Thread::quiesce() const
|
||||
{
|
||||
context->suspend();
|
||||
auto *workload = context->getSystemPtr()->workload;
|
||||
if (workload)
|
||||
workload->recordQuiesce();
|
||||
}
|
||||
|
||||
ContextID
|
||||
System::Threads::insert(ThreadContext *tc, ContextID id)
|
||||
{
|
||||
@@ -88,12 +114,18 @@ System::Threads::insert(ThreadContext *tc, ContextID id)
|
||||
fatal_if(threads[id].context,
|
||||
"Cannot have two thread contexts with the same id (%d).", id);
|
||||
|
||||
auto *sys = tc->getSystemPtr();
|
||||
|
||||
auto &t = thread(id);
|
||||
t.context = tc;
|
||||
// Look up this thread again on resume, in case the threads vector has
|
||||
// been reallocated.
|
||||
t.resumeEvent = new EventFunctionWrapper(
|
||||
[this, id](){ thread(id).resume(); }, sys->name());
|
||||
# if THE_ISA != NULL_ISA
|
||||
int port = getRemoteGDBPort();
|
||||
if (port) {
|
||||
t.gdb = new RemoteGDB(tc->getSystemPtr(), tc, port + id);
|
||||
t.gdb = new RemoteGDB(sys, tc, port + id);
|
||||
t.gdb->listen();
|
||||
}
|
||||
# endif
|
||||
@@ -105,9 +137,17 @@ void
|
||||
System::Threads::replace(ThreadContext *tc, ContextID id)
|
||||
{
|
||||
auto &t = thread(id);
|
||||
t.context = tc;
|
||||
panic_if(!t.context, "Can't replace a context which doesn't exist.");
|
||||
if (t.gdb)
|
||||
t.gdb->replaceThreadContext(tc);
|
||||
# if THE_ISA != NULL_ISA
|
||||
if (t.resumeEvent->scheduled()) {
|
||||
Tick when = t.resumeEvent->when();
|
||||
t.context->getCpuPtr()->deschedule(t.resumeEvent);
|
||||
tc->getCpuPtr()->schedule(t.resumeEvent, when);
|
||||
}
|
||||
# endif
|
||||
t.context = tc;
|
||||
}
|
||||
|
||||
ThreadContext *
|
||||
@@ -134,6 +174,31 @@ System::Threads::numRunning() const
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
System::Threads::quiesce(ContextID id)
|
||||
{
|
||||
auto &t = thread(id);
|
||||
# if THE_ISA != NULL_ISA
|
||||
BaseCPU *cpu = t.context->getCpuPtr();
|
||||
DPRINTFS(Quiesce, cpu, "quiesce()\n");
|
||||
# endif
|
||||
t.quiesce();
|
||||
}
|
||||
|
||||
void
|
||||
System::Threads::quiesceTick(ContextID id, Tick when)
|
||||
{
|
||||
# if THE_ISA != NULL_ISA
|
||||
auto &t = thread(id);
|
||||
BaseCPU *cpu = t.context->getCpuPtr();
|
||||
|
||||
DPRINTFS(Quiesce, cpu, "quiesceTick until %u\n", when);
|
||||
t.quiesce();
|
||||
|
||||
cpu->reschedule(t.resumeEvent, when, true);
|
||||
# endif
|
||||
}
|
||||
|
||||
int System::numSystemsRunning = 0;
|
||||
|
||||
System::System(Params *p)
|
||||
@@ -363,6 +428,14 @@ System::serialize(CheckpointOut &cp) const
|
||||
{
|
||||
SERIALIZE_SCALAR(pagePtr);
|
||||
|
||||
for (auto &t: threads.threads) {
|
||||
Tick when = 0;
|
||||
if (t.resumeEvent && t.resumeEvent->scheduled())
|
||||
when = t.resumeEvent->when();
|
||||
ContextID id = t.context->contextId();
|
||||
paramOut(cp, csprintf("quiesceEndTick_%d", id), when);
|
||||
}
|
||||
|
||||
// also serialize the memories in the system
|
||||
physmem.serializeSection(cp, "physmem");
|
||||
}
|
||||
@@ -373,6 +446,18 @@ System::unserialize(CheckpointIn &cp)
|
||||
{
|
||||
UNSERIALIZE_SCALAR(pagePtr);
|
||||
|
||||
for (auto &t: threads.threads) {
|
||||
Tick when;
|
||||
ContextID id = t.context->contextId();
|
||||
if (!optParamIn(cp, csprintf("quiesceEndTick_%d", id), when) ||
|
||||
!when || !t.resumeEvent) {
|
||||
continue;
|
||||
}
|
||||
# if THE_ISA != NULL_ISA
|
||||
t.context->getCpuPtr()->schedule(t.resumeEvent, when);
|
||||
# endif
|
||||
}
|
||||
|
||||
// also unserialize the memories in the system
|
||||
physmem.unserializeSection(cp, "physmem");
|
||||
}
|
||||
|
||||
@@ -108,6 +108,11 @@ class System : public SimObject, public PCEventScope
|
||||
ThreadContext *context = nullptr;
|
||||
bool active = false;
|
||||
BaseRemoteGDB *gdb = nullptr;
|
||||
Event *resumeEvent = nullptr;
|
||||
|
||||
void resume();
|
||||
std::string name() const;
|
||||
void quiesce() const;
|
||||
};
|
||||
|
||||
std::vector<Thread> threads;
|
||||
@@ -207,7 +212,8 @@ class System : public SimObject, public PCEventScope
|
||||
return count;
|
||||
}
|
||||
|
||||
void resume(ContextID id, Tick when);
|
||||
void quiesce(ContextID id);
|
||||
void quiesceTick(ContextID id, Tick when);
|
||||
|
||||
const_iterator begin() const { return const_iterator(*this, 0); }
|
||||
const_iterator end() const { return const_iterator(*this, size()); }
|
||||
|
||||
Reference in New Issue
Block a user