process.cc revision 12961
112952Sgabeblack@google.com/* 212952Sgabeblack@google.com * Copyright 2018 Google, Inc. 312952Sgabeblack@google.com * 412952Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 512952Sgabeblack@google.com * modification, are permitted provided that the following conditions are 612952Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 712952Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 812952Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 912952Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1012952Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1112952Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1212952Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1312952Sgabeblack@google.com * this software without specific prior written permission. 1412952Sgabeblack@google.com * 1512952Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612952Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712952Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812952Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912952Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012952Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112952Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212952Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312952Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412952Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512952Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612952Sgabeblack@google.com * 2712952Sgabeblack@google.com * Authors: Gabe Black 2812952Sgabeblack@google.com */ 2912952Sgabeblack@google.com 3012952Sgabeblack@google.com#include "systemc/core/process.hh" 3112957Sgabeblack@google.com 3212957Sgabeblack@google.com#include "base/logging.hh" 3312957Sgabeblack@google.com#include "systemc/core/event.hh" 3412953Sgabeblack@google.com#include "systemc/core/scheduler.hh" 3512952Sgabeblack@google.com 3612952Sgabeblack@google.comnamespace sc_gem5 3712952Sgabeblack@google.com{ 3812952Sgabeblack@google.com 3912957Sgabeblack@google.comSensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) : 4012957Sgabeblack@google.com Sensitivity(p), timeoutEvent(this), timeout(t) 4112957Sgabeblack@google.com{ 4212957Sgabeblack@google.com Tick when = scheduler.eventQueue().getCurTick() + timeout.value(); 4312957Sgabeblack@google.com scheduler.eventQueue().schedule(&timeoutEvent, when); 4412957Sgabeblack@google.com} 4512957Sgabeblack@google.com 4612957Sgabeblack@google.comSensitivityTimeout::~SensitivityTimeout() 4712957Sgabeblack@google.com{ 4812957Sgabeblack@google.com if (timeoutEvent.scheduled()) 4912957Sgabeblack@google.com scheduler.eventQueue().deschedule(&timeoutEvent); 5012957Sgabeblack@google.com} 5112957Sgabeblack@google.com 5212957Sgabeblack@google.comSensitivityEvent::SensitivityEvent( 5312957Sgabeblack@google.com Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e) 5412957Sgabeblack@google.com{ 5512957Sgabeblack@google.com Event::getFromScEvent(event)->addSensitivity(this); 5612957Sgabeblack@google.com} 5712957Sgabeblack@google.com 5812957Sgabeblack@google.comSensitivityEvent::~SensitivityEvent() 5912957Sgabeblack@google.com{ 6012957Sgabeblack@google.com Event::getFromScEvent(event)->delSensitivity(this); 6112957Sgabeblack@google.com} 6212957Sgabeblack@google.com 6312957Sgabeblack@google.comSensitivityEventAndList::SensitivityEventAndList( 6412957Sgabeblack@google.com Process *p, const ::sc_core::sc_event_and_list *list) : 6512957Sgabeblack@google.com Sensitivity(p), list(list), count(0) 6612957Sgabeblack@google.com{ 6712957Sgabeblack@google.com for (auto e: list->events) 6812957Sgabeblack@google.com Event::getFromScEvent(e)->addSensitivity(this); 6912957Sgabeblack@google.com} 7012957Sgabeblack@google.com 7112957Sgabeblack@google.comSensitivityEventAndList::~SensitivityEventAndList() 7212957Sgabeblack@google.com{ 7312957Sgabeblack@google.com for (auto e: list->events) 7412957Sgabeblack@google.com Event::getFromScEvent(e)->delSensitivity(this); 7512957Sgabeblack@google.com} 7612957Sgabeblack@google.com 7712957Sgabeblack@google.comvoid 7812957Sgabeblack@google.comSensitivityEventAndList::notifyWork(Event *e) 7912957Sgabeblack@google.com{ 8012957Sgabeblack@google.com e->delSensitivity(this); 8112957Sgabeblack@google.com count++; 8212957Sgabeblack@google.com if (count == list->events.size()) 8312959Sgabeblack@google.com process->satisfySensitivity(this); 8412957Sgabeblack@google.com} 8512957Sgabeblack@google.com 8612957Sgabeblack@google.comSensitivityEventOrList::SensitivityEventOrList( 8712957Sgabeblack@google.com Process *p, const ::sc_core::sc_event_or_list *list) : 8812957Sgabeblack@google.com Sensitivity(p), list(list) 8912957Sgabeblack@google.com{ 9012957Sgabeblack@google.com for (auto e: list->events) 9112957Sgabeblack@google.com Event::getFromScEvent(e)->addSensitivity(this); 9212957Sgabeblack@google.com} 9312957Sgabeblack@google.com 9412957Sgabeblack@google.comSensitivityEventOrList::~SensitivityEventOrList() 9512957Sgabeblack@google.com{ 9612957Sgabeblack@google.com for (auto e: list->events) 9712957Sgabeblack@google.com Event::getFromScEvent(e)->delSensitivity(this); 9812957Sgabeblack@google.com} 9912957Sgabeblack@google.com 10012957Sgabeblack@google.com 10112952Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception 10212952Sgabeblack@google.com{ 10312952Sgabeblack@google.com public: 10412952Sgabeblack@google.com const char *what() const throw() override { return "RESET"; } 10512952Sgabeblack@google.com bool is_reset() const override { return true; } 10612952Sgabeblack@google.com}; 10712952Sgabeblack@google.com 10812952Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception 10912952Sgabeblack@google.com{ 11012952Sgabeblack@google.com public: 11112952Sgabeblack@google.com const char *what() const throw() override { return "KILL"; } 11212952Sgabeblack@google.com bool is_reset() const override { return false; } 11312952Sgabeblack@google.com}; 11412952Sgabeblack@google.com 11512952Sgabeblack@google.comtemplate <typename T> 11612952Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase 11712952Sgabeblack@google.com{ 11812952Sgabeblack@google.com public: 11912952Sgabeblack@google.com T t; 12012952Sgabeblack@google.com void throw_it() override { throw t; } 12112952Sgabeblack@google.com}; 12212952Sgabeblack@google.com 12312952Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException; 12412952Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException; 12512952Sgabeblack@google.com 12612952Sgabeblack@google.com 12712952Sgabeblack@google.comvoid 12812952Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work) 12912952Sgabeblack@google.com{ 13012952Sgabeblack@google.com for (auto &kid: get_child_objects()) { 13112952Sgabeblack@google.com Process *p_kid = dynamic_cast<Process *>(kid); 13212952Sgabeblack@google.com if (p_kid) 13312952Sgabeblack@google.com work(p_kid); 13412952Sgabeblack@google.com } 13512952Sgabeblack@google.com} 13612952Sgabeblack@google.com 13712952Sgabeblack@google.comvoid 13812952Sgabeblack@google.comProcess::suspend(bool inc_kids) 13912952Sgabeblack@google.com{ 14012952Sgabeblack@google.com if (inc_kids) 14112952Sgabeblack@google.com forEachKid([](Process *p) { p->suspend(true); }); 14212952Sgabeblack@google.com 14312952Sgabeblack@google.com if (!_suspended) { 14412952Sgabeblack@google.com _suspended = true; 14512959Sgabeblack@google.com _suspendedReady = false; 14612952Sgabeblack@google.com } 14712952Sgabeblack@google.com 14812953Sgabeblack@google.com if (procKind() != ::sc_core::SC_METHOD_PROC_ && 14912953Sgabeblack@google.com scheduler.current() == this) { 15012953Sgabeblack@google.com scheduler.yield(); 15112952Sgabeblack@google.com } 15212952Sgabeblack@google.com} 15312952Sgabeblack@google.com 15412952Sgabeblack@google.comvoid 15512952Sgabeblack@google.comProcess::resume(bool inc_kids) 15612952Sgabeblack@google.com{ 15712952Sgabeblack@google.com if (inc_kids) 15812952Sgabeblack@google.com forEachKid([](Process *p) { p->resume(true); }); 15912952Sgabeblack@google.com 16012952Sgabeblack@google.com if (_suspended) { 16112952Sgabeblack@google.com _suspended = false; 16212959Sgabeblack@google.com if (_suspendedReady) 16312959Sgabeblack@google.com ready(); 16412959Sgabeblack@google.com _suspendedReady = false; 16512952Sgabeblack@google.com } 16612952Sgabeblack@google.com} 16712952Sgabeblack@google.com 16812952Sgabeblack@google.comvoid 16912952Sgabeblack@google.comProcess::disable(bool inc_kids) 17012952Sgabeblack@google.com{ 17112952Sgabeblack@google.com if (inc_kids) 17212952Sgabeblack@google.com forEachKid([](Process *p) { p->disable(true); }); 17312952Sgabeblack@google.com 17412952Sgabeblack@google.com _disabled = true; 17512952Sgabeblack@google.com} 17612952Sgabeblack@google.com 17712952Sgabeblack@google.comvoid 17812952Sgabeblack@google.comProcess::enable(bool inc_kids) 17912952Sgabeblack@google.com{ 18012952Sgabeblack@google.com 18112952Sgabeblack@google.com if (inc_kids) 18212952Sgabeblack@google.com forEachKid([](Process *p) { p->enable(true); }); 18312952Sgabeblack@google.com 18412952Sgabeblack@google.com _disabled = false; 18512952Sgabeblack@google.com} 18612952Sgabeblack@google.com 18712952Sgabeblack@google.comvoid 18812952Sgabeblack@google.comProcess::kill(bool inc_kids) 18912952Sgabeblack@google.com{ 19012952Sgabeblack@google.com // Update our state. 19112952Sgabeblack@google.com _terminated = true; 19212952Sgabeblack@google.com _isUnwinding = true; 19312952Sgabeblack@google.com 19412952Sgabeblack@google.com // Propogate the kill to our children no matter what happens to us. 19512952Sgabeblack@google.com if (inc_kids) 19612952Sgabeblack@google.com forEachKid([](Process *p) { p->kill(true); }); 19712952Sgabeblack@google.com 19812952Sgabeblack@google.com // If we're in the middle of unwinding, ignore the kill request. 19912952Sgabeblack@google.com if (_isUnwinding) 20012952Sgabeblack@google.com return; 20112952Sgabeblack@google.com 20212952Sgabeblack@google.com // Inject the kill exception into this process. 20312952Sgabeblack@google.com injectException(killException); 20412952Sgabeblack@google.com 20512952Sgabeblack@google.com _terminatedEvent.notify(); 20612952Sgabeblack@google.com} 20712952Sgabeblack@google.com 20812952Sgabeblack@google.comvoid 20912952Sgabeblack@google.comProcess::reset(bool inc_kids) 21012952Sgabeblack@google.com{ 21112952Sgabeblack@google.com // Update our state. 21212952Sgabeblack@google.com _isUnwinding = true; 21312952Sgabeblack@google.com 21412952Sgabeblack@google.com // Propogate the reset to our children no matter what happens to us. 21512952Sgabeblack@google.com if (inc_kids) 21612952Sgabeblack@google.com forEachKid([](Process *p) { p->reset(true); }); 21712952Sgabeblack@google.com 21812952Sgabeblack@google.com // If we're in the middle of unwinding, ignore the reset request. 21912952Sgabeblack@google.com if (_isUnwinding) 22012952Sgabeblack@google.com return; 22112952Sgabeblack@google.com 22212952Sgabeblack@google.com // Inject the reset exception into this process. 22312952Sgabeblack@google.com injectException(resetException); 22412952Sgabeblack@google.com 22512952Sgabeblack@google.com _resetEvent.notify(); 22612952Sgabeblack@google.com} 22712952Sgabeblack@google.com 22812952Sgabeblack@google.comvoid 22912952Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids) 23012952Sgabeblack@google.com{ 23112952Sgabeblack@google.com if (inc_kids) 23212952Sgabeblack@google.com forEachKid([&exc](Process *p) { p->throw_it(exc, true); }); 23312952Sgabeblack@google.com} 23412952Sgabeblack@google.com 23512952Sgabeblack@google.comvoid 23612952Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc) 23712952Sgabeblack@google.com{ 23812952Sgabeblack@google.com excWrapper = &exc; 23912952Sgabeblack@google.com // Let this process preempt us. 24012952Sgabeblack@google.com}; 24112952Sgabeblack@google.com 24212952Sgabeblack@google.comvoid 24312952Sgabeblack@google.comProcess::syncResetOn(bool inc_kids) 24412952Sgabeblack@google.com{ 24512952Sgabeblack@google.com if (inc_kids) 24612952Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOn(true); }); 24712952Sgabeblack@google.com 24812952Sgabeblack@google.com _syncReset = true; 24912952Sgabeblack@google.com} 25012952Sgabeblack@google.com 25112952Sgabeblack@google.comvoid 25212952Sgabeblack@google.comProcess::syncResetOff(bool inc_kids) 25312952Sgabeblack@google.com{ 25412952Sgabeblack@google.com if (inc_kids) 25512952Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOff(true); }); 25612952Sgabeblack@google.com 25712952Sgabeblack@google.com _syncReset = false; 25812952Sgabeblack@google.com} 25912952Sgabeblack@google.com 26012952Sgabeblack@google.comvoid 26112957Sgabeblack@google.comProcess::dontInitialize() 26212957Sgabeblack@google.com{ 26312957Sgabeblack@google.com scheduler.dontInitialize(this); 26412957Sgabeblack@google.com} 26512957Sgabeblack@google.com 26612957Sgabeblack@google.comvoid 26712957Sgabeblack@google.comProcess::finalize() 26812957Sgabeblack@google.com{ 26912957Sgabeblack@google.com for (auto &s: pendingStaticSensitivities) { 27012957Sgabeblack@google.com s->finalize(staticSensitivities); 27112957Sgabeblack@google.com delete s; 27212957Sgabeblack@google.com s = nullptr; 27312957Sgabeblack@google.com } 27412957Sgabeblack@google.com pendingStaticSensitivities.clear(); 27512957Sgabeblack@google.com}; 27612957Sgabeblack@google.com 27712957Sgabeblack@google.comvoid 27812953Sgabeblack@google.comProcess::run() 27912952Sgabeblack@google.com{ 28012953Sgabeblack@google.com bool reset; 28112953Sgabeblack@google.com do { 28212953Sgabeblack@google.com reset = false; 28312953Sgabeblack@google.com try { 28412953Sgabeblack@google.com func->call(); 28512953Sgabeblack@google.com } catch(::sc_core::sc_unwind_exception exc) { 28612953Sgabeblack@google.com reset = exc.is_reset(); 28712953Sgabeblack@google.com } 28812953Sgabeblack@google.com } while (reset); 28912961Sgabeblack@google.com _terminated = true; 29012953Sgabeblack@google.com} 29112952Sgabeblack@google.com 29212957Sgabeblack@google.comvoid 29312957Sgabeblack@google.comProcess::addStatic(PendingSensitivity *s) 29412957Sgabeblack@google.com{ 29512957Sgabeblack@google.com pendingStaticSensitivities.push_back(s); 29612957Sgabeblack@google.com} 29712957Sgabeblack@google.com 29812957Sgabeblack@google.comvoid 29912957Sgabeblack@google.comProcess::setDynamic(Sensitivity *s) 30012957Sgabeblack@google.com{ 30112957Sgabeblack@google.com delete dynamicSensitivity; 30212957Sgabeblack@google.com dynamicSensitivity = s; 30312957Sgabeblack@google.com} 30412957Sgabeblack@google.com 30512959Sgabeblack@google.comvoid 30612959Sgabeblack@google.comProcess::satisfySensitivity(Sensitivity *s) 30712959Sgabeblack@google.com{ 30812959Sgabeblack@google.com // If there's a dynamic sensitivity and this wasn't it, ignore. 30912959Sgabeblack@google.com if (dynamicSensitivity && dynamicSensitivity != s) 31012959Sgabeblack@google.com return; 31112959Sgabeblack@google.com 31212959Sgabeblack@google.com setDynamic(nullptr); 31312959Sgabeblack@google.com ready(); 31412959Sgabeblack@google.com} 31512959Sgabeblack@google.com 31612959Sgabeblack@google.comvoid 31712959Sgabeblack@google.comProcess::ready() 31812959Sgabeblack@google.com{ 31912959Sgabeblack@google.com if (suspended()) 32012959Sgabeblack@google.com _suspendedReady = true; 32112959Sgabeblack@google.com else 32212959Sgabeblack@google.com scheduler.ready(this); 32312959Sgabeblack@google.com} 32412959Sgabeblack@google.com 32512961Sgabeblack@google.comProcess::Process(const char *name, ProcessFuncWrapper *func, 32612961Sgabeblack@google.com bool _dynamic, bool needs_start) : 32712953Sgabeblack@google.com ::sc_core::sc_object(name), excWrapper(nullptr), func(func), 32812961Sgabeblack@google.com _needsStart(needs_start), _dynamic(_dynamic), _isUnwinding(false), 32912953Sgabeblack@google.com _terminated(false), _suspended(false), _disabled(false), 33012957Sgabeblack@google.com _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize), 33112957Sgabeblack@google.com dynamicSensitivity(nullptr) 33212953Sgabeblack@google.com{ 33312953Sgabeblack@google.com _newest = this; 33412957Sgabeblack@google.com if (_dynamic) 33512957Sgabeblack@google.com finalize(); 33612957Sgabeblack@google.com else 33712957Sgabeblack@google.com scheduler.reg(this); 33812953Sgabeblack@google.com} 33912952Sgabeblack@google.com 34012953Sgabeblack@google.comProcess *Process::_newest; 34112952Sgabeblack@google.com 34212952Sgabeblack@google.comvoid 34312952Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids) 34412952Sgabeblack@google.com{ 34512952Sgabeblack@google.com p->throw_it(exc, inc_kids); 34612952Sgabeblack@google.com} 34712952Sgabeblack@google.com 34812952Sgabeblack@google.com} // namespace sc_gem5 349