process.cc revision 12996
114184Sgabeblack@google.com/* 214184Sgabeblack@google.com * Copyright 2018 Google, Inc. 314184Sgabeblack@google.com * 414184Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 514184Sgabeblack@google.com * modification, are permitted provided that the following conditions are 614184Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 714184Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 814184Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 914184Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1014184Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1114184Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1214184Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1314184Sgabeblack@google.com * this software without specific prior written permission. 1414184Sgabeblack@google.com * 1514184Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1614184Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1714184Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1814184Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1914184Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2014184Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2114184Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2214184Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2314184Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2414184Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2514184Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2614184Sgabeblack@google.com * 2714184Sgabeblack@google.com * Authors: Gabe Black 2814184Sgabeblack@google.com */ 2914184Sgabeblack@google.com 3014184Sgabeblack@google.com#include "systemc/core/process.hh" 3114184Sgabeblack@google.com 3214184Sgabeblack@google.com#include "base/logging.hh" 3314184Sgabeblack@google.com#include "systemc/core/event.hh" 3414184Sgabeblack@google.com#include "systemc/core/scheduler.hh" 3514184Sgabeblack@google.com 3614184Sgabeblack@google.comnamespace sc_gem5 3714184Sgabeblack@google.com{ 3814184Sgabeblack@google.com 3914184Sgabeblack@google.comSensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) : 4014184Sgabeblack@google.com Sensitivity(p), timeoutEvent(this), time(t) 4114184Sgabeblack@google.com{ 4214184Sgabeblack@google.com Tick when = scheduler.getCurTick() + time.value(); 4314184Sgabeblack@google.com scheduler.schedule(&timeoutEvent, when); 4414184Sgabeblack@google.com} 4514184Sgabeblack@google.com 4614184Sgabeblack@google.comSensitivityTimeout::~SensitivityTimeout() 4714184Sgabeblack@google.com{ 4814184Sgabeblack@google.com if (timeoutEvent.scheduled()) 4914184Sgabeblack@google.com scheduler.deschedule(&timeoutEvent); 5014184Sgabeblack@google.com} 5114184Sgabeblack@google.com 5214184Sgabeblack@google.comvoid 5314184Sgabeblack@google.comSensitivityTimeout::timeout() 5414184Sgabeblack@google.com{ 5514184Sgabeblack@google.com scheduler.eventHappened(); 5614184Sgabeblack@google.com notify(); 5714184Sgabeblack@google.com} 5814184Sgabeblack@google.com 5914184Sgabeblack@google.comSensitivityEvent::SensitivityEvent( 6014184Sgabeblack@google.com Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e) 6114184Sgabeblack@google.com{ 6214184Sgabeblack@google.com Event::getFromScEvent(event)->addSensitivity(this); 6314184Sgabeblack@google.com} 6414184Sgabeblack@google.com 6514184Sgabeblack@google.comSensitivityEvent::~SensitivityEvent() 6614184Sgabeblack@google.com{ 6714184Sgabeblack@google.com Event::getFromScEvent(event)->delSensitivity(this); 6814184Sgabeblack@google.com} 6914184Sgabeblack@google.com 7014184Sgabeblack@google.comSensitivityEventAndList::SensitivityEventAndList( 7114184Sgabeblack@google.com Process *p, const ::sc_core::sc_event_and_list *list) : 7214184Sgabeblack@google.com Sensitivity(p), list(list), count(0) 7314184Sgabeblack@google.com{ 7414184Sgabeblack@google.com for (auto e: list->events) 7514184Sgabeblack@google.com Event::getFromScEvent(e)->addSensitivity(this); 7614184Sgabeblack@google.com} 7714184Sgabeblack@google.com 7814184Sgabeblack@google.comSensitivityEventAndList::~SensitivityEventAndList() 7914184Sgabeblack@google.com{ 8014184Sgabeblack@google.com for (auto e: list->events) 8114184Sgabeblack@google.com Event::getFromScEvent(e)->delSensitivity(this); 8214184Sgabeblack@google.com} 8314184Sgabeblack@google.com 8414184Sgabeblack@google.comvoid 8514184Sgabeblack@google.comSensitivityEventAndList::notifyWork(Event *e) 8614184Sgabeblack@google.com{ 8714184Sgabeblack@google.com e->delSensitivity(this); 8814184Sgabeblack@google.com count++; 8914184Sgabeblack@google.com if (count == list->events.size()) 9014184Sgabeblack@google.com process->satisfySensitivity(this); 9114184Sgabeblack@google.com} 9214184Sgabeblack@google.com 9314184Sgabeblack@google.comSensitivityEventOrList::SensitivityEventOrList( 9414184Sgabeblack@google.com Process *p, const ::sc_core::sc_event_or_list *list) : 9514184Sgabeblack@google.com Sensitivity(p), list(list) 9614184Sgabeblack@google.com{ 9714184Sgabeblack@google.com for (auto e: list->events) 9814184Sgabeblack@google.com Event::getFromScEvent(e)->addSensitivity(this); 9914184Sgabeblack@google.com} 10014184Sgabeblack@google.com 10114184Sgabeblack@google.comSensitivityEventOrList::~SensitivityEventOrList() 10214184Sgabeblack@google.com{ 10314184Sgabeblack@google.com for (auto e: list->events) 10414184Sgabeblack@google.com Event::getFromScEvent(e)->delSensitivity(this); 10514184Sgabeblack@google.com} 10614184Sgabeblack@google.com 10714184Sgabeblack@google.com 10814184Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception 10914184Sgabeblack@google.com{ 11014184Sgabeblack@google.com public: 11114184Sgabeblack@google.com UnwindExceptionReset() { _isReset = true; } 11214184Sgabeblack@google.com}; 11314184Sgabeblack@google.com 11414184Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception 11514184Sgabeblack@google.com{ 11614184Sgabeblack@google.com public: 11714184Sgabeblack@google.com UnwindExceptionKill() {} 11814184Sgabeblack@google.com}; 11914184Sgabeblack@google.com 12014184Sgabeblack@google.comtemplate <typename T> 12114184Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase 12214184Sgabeblack@google.com{ 12314184Sgabeblack@google.com public: 12414184Sgabeblack@google.com T t; 12514184Sgabeblack@google.com void throw_it() override { throw t; } 12614184Sgabeblack@google.com}; 12714184Sgabeblack@google.com 12814184Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException; 12914184Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException; 13014184Sgabeblack@google.com 13114184Sgabeblack@google.com 13214184Sgabeblack@google.comvoid 13314184Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work) 13414184Sgabeblack@google.com{ 13514184Sgabeblack@google.com for (auto &kid: get_child_objects()) { 13614184Sgabeblack@google.com Process *p_kid = dynamic_cast<Process *>(kid); 13714184Sgabeblack@google.com if (p_kid) 13814184Sgabeblack@google.com work(p_kid); 13914184Sgabeblack@google.com } 14014184Sgabeblack@google.com} 14114184Sgabeblack@google.com 14214184Sgabeblack@google.comvoid 14314184Sgabeblack@google.comProcess::suspend(bool inc_kids) 14414184Sgabeblack@google.com{ 14514184Sgabeblack@google.com if (inc_kids) 14614184Sgabeblack@google.com forEachKid([](Process *p) { p->suspend(true); }); 14714184Sgabeblack@google.com 14814184Sgabeblack@google.com if (!_suspended) { 14914184Sgabeblack@google.com _suspended = true; 15014184Sgabeblack@google.com _suspendedReady = false; 15114184Sgabeblack@google.com } 15214184Sgabeblack@google.com 15314184Sgabeblack@google.com if (procKind() != ::sc_core::SC_METHOD_PROC_ && 15414184Sgabeblack@google.com scheduler.current() == this) { 15514184Sgabeblack@google.com scheduler.yield(); 15614184Sgabeblack@google.com } 15714184Sgabeblack@google.com} 15814184Sgabeblack@google.com 15914184Sgabeblack@google.comvoid 16014184Sgabeblack@google.comProcess::resume(bool inc_kids) 16114184Sgabeblack@google.com{ 16214184Sgabeblack@google.com if (inc_kids) 16314184Sgabeblack@google.com forEachKid([](Process *p) { p->resume(true); }); 16414184Sgabeblack@google.com 16514184Sgabeblack@google.com if (_suspended) { 16614184Sgabeblack@google.com _suspended = false; 16714184Sgabeblack@google.com if (_suspendedReady) 16814184Sgabeblack@google.com ready(); 16914184Sgabeblack@google.com _suspendedReady = false; 17014184Sgabeblack@google.com } 17114184Sgabeblack@google.com} 17214184Sgabeblack@google.com 17314184Sgabeblack@google.comvoid 17414184Sgabeblack@google.comProcess::disable(bool inc_kids) 17514184Sgabeblack@google.com{ 17614184Sgabeblack@google.com if (inc_kids) 17714184Sgabeblack@google.com forEachKid([](Process *p) { p->disable(true); }); 17814184Sgabeblack@google.com 17914184Sgabeblack@google.com _disabled = true; 18014184Sgabeblack@google.com} 18114184Sgabeblack@google.com 18214184Sgabeblack@google.comvoid 18314184Sgabeblack@google.comProcess::enable(bool inc_kids) 18414184Sgabeblack@google.com{ 18514184Sgabeblack@google.com 18614184Sgabeblack@google.com if (inc_kids) 18714184Sgabeblack@google.com forEachKid([](Process *p) { p->enable(true); }); 18814184Sgabeblack@google.com 18914184Sgabeblack@google.com _disabled = false; 19014184Sgabeblack@google.com} 19114184Sgabeblack@google.com 19214184Sgabeblack@google.comvoid 19314184Sgabeblack@google.comProcess::kill(bool inc_kids) 19414184Sgabeblack@google.com{ 19514184Sgabeblack@google.com // Propogate the kill to our children no matter what happens to us. 19614184Sgabeblack@google.com if (inc_kids) 19714184Sgabeblack@google.com forEachKid([](Process *p) { p->kill(true); }); 19814184Sgabeblack@google.com 19914184Sgabeblack@google.com // If we're in the middle of unwinding, ignore the kill request. 20014184Sgabeblack@google.com if (_isUnwinding) 20114184Sgabeblack@google.com return; 20214184Sgabeblack@google.com 20314184Sgabeblack@google.com // Update our state. 20414184Sgabeblack@google.com _terminated = true; 20514184Sgabeblack@google.com _isUnwinding = true; 20614184Sgabeblack@google.com _suspendedReady = false; 20714184Sgabeblack@google.com _suspended = false; 20814184Sgabeblack@google.com _syncReset = false; 20914184Sgabeblack@google.com 21014184Sgabeblack@google.com // Inject the kill exception into this process. 21114184Sgabeblack@google.com injectException(killException); 21214184Sgabeblack@google.com 21314184Sgabeblack@google.com _terminatedEvent.notify(); 21414184Sgabeblack@google.com} 21514184Sgabeblack@google.com 21614184Sgabeblack@google.comvoid 21714184Sgabeblack@google.comProcess::reset(bool inc_kids) 21814184Sgabeblack@google.com{ 21914184Sgabeblack@google.com // Propogate the reset to our children no matter what happens to us. 22014184Sgabeblack@google.com if (inc_kids) 22114184Sgabeblack@google.com forEachKid([](Process *p) { p->reset(true); }); 22214184Sgabeblack@google.com 22314184Sgabeblack@google.com // If we're in the middle of unwinding, ignore the reset request. 22414184Sgabeblack@google.com if (_isUnwinding) 22514184Sgabeblack@google.com return; 22614184Sgabeblack@google.com 22714184Sgabeblack@google.com // Update our state. 22814184Sgabeblack@google.com _isUnwinding = true; 22914184Sgabeblack@google.com 23014184Sgabeblack@google.com // Inject the reset exception into this process. 23114184Sgabeblack@google.com injectException(resetException); 23214184Sgabeblack@google.com 23314184Sgabeblack@google.com _resetEvent.notify(); 23414184Sgabeblack@google.com} 23514184Sgabeblack@google.com 23614184Sgabeblack@google.comvoid 23714184Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids) 23814184Sgabeblack@google.com{ 23914184Sgabeblack@google.com if (inc_kids) 24014184Sgabeblack@google.com forEachKid([&exc](Process *p) { p->throw_it(exc, true); }); 24114184Sgabeblack@google.com} 24214184Sgabeblack@google.com 24314184Sgabeblack@google.comvoid 24414184Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc) 24514184Sgabeblack@google.com{ 24614184Sgabeblack@google.com excWrapper = &exc; 24714184Sgabeblack@google.com scheduler.runNow(this); 24814184Sgabeblack@google.com}; 24914184Sgabeblack@google.com 25014184Sgabeblack@google.comvoid 25114184Sgabeblack@google.comProcess::syncResetOn(bool inc_kids) 25214184Sgabeblack@google.com{ 25314184Sgabeblack@google.com if (inc_kids) 25414184Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOn(true); }); 25514184Sgabeblack@google.com 25614184Sgabeblack@google.com _syncReset = true; 25714184Sgabeblack@google.com} 25814184Sgabeblack@google.com 25914184Sgabeblack@google.comvoid 26014184Sgabeblack@google.comProcess::syncResetOff(bool inc_kids) 26114184Sgabeblack@google.com{ 26214184Sgabeblack@google.com if (inc_kids) 26314184Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOff(true); }); 26414184Sgabeblack@google.com 26514184Sgabeblack@google.com _syncReset = false; 26614184Sgabeblack@google.com} 26714184Sgabeblack@google.com 26814184Sgabeblack@google.comvoid 26914184Sgabeblack@google.comProcess::dontInitialize() 27014184Sgabeblack@google.com{ 27114184Sgabeblack@google.com scheduler.dontInitialize(this); 27214184Sgabeblack@google.com} 27314184Sgabeblack@google.com 27414184Sgabeblack@google.comvoid 27514184Sgabeblack@google.comProcess::finalize() 27614184Sgabeblack@google.com{ 27714184Sgabeblack@google.com for (auto &s: pendingStaticSensitivities) { 27814184Sgabeblack@google.com s->finalize(staticSensitivities); 27914184Sgabeblack@google.com delete s; 28014184Sgabeblack@google.com s = nullptr; 28114184Sgabeblack@google.com } 28214184Sgabeblack@google.com pendingStaticSensitivities.clear(); 28314184Sgabeblack@google.com}; 28414184Sgabeblack@google.com 28514184Sgabeblack@google.comvoid 28614184Sgabeblack@google.comProcess::run() 28714184Sgabeblack@google.com{ 28814184Sgabeblack@google.com bool reset; 28914184Sgabeblack@google.com do { 29014184Sgabeblack@google.com reset = false; 29114184Sgabeblack@google.com try { 29214184Sgabeblack@google.com func->call(); 29314184Sgabeblack@google.com } catch(const ::sc_core::sc_unwind_exception &exc) { 29414184Sgabeblack@google.com reset = exc.is_reset(); 29514184Sgabeblack@google.com _isUnwinding = false; 29614184Sgabeblack@google.com } 29714184Sgabeblack@google.com } while (reset); 29814184Sgabeblack@google.com _terminated = true; 29914184Sgabeblack@google.com} 30014184Sgabeblack@google.com 30114184Sgabeblack@google.comvoid 30214184Sgabeblack@google.comProcess::addStatic(PendingSensitivity *s) 30314184Sgabeblack@google.com{ 30414184Sgabeblack@google.com pendingStaticSensitivities.push_back(s); 30514184Sgabeblack@google.com} 30614184Sgabeblack@google.com 30714184Sgabeblack@google.comvoid 30814184Sgabeblack@google.comProcess::setDynamic(Sensitivity *s) 30914184Sgabeblack@google.com{ 31014184Sgabeblack@google.com delete dynamicSensitivity; 31114184Sgabeblack@google.com dynamicSensitivity = s; 31214184Sgabeblack@google.com} 31314184Sgabeblack@google.com 31414184Sgabeblack@google.comvoid 31514184Sgabeblack@google.comProcess::satisfySensitivity(Sensitivity *s) 31614184Sgabeblack@google.com{ 31714184Sgabeblack@google.com // If there's a dynamic sensitivity and this wasn't it, ignore. 31814184Sgabeblack@google.com if (dynamicSensitivity && dynamicSensitivity != s) 31914184Sgabeblack@google.com return; 32014184Sgabeblack@google.com 32114184Sgabeblack@google.com setDynamic(nullptr); 32214184Sgabeblack@google.com ready(); 32314184Sgabeblack@google.com} 32414184Sgabeblack@google.com 32514184Sgabeblack@google.comvoid 32614184Sgabeblack@google.comProcess::ready() 32714184Sgabeblack@google.com{ 32814184Sgabeblack@google.com if (disabled()) 32914184Sgabeblack@google.com return; 33014184Sgabeblack@google.com if (suspended()) 33114184Sgabeblack@google.com _suspendedReady = true; 33214184Sgabeblack@google.com else 33314184Sgabeblack@google.com scheduler.ready(this); 33414184Sgabeblack@google.com} 33514184Sgabeblack@google.com 33614184Sgabeblack@google.comProcess::Process(const char *name, ProcessFuncWrapper *func, 33714184Sgabeblack@google.com bool _dynamic, bool needs_start) : 33814184Sgabeblack@google.com ::sc_core::sc_object(name), excWrapper(nullptr), func(func), 33914184Sgabeblack@google.com _needsStart(needs_start), _dynamic(_dynamic), _isUnwinding(false), 34014184Sgabeblack@google.com _terminated(false), _suspended(false), _disabled(false), 34114184Sgabeblack@google.com _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize), 34214184Sgabeblack@google.com dynamicSensitivity(nullptr) 34314184Sgabeblack@google.com{ 34414184Sgabeblack@google.com _newest = this; 34514184Sgabeblack@google.com} 34614184Sgabeblack@google.com 34714184Sgabeblack@google.comProcess *Process::_newest; 34814184Sgabeblack@google.com 34914184Sgabeblack@google.comvoid 35014184Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids) 35114184Sgabeblack@google.com{ 35214184Sgabeblack@google.com p->throw_it(exc, inc_kids); 35314184Sgabeblack@google.com} 35414184Sgabeblack@google.com 35514184Sgabeblack@google.com} // namespace sc_gem5 35614184Sgabeblack@google.com