simple_thread.cc revision 5606:6da7a58b0bc8
17949SN/A/* 212230Sgiacomo.travaglini@arm.com * Copyright (c) 2001-2006 The Regents of The University of Michigan 37949SN/A * All rights reserved. 47949SN/A * 57949SN/A * Redistribution and use in source and binary forms, with or without 67949SN/A * modification, are permitted provided that the following conditions are 77949SN/A * met: redistributions of source code must retain the above copyright 87949SN/A * notice, this list of conditions and the following disclaimer; 97949SN/A * redistributions in binary form must reproduce the above copyright 107949SN/A * notice, this list of conditions and the following disclaimer in the 117949SN/A * documentation and/or other materials provided with the distribution; 127949SN/A * neither the name of the copyright holders nor the names of its 137949SN/A * contributors may be used to endorse or promote products derived from 147949SN/A * this software without specific prior written permission. 157949SN/A * 167949SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177949SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187949SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197949SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207949SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217949SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227949SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237949SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247949SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257949SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267949SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277949SN/A * 287949SN/A * Authors: Steve Reinhardt 297949SN/A * Nathan Binkert 307949SN/A * Lisa Hsu 317949SN/A * Kevin Lim 327949SN/A */ 337949SN/A 347949SN/A#include <string> 357949SN/A 367949SN/A#include "arch/isa_traits.hh" 377949SN/A#include "cpu/base.hh" 387949SN/A#include "cpu/simple_thread.hh" 397949SN/A#include "cpu/thread_context.hh" 407949SN/A#include "params/BaseCPU.hh" 417949SN/A 429330Schander.sudanthi@arm.com#if FULL_SYSTEM 437949SN/A#include "arch/kernel_stats.hh" 447949SN/A#include "arch/stacktrace.hh" 4511793Sbrandon.potter@amd.com#include "base/callback.hh" 4611793Sbrandon.potter@amd.com#include "base/cprintf.hh" 478635SN/A#include "base/output.hh" 487949SN/A#include "base/trace.hh" 4912334Sgabeblack@google.com#include "cpu/profile.hh" 5011800Sbrandon.potter@amd.com#include "cpu/quiesce_event.hh" 5112230Sgiacomo.travaglini@arm.com#include "sim/serialize.hh" 529356Snilay@cs.wisc.edu#include "sim/sim_exit.hh" 538232SN/A#else 547949SN/A#include "mem/translating_port.hh" 557949SN/A#include "sim/process.hh" 567949SN/A#include "sim/system.hh" 579330Schander.sudanthi@arm.com#endif 589330Schander.sudanthi@arm.com 5910839Sandreas.sandberg@arm.comusing namespace std; 6010839Sandreas.sandberg@arm.com 6110839Sandreas.sandberg@arm.com// constructor 6212230Sgiacomo.travaglini@arm.com#if FULL_SYSTEM 6312230Sgiacomo.travaglini@arm.comSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, 647949SN/A TheISA::ITB *_itb, TheISA::DTB *_dtb, 658635SN/A bool use_kernel_stats) 668635SN/A : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb), 678635SN/A dtb(_dtb) 688635SN/A 698635SN/A{ 708635SN/A tc = new ProxyThreadContext<SimpleThread>(this); 718635SN/A 728635SN/A quiesceEvent = new EndQuiesceEvent(tc); 737949SN/A 747949SN/A regs.clear(); 757949SN/A 7610839Sandreas.sandberg@arm.com if (cpu->params()->profile) { 777949SN/A profile = new FunctionProfile(system->kernelSymtab); 7810839Sandreas.sandberg@arm.com Callback *cb = 7910839Sandreas.sandberg@arm.com new MakeCallback<SimpleThread, 807949SN/A &SimpleThread::dumpFuncProfile>(this); 8110839Sandreas.sandberg@arm.com registerExitCallback(cb); 8210839Sandreas.sandberg@arm.com } 8312230Sgiacomo.travaglini@arm.com 8412230Sgiacomo.travaglini@arm.com // let's fill with a dummy node for now so we don't get a segfault 8512230Sgiacomo.travaglini@arm.com // on the first cycle when there's no node available. 8612230Sgiacomo.travaglini@arm.com static ProfileNode dummyNode; 8712230Sgiacomo.travaglini@arm.com profileNode = &dummyNode; 8810839Sandreas.sandberg@arm.com profilePC = 3; 8910839Sandreas.sandberg@arm.com 9010839Sandreas.sandberg@arm.com if (use_kernel_stats) 9110839Sandreas.sandberg@arm.com kernelStats = new TheISA::Kernel::Statistics(system); 9210839Sandreas.sandberg@arm.com} 9310839Sandreas.sandberg@arm.com#else 9410839Sandreas.sandberg@arm.comSimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, 9510839Sandreas.sandberg@arm.com TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid) 9610839Sandreas.sandberg@arm.com : ThreadState(_cpu, -1, _thread_num, _process, _asid), 9710839Sandreas.sandberg@arm.com cpu(_cpu), itb(_itb), dtb(_dtb) 9810839Sandreas.sandberg@arm.com{ 9910839Sandreas.sandberg@arm.com regs.clear(); 10010839Sandreas.sandberg@arm.com tc = new ProxyThreadContext<SimpleThread>(this); 10110839Sandreas.sandberg@arm.com} 10210839Sandreas.sandberg@arm.com 10310839Sandreas.sandberg@arm.com#endif 1047949SN/A 1057949SN/ASimpleThread::SimpleThread() 1067949SN/A#if FULL_SYSTEM 10710839Sandreas.sandberg@arm.com : ThreadState(NULL, -1, -1) 10810839Sandreas.sandberg@arm.com#else 1097949SN/A : ThreadState(NULL, -1, -1, NULL, -1) 11010839Sandreas.sandberg@arm.com#endif 11110839Sandreas.sandberg@arm.com{ 1127949SN/A tc = new ProxyThreadContext<SimpleThread>(this); 1137949SN/A regs.clear(); 1148635SN/A} 1159330Schander.sudanthi@arm.com 1168635SN/ASimpleThread::~SimpleThread() 11712230Sgiacomo.travaglini@arm.com{ 1188635SN/A#if FULL_SYSTEM 1198635SN/A delete physPort; 12010839Sandreas.sandberg@arm.com delete virtPort; 1218635SN/A#endif 1228635SN/A delete tc; 1238635SN/A} 1248635SN/A 1258635SN/Avoid 1268635SN/ASimpleThread::takeOverFrom(ThreadContext *oldContext) 12712230Sgiacomo.travaglini@arm.com{ 12812230Sgiacomo.travaglini@arm.com // some things should already be set up 12912230Sgiacomo.travaglini@arm.com#if FULL_SYSTEM 1308635SN/A assert(system == oldContext->getSystemPtr()); 1318635SN/A#else 1328635SN/A assert(process == oldContext->getProcessPtr()); 13311359Sandreas@sandberg.pp.se#endif 13412230Sgiacomo.travaglini@arm.com 13511359Sandreas@sandberg.pp.se copyState(oldContext); 1368635SN/A#if FULL_SYSTEM 1378635SN/A EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent(); 1388635SN/A if (quiesce) { 1399330Schander.sudanthi@arm.com // Point the quiesce event's TC at this TC so that it wakes up 1409330Schander.sudanthi@arm.com // the proper CPU. 1419330Schander.sudanthi@arm.com quiesce->tc = tc; 1429330Schander.sudanthi@arm.com } 1439330Schander.sudanthi@arm.com if (quiesceEvent) { 1449330Schander.sudanthi@arm.com quiesceEvent->tc = tc; 1459330Schander.sudanthi@arm.com } 146 147 TheISA::Kernel::Statistics *stats = oldContext->getKernelStats(); 148 if (stats) { 149 kernelStats = stats; 150 } 151#endif 152 153 storeCondFailures = 0; 154 155 oldContext->setStatus(ThreadContext::Unallocated); 156} 157 158void 159SimpleThread::copyTC(ThreadContext *context) 160{ 161 copyState(context); 162 163#if FULL_SYSTEM 164 EndQuiesceEvent *quiesce = context->getQuiesceEvent(); 165 if (quiesce) { 166 quiesceEvent = quiesce; 167 } 168 TheISA::Kernel::Statistics *stats = context->getKernelStats(); 169 if (stats) { 170 kernelStats = stats; 171 } 172#endif 173} 174 175void 176SimpleThread::copyState(ThreadContext *oldContext) 177{ 178 // copy over functional state 179 _status = oldContext->status(); 180 copyArchRegs(oldContext); 181 cpuId = oldContext->readCpuId(); 182#if !FULL_SYSTEM 183 funcExeInst = oldContext->readFuncExeInst(); 184#endif 185 inst = oldContext->getInst(); 186} 187 188void 189SimpleThread::serialize(ostream &os) 190{ 191 ThreadState::serialize(os); 192 regs.serialize(cpu, os); 193 // thread_num and cpu_id are deterministic from the config 194} 195 196 197void 198SimpleThread::unserialize(Checkpoint *cp, const std::string §ion) 199{ 200 ThreadState::unserialize(cp, section); 201 regs.unserialize(cpu, cp, section); 202 // thread_num and cpu_id are deterministic from the config 203} 204 205#if FULL_SYSTEM 206void 207SimpleThread::dumpFuncProfile() 208{ 209 std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 210 profile->dump(tc, *os); 211} 212#endif 213 214void 215SimpleThread::activate(int delay) 216{ 217 if (status() == ThreadContext::Active) 218 return; 219 220 lastActivate = curTick; 221 222// if (status() == ThreadContext::Unallocated) { 223// cpu->activateWhenReady(tid); 224// return; 225// } 226 227 _status = ThreadContext::Active; 228 229 // status() == Suspended 230 cpu->activateContext(tid, delay); 231} 232 233void 234SimpleThread::suspend() 235{ 236 if (status() == ThreadContext::Suspended) 237 return; 238 239 lastActivate = curTick; 240 lastSuspend = curTick; 241/* 242#if FULL_SYSTEM 243 // Don't change the status from active if there are pending interrupts 244 if (cpu->check_interrupts()) { 245 assert(status() == ThreadContext::Active); 246 return; 247 } 248#endif 249*/ 250 _status = ThreadContext::Suspended; 251 cpu->suspendContext(tid); 252} 253 254void 255SimpleThread::deallocate() 256{ 257 if (status() == ThreadContext::Unallocated) 258 return; 259 260 _status = ThreadContext::Unallocated; 261 cpu->deallocateContext(tid); 262} 263 264void 265SimpleThread::halt() 266{ 267 if (status() == ThreadContext::Halted) 268 return; 269 270 _status = ThreadContext::Halted; 271 cpu->haltContext(tid); 272} 273 274 275void 276SimpleThread::regStats(const string &name) 277{ 278#if FULL_SYSTEM 279 if (kernelStats) 280 kernelStats->regStats(name + ".kern"); 281#endif 282} 283 284void 285SimpleThread::copyArchRegs(ThreadContext *src_tc) 286{ 287 TheISA::copyRegs(src_tc, tc); 288} 289 290