process.cc revision 13087:1df34ed84a4b
112854Sgabeblack@google.com/* 212854Sgabeblack@google.com * Copyright 2018 Google, Inc. 312854Sgabeblack@google.com * 412854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 512854Sgabeblack@google.com * modification, are permitted provided that the following conditions are 612854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 712854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 812854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 912854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1012854Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1112854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1212854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1312854Sgabeblack@google.com * this software without specific prior written permission. 1412854Sgabeblack@google.com * 1512854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612854Sgabeblack@google.com * 2712854Sgabeblack@google.com * Authors: Gabe Black 2812854Sgabeblack@google.com */ 2912854Sgabeblack@google.com 3012854Sgabeblack@google.com#include "systemc/core/process.hh" 3112854Sgabeblack@google.com 3212854Sgabeblack@google.com#include "base/logging.hh" 3312854Sgabeblack@google.com#include "systemc/core/event.hh" 3412854Sgabeblack@google.com#include "systemc/core/scheduler.hh" 3512854Sgabeblack@google.com#include "systemc/ext/core/sc_process_handle.hh" 3612854Sgabeblack@google.com#include "systemc/ext/utils/sc_report_handler.hh" 3712854Sgabeblack@google.com 3812854Sgabeblack@google.comnamespace sc_gem5 3912854Sgabeblack@google.com{ 4012854Sgabeblack@google.com 4112854Sgabeblack@google.comSensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) : 4212854Sgabeblack@google.com Sensitivity(p), timeoutEvent([this]() { this->timeout(); }) 4312854Sgabeblack@google.com{ 4412854Sgabeblack@google.com scheduler.schedule(&timeoutEvent, t); 4512854Sgabeblack@google.com} 4612854Sgabeblack@google.com 4712854Sgabeblack@google.comSensitivityTimeout::~SensitivityTimeout() 4812854Sgabeblack@google.com{ 4912854Sgabeblack@google.com if (timeoutEvent.scheduled()) 5012854Sgabeblack@google.com scheduler.deschedule(&timeoutEvent); 5112854Sgabeblack@google.com} 5212854Sgabeblack@google.com 5312854Sgabeblack@google.comvoid 5412854Sgabeblack@google.comSensitivityTimeout::timeout() 5512854Sgabeblack@google.com{ 5612854Sgabeblack@google.com notify(); 5712854Sgabeblack@google.com} 5812854Sgabeblack@google.com 5912854Sgabeblack@google.comSensitivityEvent::SensitivityEvent( 6012854Sgabeblack@google.com Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e) 6112854Sgabeblack@google.com{ 6212854Sgabeblack@google.com Event::getFromScEvent(event)->addSensitivity(this); 6312854Sgabeblack@google.com} 6412854Sgabeblack@google.com 6512854Sgabeblack@google.comSensitivityEvent::~SensitivityEvent() 6612854Sgabeblack@google.com{ 6712854Sgabeblack@google.com Event::getFromScEvent(event)->delSensitivity(this); 6812854Sgabeblack@google.com} 6912854Sgabeblack@google.com 7012854Sgabeblack@google.comSensitivityEventAndList::SensitivityEventAndList( 7112854Sgabeblack@google.com Process *p, const ::sc_core::sc_event_and_list *list) : 7212854Sgabeblack@google.com Sensitivity(p), list(list), count(0) 7312854Sgabeblack@google.com{ 7412854Sgabeblack@google.com for (auto e: list->events) 7512854Sgabeblack@google.com Event::getFromScEvent(e)->addSensitivity(this); 7612854Sgabeblack@google.com} 7712854Sgabeblack@google.com 7812854Sgabeblack@google.comSensitivityEventAndList::~SensitivityEventAndList() 7912854Sgabeblack@google.com{ 8012854Sgabeblack@google.com for (auto e: list->events) 8112854Sgabeblack@google.com Event::getFromScEvent(e)->delSensitivity(this); 8212854Sgabeblack@google.com} 8312854Sgabeblack@google.com 8412854Sgabeblack@google.comvoid 8512854Sgabeblack@google.comSensitivityEventAndList::notifyWork(Event *e) 8612854Sgabeblack@google.com{ 8712854Sgabeblack@google.com e->delSensitivity(this); 8812854Sgabeblack@google.com count++; 8912854Sgabeblack@google.com if (count == list->events.size()) 9012854Sgabeblack@google.com process->satisfySensitivity(this); 9112854Sgabeblack@google.com} 9213322Sgabeblack@google.com 9312854Sgabeblack@google.comSensitivityEventOrList::SensitivityEventOrList( 9412854Sgabeblack@google.com Process *p, const ::sc_core::sc_event_or_list *list) : 9512854Sgabeblack@google.com Sensitivity(p), list(list) 9612854Sgabeblack@google.com{ 9712854Sgabeblack@google.com for (auto e: list->events) 9812854Sgabeblack@google.com Event::getFromScEvent(e)->addSensitivity(this); 9912854Sgabeblack@google.com} 10012854Sgabeblack@google.com 10112854Sgabeblack@google.comSensitivityEventOrList::~SensitivityEventOrList() 10212854Sgabeblack@google.com{ 10312854Sgabeblack@google.com for (auto e: list->events) 10412854Sgabeblack@google.com Event::getFromScEvent(e)->delSensitivity(this); 10512854Sgabeblack@google.com} 10612854Sgabeblack@google.com 10712854Sgabeblack@google.comvoid 10812854Sgabeblack@google.comSensitivityTimeoutAndEventAndList::notifyWork(Event *e) 10912854Sgabeblack@google.com{ 11012854Sgabeblack@google.com if (e) { 11112854Sgabeblack@google.com // An event went off which must be part of the sc_event_and_list. 11212854Sgabeblack@google.com SensitivityEventAndList::notifyWork(e); 11312854Sgabeblack@google.com } else { 11412854Sgabeblack@google.com // There's no inciting event, so this must be a timeout. 11512854Sgabeblack@google.com SensitivityTimeout::notifyWork(e); 11612854Sgabeblack@google.com } 11712854Sgabeblack@google.com} 11812854Sgabeblack@google.com 11912854Sgabeblack@google.com 12012854Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception 12112854Sgabeblack@google.com{ 12212854Sgabeblack@google.com public: 12312854Sgabeblack@google.com UnwindExceptionReset() { _isReset = true; } 12412854Sgabeblack@google.com}; 12512854Sgabeblack@google.com 12612854Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception 12712854Sgabeblack@google.com{ 12812854Sgabeblack@google.com public: 12912854Sgabeblack@google.com UnwindExceptionKill() {} 13012854Sgabeblack@google.com}; 13112854Sgabeblack@google.com 13212854Sgabeblack@google.comtemplate <typename T> 13312854Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase 13412854Sgabeblack@google.com{ 13513322Sgabeblack@google.com public: 13612854Sgabeblack@google.com T t; 13712854Sgabeblack@google.com void throw_it() override { throw t; } 13812854Sgabeblack@google.com}; 13912854Sgabeblack@google.com 14012854Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException; 14112854Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException; 14212854Sgabeblack@google.com 14312854Sgabeblack@google.com 14413160Sgabeblack@google.comvoid 14512854Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work) 14612854Sgabeblack@google.com{ 14713322Sgabeblack@google.com for (auto &kid: get_child_objects()) { 14812854Sgabeblack@google.com Process *p_kid = dynamic_cast<Process *>(kid); 14912854Sgabeblack@google.com if (p_kid) 15012854Sgabeblack@google.com work(p_kid); 15112854Sgabeblack@google.com } 15212854Sgabeblack@google.com} 15312854Sgabeblack@google.com 15412854Sgabeblack@google.comvoid 15512854Sgabeblack@google.comProcess::suspend(bool inc_kids) 15612854Sgabeblack@google.com{ 15712854Sgabeblack@google.com if (inc_kids) 15812854Sgabeblack@google.com forEachKid([](Process *p) { p->suspend(true); }); 15912854Sgabeblack@google.com 16012854Sgabeblack@google.com if (!_suspended) { 16112854Sgabeblack@google.com _suspended = true; 16212854Sgabeblack@google.com _suspendedReady = false; 16312854Sgabeblack@google.com } 16412854Sgabeblack@google.com 16512854Sgabeblack@google.com if (procKind() != ::sc_core::SC_METHOD_PROC_ && 16612854Sgabeblack@google.com scheduler.current() == this) { 16712854Sgabeblack@google.com scheduler.yield(); 16812854Sgabeblack@google.com } 16912854Sgabeblack@google.com} 17012854Sgabeblack@google.com 17112854Sgabeblack@google.comvoid 17212854Sgabeblack@google.comProcess::resume(bool inc_kids) 17312854Sgabeblack@google.com{ 17412854Sgabeblack@google.com if (inc_kids) 17512854Sgabeblack@google.com forEachKid([](Process *p) { p->resume(true); }); 17612854Sgabeblack@google.com 17712854Sgabeblack@google.com if (_suspended) { 17812854Sgabeblack@google.com _suspended = false; 17912854Sgabeblack@google.com if (_suspendedReady) 18012854Sgabeblack@google.com ready(); 18112854Sgabeblack@google.com _suspendedReady = false; 18212854Sgabeblack@google.com } 18312854Sgabeblack@google.com} 18412854Sgabeblack@google.com 18512854Sgabeblack@google.comvoid 18612854Sgabeblack@google.comProcess::disable(bool inc_kids) 18712854Sgabeblack@google.com{ 18812854Sgabeblack@google.com if (inc_kids) 18912854Sgabeblack@google.com forEachKid([](Process *p) { p->disable(true); }); 19012854Sgabeblack@google.com 19112854Sgabeblack@google.com if (!::sc_core::sc_allow_process_control_corners && 19212854Sgabeblack@google.com dynamic_cast<SensitivityTimeout *>(dynamicSensitivity)) { 19312854Sgabeblack@google.com std::string message("attempt to disable a thread with timeout wait: "); 19412854Sgabeblack@google.com message += name(); 19512854Sgabeblack@google.com SC_REPORT_ERROR("Undefined process control interaction", 19612854Sgabeblack@google.com message.c_str()); 19712854Sgabeblack@google.com } 19812854Sgabeblack@google.com 19912854Sgabeblack@google.com _disabled = true; 20012854Sgabeblack@google.com} 20112854Sgabeblack@google.com 20212854Sgabeblack@google.comvoid 20312854Sgabeblack@google.comProcess::enable(bool inc_kids) 20412854Sgabeblack@google.com{ 20512854Sgabeblack@google.com 20612854Sgabeblack@google.com if (inc_kids) 20712854Sgabeblack@google.com forEachKid([](Process *p) { p->enable(true); }); 20812854Sgabeblack@google.com 20912854Sgabeblack@google.com _disabled = false; 21012854Sgabeblack@google.com} 21112854Sgabeblack@google.com 21212854Sgabeblack@google.comvoid 21312854Sgabeblack@google.comProcess::kill(bool inc_kids) 21412854Sgabeblack@google.com{ 21512854Sgabeblack@google.com // Propogate the kill to our children no matter what happens to us. 21612854Sgabeblack@google.com if (inc_kids) 21712854Sgabeblack@google.com forEachKid([](Process *p) { p->kill(true); }); 21812854Sgabeblack@google.com 21912854Sgabeblack@google.com // If we're in the middle of unwinding, ignore the kill request. 22012854Sgabeblack@google.com if (_isUnwinding) 22112854Sgabeblack@google.com return; 22212854Sgabeblack@google.com 22312854Sgabeblack@google.com // Update our state. 22412854Sgabeblack@google.com terminate(); 22512854Sgabeblack@google.com _isUnwinding = true; 22612854Sgabeblack@google.com 22712854Sgabeblack@google.com // Make sure this process isn't marked ready 22812854Sgabeblack@google.com popListNode(); 22912854Sgabeblack@google.com 23012854Sgabeblack@google.com // Inject the kill exception into this process if it's started. 23112854Sgabeblack@google.com if (!_needsStart) 23212854Sgabeblack@google.com injectException(killException); 23312854Sgabeblack@google.com} 23412854Sgabeblack@google.com 23512854Sgabeblack@google.comvoid 23612854Sgabeblack@google.comProcess::reset(bool inc_kids) 23712854Sgabeblack@google.com{ 23812854Sgabeblack@google.com // Propogate the reset to our children no matter what happens to us. 23912854Sgabeblack@google.com if (inc_kids) 24012854Sgabeblack@google.com forEachKid([](Process *p) { p->reset(true); }); 24112854Sgabeblack@google.com 24212854Sgabeblack@google.com // If we're in the middle of unwinding, ignore the reset request. 24312854Sgabeblack@google.com if (_isUnwinding) 24412854Sgabeblack@google.com return; 24512854Sgabeblack@google.com 24612854Sgabeblack@google.com 24712854Sgabeblack@google.com if (_needsStart) { 24812854Sgabeblack@google.com scheduler.runNow(this); 24912854Sgabeblack@google.com } else { 25012854Sgabeblack@google.com _isUnwinding = true; 25112854Sgabeblack@google.com injectException(resetException); 25212854Sgabeblack@google.com } 25312854Sgabeblack@google.com 25412854Sgabeblack@google.com _resetEvent.notify(); 25512854Sgabeblack@google.com} 25612854Sgabeblack@google.com 25712854Sgabeblack@google.comvoid 25812854Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids) 25912854Sgabeblack@google.com{ 26012854Sgabeblack@google.com if (inc_kids) 26112854Sgabeblack@google.com forEachKid([&exc](Process *p) { p->throw_it(exc, true); }); 26212854Sgabeblack@google.com 26312854Sgabeblack@google.com // Only inject an exception into threads that have started. 26412854Sgabeblack@google.com if (!_needsStart) 26512854Sgabeblack@google.com injectException(exc); 26612854Sgabeblack@google.com} 26712854Sgabeblack@google.com 26812854Sgabeblack@google.comvoid 26912854Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc) 27012854Sgabeblack@google.com{ 27112854Sgabeblack@google.com excWrapper = &exc; 27212854Sgabeblack@google.com scheduler.runNow(this); 27312854Sgabeblack@google.com}; 27412854Sgabeblack@google.com 27512854Sgabeblack@google.comvoid 27612854Sgabeblack@google.comProcess::syncResetOn(bool inc_kids) 27712854Sgabeblack@google.com{ 27812854Sgabeblack@google.com if (inc_kids) 27912854Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOn(true); }); 28012854Sgabeblack@google.com 28112854Sgabeblack@google.com _syncReset = true; 28212854Sgabeblack@google.com} 28312854Sgabeblack@google.com 28412854Sgabeblack@google.comvoid 28512854Sgabeblack@google.comProcess::syncResetOff(bool inc_kids) 28612854Sgabeblack@google.com{ 28712854Sgabeblack@google.com if (inc_kids) 28812854Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOff(true); }); 28912854Sgabeblack@google.com 29012854Sgabeblack@google.com _syncReset = false; 29112854Sgabeblack@google.com} 29212854Sgabeblack@google.com 29312854Sgabeblack@google.comvoid 29412854Sgabeblack@google.comProcess::dontInitialize() 29512854Sgabeblack@google.com{ 29612854Sgabeblack@google.com scheduler.dontInitialize(this); 29712854Sgabeblack@google.com} 29812854Sgabeblack@google.com 29912854Sgabeblack@google.comvoid 30012854Sgabeblack@google.comProcess::finalize() 30112854Sgabeblack@google.com{ 30212854Sgabeblack@google.com for (auto &s: pendingStaticSensitivities) { 30312854Sgabeblack@google.com s->finalize(staticSensitivities); 30412854Sgabeblack@google.com delete s; 30512854Sgabeblack@google.com s = nullptr; 30612854Sgabeblack@google.com } 30712854Sgabeblack@google.com pendingStaticSensitivities.clear(); 30812854Sgabeblack@google.com}; 30912854Sgabeblack@google.com 31012854Sgabeblack@google.comvoid 31112854Sgabeblack@google.comProcess::run() 31212854Sgabeblack@google.com{ 31312854Sgabeblack@google.com bool reset; 31412854Sgabeblack@google.com do { 31512854Sgabeblack@google.com reset = false; 31612854Sgabeblack@google.com try { 31712854Sgabeblack@google.com func->call(); 31812854Sgabeblack@google.com } catch(const ::sc_core::sc_unwind_exception &exc) { 31912854Sgabeblack@google.com reset = exc.is_reset(); 32012854Sgabeblack@google.com _isUnwinding = false; 32112854Sgabeblack@google.com } 32212854Sgabeblack@google.com } while (reset); 32312854Sgabeblack@google.com} 32412854Sgabeblack@google.com 32512854Sgabeblack@google.comvoid 32612854Sgabeblack@google.comProcess::addStatic(PendingSensitivity *s) 32712854Sgabeblack@google.com{ 32812854Sgabeblack@google.com pendingStaticSensitivities.push_back(s); 32912854Sgabeblack@google.com} 33012854Sgabeblack@google.com 33112854Sgabeblack@google.comvoid 33212854Sgabeblack@google.comProcess::setDynamic(Sensitivity *s) 33312854Sgabeblack@google.com{ 33412854Sgabeblack@google.com delete dynamicSensitivity; 33512854Sgabeblack@google.com dynamicSensitivity = s; 33612854Sgabeblack@google.com} 33712854Sgabeblack@google.com 33812854Sgabeblack@google.comvoid 33912854Sgabeblack@google.comProcess::satisfySensitivity(Sensitivity *s) 34012854Sgabeblack@google.com{ 34112854Sgabeblack@google.com // If there's a dynamic sensitivity and this wasn't it, ignore. 34212854Sgabeblack@google.com if (dynamicSensitivity && dynamicSensitivity != s) 34312854Sgabeblack@google.com return; 34412854Sgabeblack@google.com 34512854Sgabeblack@google.com setDynamic(nullptr); 34612854Sgabeblack@google.com ready(); 34712854Sgabeblack@google.com} 34812854Sgabeblack@google.com 34912854Sgabeblack@google.comvoid 35012854Sgabeblack@google.comProcess::ready() 35112854Sgabeblack@google.com{ 35212854Sgabeblack@google.com if (disabled()) 35312854Sgabeblack@google.com return; 35412854Sgabeblack@google.com if (suspended()) 35512854Sgabeblack@google.com _suspendedReady = true; 35612854Sgabeblack@google.com else 35712854Sgabeblack@google.com scheduler.ready(this); 35812854Sgabeblack@google.com} 35912854Sgabeblack@google.com 36012854Sgabeblack@google.comvoid 36112854Sgabeblack@google.comProcess::lastReport(::sc_core::sc_report *report) 36212854Sgabeblack@google.com{ 36312854Sgabeblack@google.com if (report) { 36412854Sgabeblack@google.com _lastReport = std::unique_ptr<::sc_core::sc_report>( 36512854Sgabeblack@google.com new ::sc_core::sc_report(*report)); 36612854Sgabeblack@google.com } else { 36712854Sgabeblack@google.com _lastReport = nullptr; 36812854Sgabeblack@google.com } 36912854Sgabeblack@google.com} 37012854Sgabeblack@google.com 37112854Sgabeblack@google.com::sc_core::sc_report *Process::lastReport() const { return _lastReport.get(); } 37212854Sgabeblack@google.com 37312854Sgabeblack@google.comProcess::Process(const char *name, ProcessFuncWrapper *func, bool _dynamic) : 37412854Sgabeblack@google.com ::sc_core::sc_process_b(name), excWrapper(nullptr), func(func), 37512854Sgabeblack@google.com _needsStart(true), _dynamic(_dynamic), _isUnwinding(false), 37612854Sgabeblack@google.com _terminated(false), _suspended(false), _disabled(false), 37712854Sgabeblack@google.com _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize), 37812854Sgabeblack@google.com dynamicSensitivity(nullptr) 37912854Sgabeblack@google.com{ 38012854Sgabeblack@google.com _newest = this; 38112854Sgabeblack@google.com} 38212854Sgabeblack@google.com 38312854Sgabeblack@google.comvoid 38412854Sgabeblack@google.comProcess::terminate() 38512854Sgabeblack@google.com{ 38612854Sgabeblack@google.com _terminated = true; 38712854Sgabeblack@google.com _suspendedReady = false; 38812854Sgabeblack@google.com _suspended = false; 38912854Sgabeblack@google.com _syncReset = false; 39012854Sgabeblack@google.com delete dynamicSensitivity; 39112854Sgabeblack@google.com dynamicSensitivity = nullptr; 39212854Sgabeblack@google.com for (auto s: staticSensitivities) 39312854Sgabeblack@google.com delete s; 39412854Sgabeblack@google.com staticSensitivities.clear(); 39512854Sgabeblack@google.com 39612854Sgabeblack@google.com _terminatedEvent.notify(); 39712854Sgabeblack@google.com} 39812854Sgabeblack@google.com 39912854Sgabeblack@google.comProcess *Process::_newest; 40012854Sgabeblack@google.com 40112854Sgabeblack@google.comvoid 40212854Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids) 40312854Sgabeblack@google.com{ 40412854Sgabeblack@google.com p->throw_it(exc, inc_kids); 40512854Sgabeblack@google.com} 40612854Sgabeblack@google.com 40712854Sgabeblack@google.com} // namespace sc_gem5 40812854Sgabeblack@google.com