summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
authorTuan Ta <qtt2@cornell.edu>2018-04-02 16:21:37 -0400
committerTuan Ta <qtt2@cornell.edu>2019-02-08 15:25:30 +0000
commitbae0edb0d26dc6c4738855cf38e9a6a109ae8003 (patch)
tree28d8e6ce42a1bcf2c908542ddaafa37c995461b2 /src/sim
parent72d1d2930fc2b8ef6d32ec2ce2eabbac00684159 (diff)
downloadgem5-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>
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/syscall_emul.cc75
-rw-r--r--src/sim/system.cc3
2 files changed, 51 insertions, 27 deletions
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));
}
);
}