simple_thread.cc revision 5482
1955SN/A/* 2955SN/A * Copyright (c) 2001-2006 The Regents of The University of Michigan 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt 292665Ssaidi@eecs.umich.edu * Nathan Binkert 30955SN/A * Lisa Hsu 31955SN/A * Kevin Lim 32955SN/A */ 331608SN/A 34955SN/A#include <string> 35955SN/A 36955SN/A#include "arch/isa_traits.hh" 37955SN/A#include "cpu/base.hh" 38955SN/A#include "cpu/simple_thread.hh" 39955SN/A#include "cpu/thread_context.hh" 40955SN/A 41955SN/A#if FULL_SYSTEM 42955SN/A#include "arch/kernel_stats.hh" 43955SN/A#include "base/callback.hh" 44955SN/A#include "base/cprintf.hh" 45955SN/A#include "base/output.hh" 46955SN/A#include "base/trace.hh" 47955SN/A#include "cpu/profile.hh" 482023SN/A#include "cpu/quiesce_event.hh" 49955SN/A#include "sim/serialize.hh" 50955SN/A#include "sim/sim_exit.hh" 51955SN/A#include "arch/stacktrace.hh" 52955SN/A#else 53955SN/A#include "sim/process.hh" 54955SN/A#include "sim/system.hh" 55955SN/A#include "mem/translating_port.hh" 56955SN/A#endif 57955SN/A 581031SN/Ausing namespace std; 59955SN/A 601388SN/A// constructor 61955SN/A#if FULL_SYSTEM 62955SN/ASimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, 631296SN/A TheISA::ITB *_itb, TheISA::DTB *_dtb, 64955SN/A bool use_kernel_stats) 652609SN/A : ThreadState(_cpu, -1, _thread_num), cpu(_cpu), system(_sys), itb(_itb), 66955SN/A dtb(_dtb) 67955SN/A 68955SN/A{ 69955SN/A tc = new ProxyThreadContext<SimpleThread>(this); 70955SN/A 71955SN/A quiesceEvent = new EndQuiesceEvent(tc); 72955SN/A 73955SN/A regs.clear(); 74955SN/A 75955SN/A if (cpu->params->profile) { 76955SN/A profile = new FunctionProfile(system->kernelSymtab); 77955SN/A Callback *cb = 78955SN/A new MakeCallback<SimpleThread, 79955SN/A &SimpleThread::dumpFuncProfile>(this); 80955SN/A registerExitCallback(cb); 81955SN/A } 82955SN/A 83955SN/A // let's fill with a dummy node for now so we don't get a segfault 841717SN/A // on the first cycle when there's no node available. 852190SN/A static ProfileNode dummyNode; 862652Ssaidi@eecs.umich.edu profileNode = &dummyNode; 87955SN/A profilePC = 3; 882410SN/A 89955SN/A if (use_kernel_stats) 90955SN/A kernelStats = new TheISA::Kernel::Statistics(system); 911717SN/A} 922568SN/A#else 932568SN/ASimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, 942568SN/A TheISA::ITB *_itb, TheISA::DTB *_dtb, int _asid) 952499SN/A : ThreadState(_cpu, -1, _thread_num, _process, _asid), 962462SN/A cpu(_cpu), itb(_itb), dtb(_dtb) 972568SN/A{ 982395SN/A regs.clear(); 992405SN/A tc = new ProxyThreadContext<SimpleThread>(this); 100955SN/A} 101955SN/A 102955SN/A#endif 103955SN/A 104955SN/ASimpleThread::SimpleThread() 1052090SN/A#if FULL_SYSTEM 106955SN/A : ThreadState(NULL, -1, -1) 1072667Sstever@eecs.umich.edu#else 108955SN/A : ThreadState(NULL, -1, -1, NULL, -1) 109955SN/A#endif 1101696SN/A{ 111955SN/A tc = new ProxyThreadContext<SimpleThread>(this); 112955SN/A regs.clear(); 113955SN/A} 1141127SN/A 115955SN/ASimpleThread::~SimpleThread() 116955SN/A{ 1172379SN/A#if FULL_SYSTEM 118955SN/A delete physPort; 119955SN/A delete virtPort; 120955SN/A#endif 1212155SN/A delete tc; 1222155SN/A} 1232155SN/A 1242155SN/Avoid 1252155SN/ASimpleThread::takeOverFrom(ThreadContext *oldContext) 1262155SN/A{ 1272155SN/A // some things should already be set up 1282155SN/A#if FULL_SYSTEM 1292155SN/A assert(system == oldContext->getSystemPtr()); 1302155SN/A#else 1312155SN/A assert(process == oldContext->getProcessPtr()); 1322155SN/A#endif 1332155SN/A 1342155SN/A copyState(oldContext); 1352155SN/A#if FULL_SYSTEM 1362155SN/A EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent(); 1372155SN/A if (quiesce) { 1382155SN/A // Point the quiesce event's TC at this TC so that it wakes up 1392155SN/A // the proper CPU. 1402155SN/A quiesce->tc = tc; 1412155SN/A } 1422155SN/A if (quiesceEvent) { 1432155SN/A quiesceEvent->tc = tc; 1442155SN/A } 1452155SN/A 1462155SN/A TheISA::Kernel::Statistics *stats = oldContext->getKernelStats(); 1472155SN/A if (stats) { 1482155SN/A kernelStats = stats; 1492155SN/A } 1502155SN/A#endif 1512155SN/A 1522155SN/A storeCondFailures = 0; 1532155SN/A 1542155SN/A oldContext->setStatus(ThreadContext::Unallocated); 1552155SN/A} 1562155SN/A 1572155SN/Avoid 1582155SN/ASimpleThread::copyTC(ThreadContext *context) 1592155SN/A{ 1602422SN/A copyState(context); 1612422SN/A 1622422SN/A#if FULL_SYSTEM 1632422SN/A EndQuiesceEvent *quiesce = context->getQuiesceEvent(); 1642422SN/A if (quiesce) { 1652422SN/A quiesceEvent = quiesce; 1662422SN/A } 1672397SN/A TheISA::Kernel::Statistics *stats = context->getKernelStats(); 1682397SN/A if (stats) { 1692422SN/A kernelStats = stats; 1702422SN/A } 171955SN/A#endif 172955SN/A} 173955SN/A 174955SN/Avoid 175955SN/ASimpleThread::copyState(ThreadContext *oldContext) 176955SN/A{ 177955SN/A // copy over functional state 178955SN/A _status = oldContext->status(); 1791078SN/A copyArchRegs(oldContext); 180955SN/A cpuId = oldContext->readCpuId(); 181955SN/A#if !FULL_SYSTEM 182955SN/A funcExeInst = oldContext->readFuncExeInst(); 183955SN/A#endif 1841917SN/A inst = oldContext->getInst(); 185955SN/A} 186955SN/A 187955SN/Avoid 188955SN/ASimpleThread::serialize(ostream &os) 189974SN/A{ 190955SN/A ThreadState::serialize(os); 191955SN/A regs.serialize(os); 192955SN/A // thread_num and cpu_id are deterministic from the config 193955SN/A} 1942566SN/A 1952566SN/A 196955SN/Avoid 197955SN/ASimpleThread::unserialize(Checkpoint *cp, const std::string §ion) 1982539SN/A{ 199955SN/A ThreadState::unserialize(cp, section); 200955SN/A regs.unserialize(cp, section); 201955SN/A // thread_num and cpu_id are deterministic from the config 2021817SN/A} 2031154SN/A 2041840SN/A#if FULL_SYSTEM 2052522SN/Avoid 2062522SN/ASimpleThread::dumpFuncProfile() 2072629SN/A{ 208955SN/A std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); 209955SN/A profile->dump(tc, *os); 210955SN/A} 2112539SN/A#endif 212955SN/A 2132539SN/Avoid 214955SN/ASimpleThread::activate(int delay) 2151730SN/A{ 216955SN/A if (status() == ThreadContext::Active) 2171070SN/A return; 218955SN/A 219955SN/A lastActivate = curTick; 2202212SN/A 221955SN/A// if (status() == ThreadContext::Unallocated) { 2221040SN/A// cpu->activateWhenReady(tid); 2232507SN/A// return; 2242521SN/A// } 2252521SN/A 2262507SN/A _status = ThreadContext::Active; 2272507SN/A 2282507SN/A // status() == Suspended 2292521SN/A cpu->activateContext(tid, delay); 2302507SN/A} 2312507SN/A 232955SN/Avoid 233955SN/ASimpleThread::suspend() 234955SN/A{ 235955SN/A if (status() == ThreadContext::Suspended) 236955SN/A return; 237955SN/A 2381742SN/A lastActivate = curTick; 2391742SN/A lastSuspend = curTick; 2401742SN/A/* 2411742SN/A#if FULL_SYSTEM 2421742SN/A // Don't change the status from active if there are pending interrupts 2431742SN/A if (cpu->check_interrupts()) { 2441742SN/A assert(status() == ThreadContext::Active); 2451742SN/A return; 2461742SN/A } 2471742SN/A#endif 2481742SN/A*/ 2491742SN/A _status = ThreadContext::Suspended; 2501742SN/A cpu->suspendContext(tid); 2511742SN/A} 2521742SN/A 2531742SN/Avoid 2541742SN/ASimpleThread::deallocate() 2551742SN/A{ 2561742SN/A if (status() == ThreadContext::Unallocated) 2571742SN/A return; 258955SN/A 259955SN/A _status = ThreadContext::Unallocated; 2602520SN/A cpu->deallocateContext(tid); 2612517SN/A} 2622253SN/A 2632253SN/Avoid 2642253SN/ASimpleThread::halt() 2652253SN/A{ 2662553SN/A if (status() == ThreadContext::Halted) 2672553SN/A return; 2682553SN/A 2692553SN/A _status = ThreadContext::Halted; 2702507SN/A cpu->haltContext(tid); 2712470SN/A} 2721744SN/A 2731744SN/A 2742470SN/Avoid 2752470SN/ASimpleThread::regStats(const string &name) 2762470SN/A{ 2772470SN/A#if FULL_SYSTEM 2782470SN/A if (kernelStats) 2792470SN/A kernelStats->regStats(name + ".kern"); 2802400SN/A#endif 2812400SN/A} 282955SN/A 283955SN/Avoid 2842667Sstever@eecs.umich.eduSimpleThread::copyArchRegs(ThreadContext *src_tc) 2852667Sstever@eecs.umich.edu{ 2862667Sstever@eecs.umich.edu TheISA::copyRegs(src_tc, tc); 2872667Sstever@eecs.umich.edu} 2882667Sstever@eecs.umich.edu 2892667Sstever@eecs.umich.edu#if FULL_SYSTEM 2902037SN/AVirtualPort* 2912037SN/ASimpleThread::getVirtPort(ThreadContext *src_tc) 2922037SN/A{ 2932667Sstever@eecs.umich.edu if (!src_tc) 2942139SN/A return virtPort; 2952667Sstever@eecs.umich.edu 2962155SN/A VirtualPort *vp = new VirtualPort("tc-vport", src_tc); 2972155SN/A connectToMemFunc(vp); 2982155SN/A return vp; 2992155SN/A} 3002155SN/A 3012155SN/Avoid 302955SN/ASimpleThread::delVirtPort(VirtualPort *vp) 3032155SN/A{ 304955SN/A if (vp != virtPort) { 305955SN/A vp->removeConn(); 306955SN/A delete vp; 3071742SN/A } 3081742SN/A} 309955SN/A 310955SN/A#endif 311955SN/A 3121858SN/A