process.cc revision 12953
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" 3112953Sgabeblack@google.com#include "systemc/core/scheduler.hh" 3212952Sgabeblack@google.com 3312952Sgabeblack@google.comnamespace sc_gem5 3412952Sgabeblack@google.com{ 3512952Sgabeblack@google.com 3612952Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception 3712952Sgabeblack@google.com{ 3812952Sgabeblack@google.com public: 3912952Sgabeblack@google.com const char *what() const throw() override { return "RESET"; } 4012952Sgabeblack@google.com bool is_reset() const override { return true; } 4112952Sgabeblack@google.com}; 4212952Sgabeblack@google.com 4312952Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception 4412952Sgabeblack@google.com{ 4512952Sgabeblack@google.com public: 4612952Sgabeblack@google.com const char *what() const throw() override { return "KILL"; } 4712952Sgabeblack@google.com bool is_reset() const override { return false; } 4812952Sgabeblack@google.com}; 4912952Sgabeblack@google.com 5012952Sgabeblack@google.comtemplate <typename T> 5112952Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase 5212952Sgabeblack@google.com{ 5312952Sgabeblack@google.com public: 5412952Sgabeblack@google.com T t; 5512952Sgabeblack@google.com void throw_it() override { throw t; } 5612952Sgabeblack@google.com}; 5712952Sgabeblack@google.com 5812952Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException; 5912952Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException; 6012952Sgabeblack@google.com 6112952Sgabeblack@google.com 6212952Sgabeblack@google.comvoid 6312952Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work) 6412952Sgabeblack@google.com{ 6512952Sgabeblack@google.com for (auto &kid: get_child_objects()) { 6612952Sgabeblack@google.com Process *p_kid = dynamic_cast<Process *>(kid); 6712952Sgabeblack@google.com if (p_kid) 6812952Sgabeblack@google.com work(p_kid); 6912952Sgabeblack@google.com } 7012952Sgabeblack@google.com} 7112952Sgabeblack@google.com 7212952Sgabeblack@google.comvoid 7312952Sgabeblack@google.comProcess::suspend(bool inc_kids) 7412952Sgabeblack@google.com{ 7512952Sgabeblack@google.com if (inc_kids) 7612952Sgabeblack@google.com forEachKid([](Process *p) { p->suspend(true); }); 7712952Sgabeblack@google.com 7812952Sgabeblack@google.com if (!_suspended) { 7912952Sgabeblack@google.com _suspended = true; 8012952Sgabeblack@google.com //TODO Suspend this process. 8112952Sgabeblack@google.com } 8212952Sgabeblack@google.com 8312953Sgabeblack@google.com if (procKind() != ::sc_core::SC_METHOD_PROC_ && 8412953Sgabeblack@google.com scheduler.current() == this) { 8512953Sgabeblack@google.com scheduler.yield(); 8612952Sgabeblack@google.com } 8712952Sgabeblack@google.com} 8812952Sgabeblack@google.com 8912952Sgabeblack@google.comvoid 9012952Sgabeblack@google.comProcess::resume(bool inc_kids) 9112952Sgabeblack@google.com{ 9212952Sgabeblack@google.com if (inc_kids) 9312952Sgabeblack@google.com forEachKid([](Process *p) { p->resume(true); }); 9412952Sgabeblack@google.com 9512952Sgabeblack@google.com if (_suspended) { 9612952Sgabeblack@google.com _suspended = false; 9712952Sgabeblack@google.com //TODO Resume this process. 9812952Sgabeblack@google.com } 9912952Sgabeblack@google.com} 10012952Sgabeblack@google.com 10112952Sgabeblack@google.comvoid 10212952Sgabeblack@google.comProcess::disable(bool inc_kids) 10312952Sgabeblack@google.com{ 10412952Sgabeblack@google.com if (inc_kids) 10512952Sgabeblack@google.com forEachKid([](Process *p) { p->disable(true); }); 10612952Sgabeblack@google.com 10712952Sgabeblack@google.com _disabled = true; 10812952Sgabeblack@google.com} 10912952Sgabeblack@google.com 11012952Sgabeblack@google.comvoid 11112952Sgabeblack@google.comProcess::enable(bool inc_kids) 11212952Sgabeblack@google.com{ 11312952Sgabeblack@google.com 11412952Sgabeblack@google.com if (inc_kids) 11512952Sgabeblack@google.com forEachKid([](Process *p) { p->enable(true); }); 11612952Sgabeblack@google.com 11712952Sgabeblack@google.com _disabled = false; 11812952Sgabeblack@google.com} 11912952Sgabeblack@google.com 12012952Sgabeblack@google.comvoid 12112952Sgabeblack@google.comProcess::kill(bool inc_kids) 12212952Sgabeblack@google.com{ 12312952Sgabeblack@google.com // Update our state. 12412952Sgabeblack@google.com _terminated = true; 12512952Sgabeblack@google.com _isUnwinding = true; 12612952Sgabeblack@google.com 12712952Sgabeblack@google.com // Propogate the kill to our children no matter what happens to us. 12812952Sgabeblack@google.com if (inc_kids) 12912952Sgabeblack@google.com forEachKid([](Process *p) { p->kill(true); }); 13012952Sgabeblack@google.com 13112952Sgabeblack@google.com // If we're in the middle of unwinding, ignore the kill request. 13212952Sgabeblack@google.com if (_isUnwinding) 13312952Sgabeblack@google.com return; 13412952Sgabeblack@google.com 13512952Sgabeblack@google.com // Inject the kill exception into this process. 13612952Sgabeblack@google.com injectException(killException); 13712952Sgabeblack@google.com 13812952Sgabeblack@google.com _terminatedEvent.notify(); 13912952Sgabeblack@google.com} 14012952Sgabeblack@google.com 14112952Sgabeblack@google.comvoid 14212952Sgabeblack@google.comProcess::reset(bool inc_kids) 14312952Sgabeblack@google.com{ 14412952Sgabeblack@google.com // Update our state. 14512952Sgabeblack@google.com _isUnwinding = true; 14612952Sgabeblack@google.com 14712952Sgabeblack@google.com // Propogate the reset to our children no matter what happens to us. 14812952Sgabeblack@google.com if (inc_kids) 14912952Sgabeblack@google.com forEachKid([](Process *p) { p->reset(true); }); 15012952Sgabeblack@google.com 15112952Sgabeblack@google.com // If we're in the middle of unwinding, ignore the reset request. 15212952Sgabeblack@google.com if (_isUnwinding) 15312952Sgabeblack@google.com return; 15412952Sgabeblack@google.com 15512952Sgabeblack@google.com // Inject the reset exception into this process. 15612952Sgabeblack@google.com injectException(resetException); 15712952Sgabeblack@google.com 15812952Sgabeblack@google.com _resetEvent.notify(); 15912952Sgabeblack@google.com} 16012952Sgabeblack@google.com 16112952Sgabeblack@google.comvoid 16212952Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids) 16312952Sgabeblack@google.com{ 16412952Sgabeblack@google.com if (inc_kids) 16512952Sgabeblack@google.com forEachKid([&exc](Process *p) { p->throw_it(exc, true); }); 16612952Sgabeblack@google.com} 16712952Sgabeblack@google.com 16812952Sgabeblack@google.comvoid 16912952Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc) 17012952Sgabeblack@google.com{ 17112952Sgabeblack@google.com excWrapper = &exc; 17212952Sgabeblack@google.com // Let this process preempt us. 17312952Sgabeblack@google.com}; 17412952Sgabeblack@google.com 17512952Sgabeblack@google.comvoid 17612952Sgabeblack@google.comProcess::syncResetOn(bool inc_kids) 17712952Sgabeblack@google.com{ 17812952Sgabeblack@google.com if (inc_kids) 17912952Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOn(true); }); 18012952Sgabeblack@google.com 18112952Sgabeblack@google.com _syncReset = true; 18212952Sgabeblack@google.com} 18312952Sgabeblack@google.com 18412952Sgabeblack@google.comvoid 18512952Sgabeblack@google.comProcess::syncResetOff(bool inc_kids) 18612952Sgabeblack@google.com{ 18712952Sgabeblack@google.com if (inc_kids) 18812952Sgabeblack@google.com forEachKid([](Process *p) { p->syncResetOff(true); }); 18912952Sgabeblack@google.com 19012952Sgabeblack@google.com _syncReset = false; 19112952Sgabeblack@google.com} 19212952Sgabeblack@google.com 19312952Sgabeblack@google.comvoid 19412953Sgabeblack@google.comProcess::run() 19512952Sgabeblack@google.com{ 19612953Sgabeblack@google.com _running = true; 19712953Sgabeblack@google.com bool reset; 19812953Sgabeblack@google.com do { 19912953Sgabeblack@google.com reset = false; 20012953Sgabeblack@google.com try { 20112953Sgabeblack@google.com func->call(); 20212953Sgabeblack@google.com } catch(::sc_core::sc_unwind_exception exc) { 20312953Sgabeblack@google.com reset = exc.is_reset(); 20412953Sgabeblack@google.com } 20512953Sgabeblack@google.com } while (reset); 20612953Sgabeblack@google.com _running = false; 20712953Sgabeblack@google.com} 20812952Sgabeblack@google.com 20912953Sgabeblack@google.comProcess::Process(const char *name, ProcessFuncWrapper *func, bool _dynamic) : 21012953Sgabeblack@google.com ::sc_core::sc_object(name), excWrapper(nullptr), func(func), 21112953Sgabeblack@google.com _running(false), _dynamic(_dynamic), _isUnwinding(false), 21212953Sgabeblack@google.com _terminated(false), _suspended(false), _disabled(false), 21312953Sgabeblack@google.com _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize) 21412953Sgabeblack@google.com{ 21512953Sgabeblack@google.com _newest = this; 21612953Sgabeblack@google.com if (!_dynamic) 21712953Sgabeblack@google.com scheduler.init(this); 21812953Sgabeblack@google.com} 21912952Sgabeblack@google.com 22012953Sgabeblack@google.comProcess *Process::_newest; 22112952Sgabeblack@google.com 22212952Sgabeblack@google.comvoid 22312952Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids) 22412952Sgabeblack@google.com{ 22512952Sgabeblack@google.com p->throw_it(exc, inc_kids); 22612952Sgabeblack@google.com} 22712952Sgabeblack@google.com 22812952Sgabeblack@google.com} // namespace sc_gem5 229