thread_context.hh revision 13622:ba31c2a23eca
1/* 2 * Copyright (c) 2011-2012, 2016-2018 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Kevin Lim 42 */ 43 44#ifndef __CPU_THREAD_CONTEXT_HH__ 45#define __CPU_THREAD_CONTEXT_HH__ 46 47#include <iostream> 48#include <string> 49 50#include "arch/registers.hh" 51#include "arch/types.hh" 52#include "base/types.hh" 53#include "config/the_isa.hh" 54#include "cpu/reg_class.hh" 55 56// @todo: Figure out a more architecture independent way to obtain the ITB and 57// DTB pointers. 58namespace TheISA 59{ 60 class Decoder; 61} 62class BaseCPU; 63class BaseTLB; 64class CheckerCPU; 65class Checkpoint; 66class EndQuiesceEvent; 67class SETranslatingPortProxy; 68class FSTranslatingPortProxy; 69class PortProxy; 70class Process; 71class System; 72namespace TheISA { 73 namespace Kernel { 74 class Statistics; 75 } 76} 77 78/** 79 * ThreadContext is the external interface to all thread state for 80 * anything outside of the CPU. It provides all accessor methods to 81 * state that might be needed by external objects, ranging from 82 * register values to things such as kernel stats. It is an abstract 83 * base class; the CPU can create its own ThreadContext by either 84 * deriving from it, or using the templated ProxyThreadContext. 85 * 86 * The ThreadContext is slightly different than the ExecContext. The 87 * ThreadContext provides access to an individual thread's state; an 88 * ExecContext provides ISA access to the CPU (meaning it is 89 * implicitly multithreaded on SMT systems). Additionally the 90 * ThreadState is an abstract class that exactly defines the 91 * interface; the ExecContext is a more implicit interface that must 92 * be implemented so that the ISA can access whatever state it needs. 93 */ 94class ThreadContext 95{ 96 protected: 97 typedef TheISA::MachInst MachInst; 98 using VecRegContainer = TheISA::VecRegContainer; 99 using VecElem = TheISA::VecElem; 100 using VecPredRegContainer = TheISA::VecPredRegContainer; 101 102 public: 103 104 enum Status 105 { 106 /// Running. Instructions should be executed only when 107 /// the context is in this state. 108 Active, 109 110 /// Temporarily inactive. Entered while waiting for 111 /// synchronization, etc. 112 Suspended, 113 114 /// Permanently shut down. Entered when target executes 115 /// m5exit pseudo-instruction. When all contexts enter 116 /// this state, the simulation will terminate. 117 Halted 118 }; 119 120 virtual ~ThreadContext() { }; 121 122 virtual BaseCPU *getCpuPtr() = 0; 123 124 virtual int cpuId() const = 0; 125 126 virtual uint32_t socketId() const = 0; 127 128 virtual int threadId() const = 0; 129 130 virtual void setThreadId(int id) = 0; 131 132 virtual int contextId() const = 0; 133 134 virtual void setContextId(int id) = 0; 135 136 virtual BaseTLB *getITBPtr() = 0; 137 138 virtual BaseTLB *getDTBPtr() = 0; 139 140 virtual CheckerCPU *getCheckerCpuPtr() = 0; 141 142 virtual TheISA::Decoder *getDecoderPtr() = 0; 143 144 virtual System *getSystemPtr() = 0; 145 146 virtual TheISA::Kernel::Statistics *getKernelStats() = 0; 147 148 virtual PortProxy &getPhysProxy() = 0; 149 150 virtual FSTranslatingPortProxy &getVirtProxy() = 0; 151 152 /** 153 * Initialise the physical and virtual port proxies and tie them to 154 * the data port of the CPU. 155 * 156 * tc ThreadContext for the virtual-to-physical translation 157 */ 158 virtual void initMemProxies(ThreadContext *tc) = 0; 159 160 virtual SETranslatingPortProxy &getMemProxy() = 0; 161 162 virtual Process *getProcessPtr() = 0; 163 164 virtual void setProcessPtr(Process *p) = 0; 165 166 virtual Status status() const = 0; 167 168 virtual void setStatus(Status new_status) = 0; 169 170 /// Set the status to Active. 171 virtual void activate() = 0; 172 173 /// Set the status to Suspended. 174 virtual void suspend() = 0; 175 176 /// Set the status to Halted. 177 virtual void halt() = 0; 178 179 /// Quiesce thread context 180 void quiesce(); 181 182 /// Quiesce, suspend, and schedule activate at resume 183 void quiesceTick(Tick resume); 184 185 virtual void dumpFuncProfile() = 0; 186 187 virtual void takeOverFrom(ThreadContext *old_context) = 0; 188 189 virtual void regStats(const std::string &name) = 0; 190 191 virtual EndQuiesceEvent *getQuiesceEvent() = 0; 192 193 // Not necessarily the best location for these... 194 // Having an extra function just to read these is obnoxious 195 virtual Tick readLastActivate() = 0; 196 virtual Tick readLastSuspend() = 0; 197 198 virtual void profileClear() = 0; 199 virtual void profileSample() = 0; 200 201 virtual void copyArchRegs(ThreadContext *tc) = 0; 202 203 virtual void clearArchRegs() = 0; 204 205 // 206 // New accessors for new decoder. 207 // 208 virtual RegVal readIntReg(int reg_idx) = 0; 209 210 virtual RegVal readFloatReg(int reg_idx) = 0; 211 212 virtual const VecRegContainer& readVecReg(const RegId& reg) const = 0; 213 virtual VecRegContainer& getWritableVecReg(const RegId& reg) = 0; 214 215 /** Vector Register Lane Interfaces. */ 216 /** @{ */ 217 /** Reads source vector 8bit operand. */ 218 virtual ConstVecLane8 219 readVec8BitLaneReg(const RegId& reg) const = 0; 220 221 /** Reads source vector 16bit operand. */ 222 virtual ConstVecLane16 223 readVec16BitLaneReg(const RegId& reg) const = 0; 224 225 /** Reads source vector 32bit operand. */ 226 virtual ConstVecLane32 227 readVec32BitLaneReg(const RegId& reg) const = 0; 228 229 /** Reads source vector 64bit operand. */ 230 virtual ConstVecLane64 231 readVec64BitLaneReg(const RegId& reg) const = 0; 232 233 /** Write a lane of the destination vector register. */ 234 virtual void setVecLane(const RegId& reg, 235 const LaneData<LaneSize::Byte>& val) = 0; 236 virtual void setVecLane(const RegId& reg, 237 const LaneData<LaneSize::TwoByte>& val) = 0; 238 virtual void setVecLane(const RegId& reg, 239 const LaneData<LaneSize::FourByte>& val) = 0; 240 virtual void setVecLane(const RegId& reg, 241 const LaneData<LaneSize::EightByte>& val) = 0; 242 /** @} */ 243 244 virtual const VecElem& readVecElem(const RegId& reg) const = 0; 245 246 virtual const VecPredRegContainer& readVecPredReg(const RegId& reg) 247 const = 0; 248 virtual VecPredRegContainer& getWritableVecPredReg(const RegId& reg) = 0; 249 250 virtual RegVal readCCReg(int reg_idx) = 0; 251 252 virtual void setIntReg(int reg_idx, RegVal val) = 0; 253 254 virtual void setFloatReg(int reg_idx, RegVal val) = 0; 255 256 virtual void setVecReg(const RegId& reg, const VecRegContainer& val) = 0; 257 258 virtual void setVecElem(const RegId& reg, const VecElem& val) = 0; 259 260 virtual void setVecPredReg(const RegId& reg, 261 const VecPredRegContainer& val) = 0; 262 263 virtual void setCCReg(int reg_idx, RegVal val) = 0; 264 265 virtual TheISA::PCState pcState() = 0; 266 267 virtual void pcState(const TheISA::PCState &val) = 0; 268 269 void 270 setNPC(Addr val) 271 { 272 TheISA::PCState pc_state = pcState(); 273 pc_state.setNPC(val); 274 pcState(pc_state); 275 } 276 277 virtual void pcStateNoRecord(const TheISA::PCState &val) = 0; 278 279 virtual Addr instAddr() = 0; 280 281 virtual Addr nextInstAddr() = 0; 282 283 virtual MicroPC microPC() = 0; 284 285 virtual RegVal readMiscRegNoEffect(int misc_reg) const = 0; 286 287 virtual RegVal readMiscReg(int misc_reg) = 0; 288 289 virtual void setMiscRegNoEffect(int misc_reg, RegVal val) = 0; 290 291 virtual void setMiscReg(int misc_reg, RegVal val) = 0; 292 293 virtual RegId flattenRegId(const RegId& regId) const = 0; 294 295 virtual RegVal 296 readRegOtherThread(const RegId& misc_reg, ThreadID tid) 297 { 298 return 0; 299 } 300 301 virtual void 302 setRegOtherThread(const RegId& misc_reg, RegVal val, ThreadID tid) 303 { 304 } 305 306 // Also not necessarily the best location for these two. Hopefully will go 307 // away once we decide upon where st cond failures goes. 308 virtual unsigned readStCondFailures() = 0; 309 310 virtual void setStCondFailures(unsigned sc_failures) = 0; 311 312 // Same with st cond failures. 313 virtual Counter readFuncExeInst() = 0; 314 315 virtual void syscall(int64_t callnum, Fault *fault) = 0; 316 317 // This function exits the thread context in the CPU and returns 318 // 1 if the CPU has no more active threads (meaning it's OK to exit); 319 // Used in syscall-emulation mode when a thread calls the exit syscall. 320 virtual int exit() { return 1; }; 321 322 /** function to compare two thread contexts (for debugging) */ 323 static void compare(ThreadContext *one, ThreadContext *two); 324 325 /** @{ */ 326 /** 327 * Flat register interfaces 328 * 329 * Some architectures have different registers visible in 330 * different modes. Such architectures "flatten" a register (see 331 * flattenRegId()) to map it into the 332 * gem5 register file. This interface provides a flat interface to 333 * the underlying register file, which allows for example 334 * serialization code to access all registers. 335 */ 336 337 virtual RegVal readIntRegFlat(int idx) = 0; 338 virtual void setIntRegFlat(int idx, RegVal val) = 0; 339 340 virtual RegVal readFloatRegFlat(int idx) = 0; 341 virtual void setFloatRegFlat(int idx, RegVal val) = 0; 342 343 virtual const VecRegContainer& readVecRegFlat(int idx) const = 0; 344 virtual VecRegContainer& getWritableVecRegFlat(int idx) = 0; 345 virtual void setVecRegFlat(int idx, const VecRegContainer& val) = 0; 346 347 virtual const VecElem& readVecElemFlat(const RegIndex& idx, 348 const ElemIndex& elemIdx) const = 0; 349 virtual void setVecElemFlat(const RegIndex& idx, const ElemIndex& elemIdx, 350 const VecElem& val) = 0; 351 352 virtual const VecPredRegContainer& readVecPredRegFlat(int idx) const = 0; 353 virtual VecPredRegContainer& getWritableVecPredRegFlat(int idx) = 0; 354 virtual void setVecPredRegFlat(int idx, 355 const VecPredRegContainer& val) = 0; 356 357 virtual RegVal readCCRegFlat(int idx) = 0; 358 virtual void setCCRegFlat(int idx, RegVal val) = 0; 359 /** @} */ 360 361}; 362 363/** 364 * ProxyThreadContext class that provides a way to implement a 365 * ThreadContext without having to derive from it. ThreadContext is an 366 * abstract class, so anything that derives from it and uses its 367 * interface will pay the overhead of virtual function calls. This 368 * class is created to enable a user-defined Thread object to be used 369 * wherever ThreadContexts are used, without paying the overhead of 370 * virtual function calls when it is used by itself. See 371 * simple_thread.hh for an example of this. 372 */ 373template <class TC> 374class ProxyThreadContext : public ThreadContext 375{ 376 public: 377 ProxyThreadContext(TC *actual_tc) 378 { actualTC = actual_tc; } 379 380 private: 381 TC *actualTC; 382 383 public: 384 385 BaseCPU *getCpuPtr() { return actualTC->getCpuPtr(); } 386 387 int cpuId() const { return actualTC->cpuId(); } 388 389 uint32_t socketId() const { return actualTC->socketId(); } 390 391 int threadId() const { return actualTC->threadId(); } 392 393 void setThreadId(int id) { actualTC->setThreadId(id); } 394 395 int contextId() const { return actualTC->contextId(); } 396 397 void setContextId(int id) { actualTC->setContextId(id); } 398 399 BaseTLB *getITBPtr() { return actualTC->getITBPtr(); } 400 401 BaseTLB *getDTBPtr() { return actualTC->getDTBPtr(); } 402 403 CheckerCPU *getCheckerCpuPtr() { return actualTC->getCheckerCpuPtr(); } 404 405 TheISA::Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); } 406 407 System *getSystemPtr() { return actualTC->getSystemPtr(); } 408 409 TheISA::Kernel::Statistics *getKernelStats() 410 { return actualTC->getKernelStats(); } 411 412 PortProxy &getPhysProxy() { return actualTC->getPhysProxy(); } 413 414 FSTranslatingPortProxy &getVirtProxy() { return actualTC->getVirtProxy(); } 415 416 void initMemProxies(ThreadContext *tc) { actualTC->initMemProxies(tc); } 417 418 SETranslatingPortProxy &getMemProxy() { return actualTC->getMemProxy(); } 419 420 Process *getProcessPtr() { return actualTC->getProcessPtr(); } 421 422 void setProcessPtr(Process *p) { actualTC->setProcessPtr(p); } 423 424 Status status() const { return actualTC->status(); } 425 426 void setStatus(Status new_status) { actualTC->setStatus(new_status); } 427 428 /// Set the status to Active. 429 void activate() { actualTC->activate(); } 430 431 /// Set the status to Suspended. 432 void suspend() { actualTC->suspend(); } 433 434 /// Set the status to Halted. 435 void halt() { actualTC->halt(); } 436 437 /// Quiesce thread context 438 void quiesce() { actualTC->quiesce(); } 439 440 /// Quiesce, suspend, and schedule activate at resume 441 void quiesceTick(Tick resume) { actualTC->quiesceTick(resume); } 442 443 void dumpFuncProfile() { actualTC->dumpFuncProfile(); } 444 445 void takeOverFrom(ThreadContext *oldContext) 446 { actualTC->takeOverFrom(oldContext); } 447 448 void regStats(const std::string &name) { actualTC->regStats(name); } 449 450 EndQuiesceEvent *getQuiesceEvent() { return actualTC->getQuiesceEvent(); } 451 452 Tick readLastActivate() { return actualTC->readLastActivate(); } 453 Tick readLastSuspend() { return actualTC->readLastSuspend(); } 454 455 void profileClear() { return actualTC->profileClear(); } 456 void profileSample() { return actualTC->profileSample(); } 457 458 // @todo: Do I need this? 459 void copyArchRegs(ThreadContext *tc) { actualTC->copyArchRegs(tc); } 460 461 void clearArchRegs() { actualTC->clearArchRegs(); } 462 463 // 464 // New accessors for new decoder. 465 // 466 RegVal readIntReg(int reg_idx) 467 { return actualTC->readIntReg(reg_idx); } 468 469 RegVal readFloatReg(int reg_idx) 470 { return actualTC->readFloatReg(reg_idx); } 471 472 const VecRegContainer& readVecReg(const RegId& reg) const 473 { return actualTC->readVecReg(reg); } 474 475 VecRegContainer& getWritableVecReg(const RegId& reg) 476 { return actualTC->getWritableVecReg(reg); } 477 478 /** Vector Register Lane Interfaces. */ 479 /** @{ */ 480 /** Reads source vector 8bit operand. */ 481 ConstVecLane8 482 readVec8BitLaneReg(const RegId& reg) const 483 { return actualTC->readVec8BitLaneReg(reg); } 484 485 /** Reads source vector 16bit operand. */ 486 ConstVecLane16 487 readVec16BitLaneReg(const RegId& reg) const 488 { return actualTC->readVec16BitLaneReg(reg); } 489 490 /** Reads source vector 32bit operand. */ 491 ConstVecLane32 492 readVec32BitLaneReg(const RegId& reg) const 493 { return actualTC->readVec32BitLaneReg(reg); } 494 495 /** Reads source vector 64bit operand. */ 496 ConstVecLane64 497 readVec64BitLaneReg(const RegId& reg) const 498 { return actualTC->readVec64BitLaneReg(reg); } 499 500 /** Write a lane of the destination vector register. */ 501 virtual void setVecLane(const RegId& reg, 502 const LaneData<LaneSize::Byte>& val) 503 { return actualTC->setVecLane(reg, val); } 504 virtual void setVecLane(const RegId& reg, 505 const LaneData<LaneSize::TwoByte>& val) 506 { return actualTC->setVecLane(reg, val); } 507 virtual void setVecLane(const RegId& reg, 508 const LaneData<LaneSize::FourByte>& val) 509 { return actualTC->setVecLane(reg, val); } 510 virtual void setVecLane(const RegId& reg, 511 const LaneData<LaneSize::EightByte>& val) 512 { return actualTC->setVecLane(reg, val); } 513 /** @} */ 514 515 const VecElem& readVecElem(const RegId& reg) const 516 { return actualTC->readVecElem(reg); } 517 518 const VecPredRegContainer& readVecPredReg(const RegId& reg) const 519 { return actualTC->readVecPredReg(reg); } 520 521 VecPredRegContainer& getWritableVecPredReg(const RegId& reg) 522 { return actualTC->getWritableVecPredReg(reg); } 523 524 RegVal readCCReg(int reg_idx) 525 { return actualTC->readCCReg(reg_idx); } 526 527 void setIntReg(int reg_idx, RegVal val) 528 { actualTC->setIntReg(reg_idx, val); } 529 530 void setFloatReg(int reg_idx, RegVal val) 531 { actualTC->setFloatReg(reg_idx, val); } 532 533 void setVecReg(const RegId& reg, const VecRegContainer& val) 534 { actualTC->setVecReg(reg, val); } 535 536 void setVecPredReg(const RegId& reg, const VecPredRegContainer& val) 537 { actualTC->setVecPredReg(reg, val); } 538 539 void setVecElem(const RegId& reg, const VecElem& val) 540 { actualTC->setVecElem(reg, val); } 541 542 void setCCReg(int reg_idx, RegVal val) 543 { actualTC->setCCReg(reg_idx, val); } 544 545 TheISA::PCState pcState() { return actualTC->pcState(); } 546 547 void pcState(const TheISA::PCState &val) { actualTC->pcState(val); } 548 549 void pcStateNoRecord(const TheISA::PCState &val) { actualTC->pcState(val); } 550 551 Addr instAddr() { return actualTC->instAddr(); } 552 Addr nextInstAddr() { return actualTC->nextInstAddr(); } 553 MicroPC microPC() { return actualTC->microPC(); } 554 555 bool readPredicate() { return actualTC->readPredicate(); } 556 557 void setPredicate(bool val) 558 { actualTC->setPredicate(val); } 559 560 RegVal readMiscRegNoEffect(int misc_reg) const 561 { return actualTC->readMiscRegNoEffect(misc_reg); } 562 563 RegVal readMiscReg(int misc_reg) 564 { return actualTC->readMiscReg(misc_reg); } 565 566 void setMiscRegNoEffect(int misc_reg, RegVal val) 567 { return actualTC->setMiscRegNoEffect(misc_reg, val); } 568 569 void setMiscReg(int misc_reg, RegVal val) 570 { return actualTC->setMiscReg(misc_reg, val); } 571 572 RegId flattenRegId(const RegId& regId) const 573 { return actualTC->flattenRegId(regId); } 574 575 unsigned readStCondFailures() 576 { return actualTC->readStCondFailures(); } 577 578 void setStCondFailures(unsigned sc_failures) 579 { actualTC->setStCondFailures(sc_failures); } 580 581 void syscall(int64_t callnum, Fault *fault) 582 { actualTC->syscall(callnum, fault); } 583 584 Counter readFuncExeInst() { return actualTC->readFuncExeInst(); } 585 586 RegVal readIntRegFlat(int idx) 587 { return actualTC->readIntRegFlat(idx); } 588 589 void setIntRegFlat(int idx, RegVal val) 590 { actualTC->setIntRegFlat(idx, val); } 591 592 RegVal readFloatRegFlat(int idx) 593 { return actualTC->readFloatRegFlat(idx); } 594 595 void setFloatRegFlat(int idx, RegVal val) 596 { actualTC->setFloatRegFlat(idx, val); } 597 598 const VecRegContainer& readVecRegFlat(int id) const 599 { return actualTC->readVecRegFlat(id); } 600 601 VecRegContainer& getWritableVecRegFlat(int id) 602 { return actualTC->getWritableVecRegFlat(id); } 603 604 void setVecRegFlat(int idx, const VecRegContainer& val) 605 { actualTC->setVecRegFlat(idx, val); } 606 607 const VecElem& readVecElemFlat(const RegIndex& id, 608 const ElemIndex& elemIndex) const 609 { return actualTC->readVecElemFlat(id, elemIndex); } 610 611 void setVecElemFlat(const RegIndex& id, const ElemIndex& elemIndex, 612 const VecElem& val) 613 { actualTC->setVecElemFlat(id, elemIndex, val); } 614 615 const VecPredRegContainer& readVecPredRegFlat(int id) const 616 { return actualTC->readVecPredRegFlat(id); } 617 618 VecPredRegContainer& getWritableVecPredRegFlat(int id) 619 { return actualTC->getWritableVecPredRegFlat(id); } 620 621 void setVecPredRegFlat(int idx, const VecPredRegContainer& val) 622 { actualTC->setVecPredRegFlat(idx, val); } 623 624 RegVal readCCRegFlat(int idx) 625 { return actualTC->readCCRegFlat(idx); } 626 627 void setCCRegFlat(int idx, RegVal val) 628 { actualTC->setCCRegFlat(idx, val); } 629}; 630 631/** @{ */ 632/** 633 * Thread context serialization helpers 634 * 635 * These helper functions provide a way to the data in a 636 * ThreadContext. They are provided as separate helper function since 637 * implementing them as members of the ThreadContext interface would 638 * be confusing when the ThreadContext is exported via a proxy. 639 */ 640 641void serialize(ThreadContext &tc, CheckpointOut &cp); 642void unserialize(ThreadContext &tc, CheckpointIn &cp); 643 644/** @} */ 645 646 647/** 648 * Copy state between thread contexts in preparation for CPU handover. 649 * 650 * @note This method modifies the old thread contexts as well as the 651 * new thread context. The old thread context will have its quiesce 652 * event descheduled if it is scheduled and its status set to halted. 653 * 654 * @param new_tc Destination ThreadContext. 655 * @param old_tc Source ThreadContext. 656 */ 657void takeOverFrom(ThreadContext &new_tc, ThreadContext &old_tc); 658 659#endif 660