+template <class Impl>
+void
+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());
+
+ // make sure the thread has not been added to the list yet
+ assert(exitingThreads.count(tid) == 0);
+
+ // add the thread to exitingThreads list to mark that this thread is
+ // trying to exit. The boolean value in the pair denotes if a thread is
+ // ready to exit. The thread is not ready to exit until the corresponding
+ // exit trap event is processed in the future. Until then, it'll be still
+ // an active thread that is trying to exit.
+ exitingThreads.emplace(std::make_pair(tid, false));
+}
+
+template <class Impl>
+bool
+FullO3CPU<Impl>::isThreadExiting(ThreadID tid) const
+{
+ return exitingThreads.count(tid) == 1;
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::scheduleThreadExitEvent(ThreadID tid)
+{
+ assert(exitingThreads.count(tid) == 1);
+
+ // exit trap event has been processed. Now, the thread is ready to exit
+ // and be removed from the CPU.
+ exitingThreads[tid] = true;
+
+ // we schedule a threadExitEvent in the next cycle to properly clean
+ // up the thread's states in the pipeline. threadExitEvent has lower
+ // priority than tickEvent, so the cleanup will happen at the very end
+ // of the next cycle after all pipeline stages complete their operations.
+ // We want all stages to complete squashing instructions before doing
+ // the cleanup.
+ if (!threadExitEvent.scheduled()) {
+ schedule(threadExitEvent, nextCycle());
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::exitThreads()
+{
+ // there must be at least one thread trying to exit
+ assert(exitingThreads.size() > 0);
+
+ // terminate all threads that are ready to exit
+ auto it = exitingThreads.begin();
+ while (it != exitingThreads.end()) {
+ ThreadID thread_id = it->first;
+ bool readyToExit = it->second;
+
+ if (readyToExit) {
+ DPRINTF(O3CPU, "Exiting thread %d\n", thread_id);
+ haltContext(thread_id);
+ tcBase(thread_id)->setStatus(ThreadContext::Halted);
+ it = exitingThreads.erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+