diff options
author | Tuan Ta <qtt2@cornell.edu> | 2018-04-02 16:21:37 -0400 |
---|---|---|
committer | Tuan Ta <qtt2@cornell.edu> | 2019-02-08 15:25:30 +0000 |
commit | bae0edb0d26dc6c4738855cf38e9a6a109ae8003 (patch) | |
tree | 28d8e6ce42a1bcf2c908542ddaafa37c995461b2 | |
parent | 72d1d2930fc2b8ef6d32ec2ce2eabbac00684159 (diff) | |
download | gem5-bae0edb0d26dc6c4738855cf38e9a6a109ae8003.tar.xz |
sim,cpu: make exit_group halt all threads in a group
When a thread calls exit_group, in addition to halting the thread
itself, it needs to halt all other threads in its group (i.e., threads
sharing the same thread group ID). This patch enables threads to do
that.
Change-Id: Ib2e158fb27cf98843f177a64a2d643b1bbc94d03
Reviewed-on: https://gem5-review.googlesource.com/c/9623
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
-rw-r--r-- | src/cpu/o3/cpu.cc | 5 | ||||
-rw-r--r-- | src/sim/syscall_emul.cc | 75 | ||||
-rw-r--r-- | src/sim/system.cc | 3 |
3 files changed, 53 insertions, 30 deletions
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index e50741ec0..965ab04e0 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -1861,9 +1861,8 @@ FullO3CPU<Impl>::addThreadToExitingList(ThreadID tid) { DPRINTF(O3CPU, "Thread %d is inserted to exitingThreads list\n", tid); - // make sure the thread is Active - assert(std::find(activeThreads.begin(), activeThreads.end(), tid) - != activeThreads.end()); + // the thread trying to exit can't be already halted + assert(tcBase(tid)->status() != ThreadContext::Halted); // make sure the thread has not been added to the list yet assert(exitingThreads.count(tid) == 0); diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 25e0b6856..fbfe21a93 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -102,28 +102,6 @@ exitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, System *sys = tc->getSystemPtr(); - int activeContexts = 0; - for (auto &system: sys->systemList) - activeContexts += system->numRunningContexts(); - if (activeContexts == 1) { - /** - * Even though we are terminating the final thread context, dist-gem5 - * requires the simulation to remain active and provide - * synchronization messages to the switch process. So we just halt - * the last thread context and return. The simulation will be - * terminated by dist-gem5 in a coordinated manner once all nodes - * have signaled their readiness to exit. For non dist-gem5 - * simulations, readyToExit() always returns true. - */ - if (!DistIface::readyToExit(0)) { - tc->halt(); - return status; - } - - exitSimLoop("exiting with last active thread context", status & 0xff); - return status; - } - if (group) *p->exitGroup = true; @@ -146,16 +124,34 @@ exitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, if (walk->pid() == p->tgid()) tg_lead = walk; - if ((sys->threadContexts[i]->status() != ThreadContext::Halted) - && (walk != p)) { + if ((sys->threadContexts[i]->status() != ThreadContext::Halted) && + (sys->threadContexts[i]->status() != ThreadContext::Halting) && + (walk != p)) { /** * Check if we share thread group with the pointer; this denotes * that we are not the last thread active in the thread group. * Note that setting this to false also prevents further * iterations of the loop. */ - if (walk->tgid() == p->tgid()) - last_thread = false; + if (walk->tgid() == p->tgid()) { + /** + * If p is trying to exit_group and both walk and p are in + * the same thread group (i.e., sharing the same tgid), + * we need to halt walk's thread context. After all threads + * except p are halted, p becomes the last thread in the + * group. + * + * If p is not doing exit_group and there exists another + * active thread context in the group, last_thread is + * set to false to prevent the parent thread from killing + * all threads in the group. + */ + if (*(p->exitGroup)) { + sys->threadContexts[i]->halt(); + } else { + last_thread = false; + } + } /** * A corner case exists which involves execve(). After execve(), @@ -189,6 +185,33 @@ exitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, } tc->halt(); + + /** + * check to see if there is no more active thread in the system. If so, + * exit the simulation loop + */ + int activeContexts = 0; + for (auto &system: sys->systemList) + activeContexts += system->numRunningContexts(); + + if (activeContexts == 0) { + /** + * Even though we are terminating the final thread context, dist-gem5 + * requires the simulation to remain active and provide + * synchronization messages to the switch process. So we just halt + * the last thread context and return. The simulation will be + * terminated by dist-gem5 in a coordinated manner once all nodes + * have signaled their readiness to exit. For non dist-gem5 + * simulations, readyToExit() always returns true. + */ + if (!DistIface::readyToExit(0)) { + return status; + } + + exitSimLoop("exiting with last active thread context", status & 0xff); + return status; + } + return status; } diff --git a/src/sim/system.cc b/src/sim/system.cc index fc2578f86..ffa8edaa6 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -291,7 +291,8 @@ System::numRunningContexts() threadContexts.cbegin(), threadContexts.cend(), [] (ThreadContext* tc) { - return tc->status() != ThreadContext::Halted; + return ((tc->status() != ThreadContext::Halted) && + (tc->status() != ThreadContext::Halting)); } ); } |