process.cc revision 12957
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.comvoid
4012957Sgabeblack@google.comSensitivity::satisfy()
4112957Sgabeblack@google.com{
4212957Sgabeblack@google.com    warn_once("Ignoring suspended status for now.\n");
4312957Sgabeblack@google.com    process->setDynamic(nullptr);
4412957Sgabeblack@google.com    scheduler.ready(process);
4512957Sgabeblack@google.com}
4612957Sgabeblack@google.com
4712957Sgabeblack@google.comSensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
4812957Sgabeblack@google.com    Sensitivity(p), timeoutEvent(this), timeout(t)
4912957Sgabeblack@google.com{
5012957Sgabeblack@google.com    Tick when = scheduler.eventQueue().getCurTick() + timeout.value();
5112957Sgabeblack@google.com    scheduler.eventQueue().schedule(&timeoutEvent, when);
5212957Sgabeblack@google.com}
5312957Sgabeblack@google.com
5412957Sgabeblack@google.comSensitivityTimeout::~SensitivityTimeout()
5512957Sgabeblack@google.com{
5612957Sgabeblack@google.com    if (timeoutEvent.scheduled())
5712957Sgabeblack@google.com        scheduler.eventQueue().deschedule(&timeoutEvent);
5812957Sgabeblack@google.com}
5912957Sgabeblack@google.com
6012957Sgabeblack@google.comSensitivityEvent::SensitivityEvent(
6112957Sgabeblack@google.com        Process *p, const ::sc_core::sc_event *e) : Sensitivity(p), event(e)
6212957Sgabeblack@google.com{
6312957Sgabeblack@google.com    Event::getFromScEvent(event)->addSensitivity(this);
6412957Sgabeblack@google.com}
6512957Sgabeblack@google.com
6612957Sgabeblack@google.comSensitivityEvent::~SensitivityEvent()
6712957Sgabeblack@google.com{
6812957Sgabeblack@google.com    Event::getFromScEvent(event)->delSensitivity(this);
6912957Sgabeblack@google.com}
7012957Sgabeblack@google.com
7112957Sgabeblack@google.comSensitivityEventAndList::SensitivityEventAndList(
7212957Sgabeblack@google.com        Process *p, const ::sc_core::sc_event_and_list *list) :
7312957Sgabeblack@google.com    Sensitivity(p), list(list), count(0)
7412957Sgabeblack@google.com{
7512957Sgabeblack@google.com    for (auto e: list->events)
7612957Sgabeblack@google.com        Event::getFromScEvent(e)->addSensitivity(this);
7712957Sgabeblack@google.com}
7812957Sgabeblack@google.com
7912957Sgabeblack@google.comSensitivityEventAndList::~SensitivityEventAndList()
8012957Sgabeblack@google.com{
8112957Sgabeblack@google.com    for (auto e: list->events)
8212957Sgabeblack@google.com        Event::getFromScEvent(e)->delSensitivity(this);
8312957Sgabeblack@google.com}
8412957Sgabeblack@google.com
8512957Sgabeblack@google.comvoid
8612957Sgabeblack@google.comSensitivityEventAndList::notifyWork(Event *e)
8712957Sgabeblack@google.com{
8812957Sgabeblack@google.com    e->delSensitivity(this);
8912957Sgabeblack@google.com    count++;
9012957Sgabeblack@google.com    if (count == list->events.size())
9112957Sgabeblack@google.com        satisfy();
9212957Sgabeblack@google.com}
9312957Sgabeblack@google.com
9412957Sgabeblack@google.comSensitivityEventOrList::SensitivityEventOrList(
9512957Sgabeblack@google.com        Process *p, const ::sc_core::sc_event_or_list *list) :
9612957Sgabeblack@google.com    Sensitivity(p), list(list)
9712957Sgabeblack@google.com{
9812957Sgabeblack@google.com    for (auto e: list->events)
9912957Sgabeblack@google.com        Event::getFromScEvent(e)->addSensitivity(this);
10012957Sgabeblack@google.com}
10112957Sgabeblack@google.com
10212957Sgabeblack@google.comSensitivityEventOrList::~SensitivityEventOrList()
10312957Sgabeblack@google.com{
10412957Sgabeblack@google.com    for (auto e: list->events)
10512957Sgabeblack@google.com        Event::getFromScEvent(e)->delSensitivity(this);
10612957Sgabeblack@google.com}
10712957Sgabeblack@google.com
10812957Sgabeblack@google.com
10912952Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception
11012952Sgabeblack@google.com{
11112952Sgabeblack@google.com  public:
11212952Sgabeblack@google.com    const char *what() const throw() override { return "RESET"; }
11312952Sgabeblack@google.com    bool is_reset() const override { return true; }
11412952Sgabeblack@google.com};
11512952Sgabeblack@google.com
11612952Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception
11712952Sgabeblack@google.com{
11812952Sgabeblack@google.com  public:
11912952Sgabeblack@google.com    const char *what() const throw() override { return "KILL"; }
12012952Sgabeblack@google.com    bool is_reset() const override { return false; }
12112952Sgabeblack@google.com};
12212952Sgabeblack@google.com
12312952Sgabeblack@google.comtemplate <typename T>
12412952Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase
12512952Sgabeblack@google.com{
12612952Sgabeblack@google.com  public:
12712952Sgabeblack@google.com    T t;
12812952Sgabeblack@google.com    void throw_it() override { throw t; }
12912952Sgabeblack@google.com};
13012952Sgabeblack@google.com
13112952Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException;
13212952Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException;
13312952Sgabeblack@google.com
13412952Sgabeblack@google.com
13512952Sgabeblack@google.comvoid
13612952Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work)
13712952Sgabeblack@google.com{
13812952Sgabeblack@google.com    for (auto &kid: get_child_objects()) {
13912952Sgabeblack@google.com        Process *p_kid = dynamic_cast<Process *>(kid);
14012952Sgabeblack@google.com        if (p_kid)
14112952Sgabeblack@google.com            work(p_kid);
14212952Sgabeblack@google.com    }
14312952Sgabeblack@google.com}
14412952Sgabeblack@google.com
14512952Sgabeblack@google.comvoid
14612952Sgabeblack@google.comProcess::suspend(bool inc_kids)
14712952Sgabeblack@google.com{
14812952Sgabeblack@google.com    if (inc_kids)
14912952Sgabeblack@google.com        forEachKid([](Process *p) { p->suspend(true); });
15012952Sgabeblack@google.com
15112952Sgabeblack@google.com    if (!_suspended) {
15212952Sgabeblack@google.com        _suspended = true;
15312952Sgabeblack@google.com        //TODO Suspend this process.
15412952Sgabeblack@google.com    }
15512952Sgabeblack@google.com
15612953Sgabeblack@google.com    if (procKind() != ::sc_core::SC_METHOD_PROC_ &&
15712953Sgabeblack@google.com            scheduler.current() == this) {
15812953Sgabeblack@google.com        scheduler.yield();
15912952Sgabeblack@google.com    }
16012952Sgabeblack@google.com}
16112952Sgabeblack@google.com
16212952Sgabeblack@google.comvoid
16312952Sgabeblack@google.comProcess::resume(bool inc_kids)
16412952Sgabeblack@google.com{
16512952Sgabeblack@google.com    if (inc_kids)
16612952Sgabeblack@google.com        forEachKid([](Process *p) { p->resume(true); });
16712952Sgabeblack@google.com
16812952Sgabeblack@google.com    if (_suspended) {
16912952Sgabeblack@google.com        _suspended = false;
17012952Sgabeblack@google.com        //TODO Resume this process.
17112952Sgabeblack@google.com    }
17212952Sgabeblack@google.com}
17312952Sgabeblack@google.com
17412952Sgabeblack@google.comvoid
17512952Sgabeblack@google.comProcess::disable(bool inc_kids)
17612952Sgabeblack@google.com{
17712952Sgabeblack@google.com    if (inc_kids)
17812952Sgabeblack@google.com        forEachKid([](Process *p) { p->disable(true); });
17912952Sgabeblack@google.com
18012952Sgabeblack@google.com    _disabled = true;
18112952Sgabeblack@google.com}
18212952Sgabeblack@google.com
18312952Sgabeblack@google.comvoid
18412952Sgabeblack@google.comProcess::enable(bool inc_kids)
18512952Sgabeblack@google.com{
18612952Sgabeblack@google.com
18712952Sgabeblack@google.com    if (inc_kids)
18812952Sgabeblack@google.com        forEachKid([](Process *p) { p->enable(true); });
18912952Sgabeblack@google.com
19012952Sgabeblack@google.com    _disabled = false;
19112952Sgabeblack@google.com}
19212952Sgabeblack@google.com
19312952Sgabeblack@google.comvoid
19412952Sgabeblack@google.comProcess::kill(bool inc_kids)
19512952Sgabeblack@google.com{
19612952Sgabeblack@google.com    // Update our state.
19712952Sgabeblack@google.com    _terminated = true;
19812952Sgabeblack@google.com    _isUnwinding = true;
19912952Sgabeblack@google.com
20012952Sgabeblack@google.com    // Propogate the kill to our children no matter what happens to us.
20112952Sgabeblack@google.com    if (inc_kids)
20212952Sgabeblack@google.com        forEachKid([](Process *p) { p->kill(true); });
20312952Sgabeblack@google.com
20412952Sgabeblack@google.com    // If we're in the middle of unwinding, ignore the kill request.
20512952Sgabeblack@google.com    if (_isUnwinding)
20612952Sgabeblack@google.com        return;
20712952Sgabeblack@google.com
20812952Sgabeblack@google.com    // Inject the kill exception into this process.
20912952Sgabeblack@google.com    injectException(killException);
21012952Sgabeblack@google.com
21112952Sgabeblack@google.com    _terminatedEvent.notify();
21212952Sgabeblack@google.com}
21312952Sgabeblack@google.com
21412952Sgabeblack@google.comvoid
21512952Sgabeblack@google.comProcess::reset(bool inc_kids)
21612952Sgabeblack@google.com{
21712952Sgabeblack@google.com    // Update our state.
21812952Sgabeblack@google.com    _isUnwinding = true;
21912952Sgabeblack@google.com
22012952Sgabeblack@google.com    // Propogate the reset to our children no matter what happens to us.
22112952Sgabeblack@google.com    if (inc_kids)
22212952Sgabeblack@google.com        forEachKid([](Process *p) { p->reset(true); });
22312952Sgabeblack@google.com
22412952Sgabeblack@google.com    // If we're in the middle of unwinding, ignore the reset request.
22512952Sgabeblack@google.com    if (_isUnwinding)
22612952Sgabeblack@google.com        return;
22712952Sgabeblack@google.com
22812952Sgabeblack@google.com    // Inject the reset exception into this process.
22912952Sgabeblack@google.com    injectException(resetException);
23012952Sgabeblack@google.com
23112952Sgabeblack@google.com    _resetEvent.notify();
23212952Sgabeblack@google.com}
23312952Sgabeblack@google.com
23412952Sgabeblack@google.comvoid
23512952Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
23612952Sgabeblack@google.com{
23712952Sgabeblack@google.com    if (inc_kids)
23812952Sgabeblack@google.com        forEachKid([&exc](Process *p) { p->throw_it(exc, true); });
23912952Sgabeblack@google.com}
24012952Sgabeblack@google.com
24112952Sgabeblack@google.comvoid
24212952Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc)
24312952Sgabeblack@google.com{
24412952Sgabeblack@google.com    excWrapper = &exc;
24512952Sgabeblack@google.com    // Let this process preempt us.
24612952Sgabeblack@google.com};
24712952Sgabeblack@google.com
24812952Sgabeblack@google.comvoid
24912952Sgabeblack@google.comProcess::syncResetOn(bool inc_kids)
25012952Sgabeblack@google.com{
25112952Sgabeblack@google.com    if (inc_kids)
25212952Sgabeblack@google.com        forEachKid([](Process *p) { p->syncResetOn(true); });
25312952Sgabeblack@google.com
25412952Sgabeblack@google.com    _syncReset = true;
25512952Sgabeblack@google.com}
25612952Sgabeblack@google.com
25712952Sgabeblack@google.comvoid
25812952Sgabeblack@google.comProcess::syncResetOff(bool inc_kids)
25912952Sgabeblack@google.com{
26012952Sgabeblack@google.com    if (inc_kids)
26112952Sgabeblack@google.com        forEachKid([](Process *p) { p->syncResetOff(true); });
26212952Sgabeblack@google.com
26312952Sgabeblack@google.com    _syncReset = false;
26412952Sgabeblack@google.com}
26512952Sgabeblack@google.com
26612952Sgabeblack@google.comvoid
26712957Sgabeblack@google.comProcess::dontInitialize()
26812957Sgabeblack@google.com{
26912957Sgabeblack@google.com    scheduler.dontInitialize(this);
27012957Sgabeblack@google.com}
27112957Sgabeblack@google.com
27212957Sgabeblack@google.comvoid
27312957Sgabeblack@google.comProcess::finalize()
27412957Sgabeblack@google.com{
27512957Sgabeblack@google.com    for (auto &s: pendingStaticSensitivities) {
27612957Sgabeblack@google.com        s->finalize(staticSensitivities);
27712957Sgabeblack@google.com        delete s;
27812957Sgabeblack@google.com        s = nullptr;
27912957Sgabeblack@google.com    }
28012957Sgabeblack@google.com    pendingStaticSensitivities.clear();
28112957Sgabeblack@google.com};
28212957Sgabeblack@google.com
28312957Sgabeblack@google.comvoid
28412953Sgabeblack@google.comProcess::run()
28512952Sgabeblack@google.com{
28612953Sgabeblack@google.com    _running = true;
28712953Sgabeblack@google.com    bool reset;
28812953Sgabeblack@google.com    do {
28912953Sgabeblack@google.com        reset = false;
29012953Sgabeblack@google.com        try {
29112953Sgabeblack@google.com            func->call();
29212953Sgabeblack@google.com        } catch(::sc_core::sc_unwind_exception exc) {
29312953Sgabeblack@google.com            reset = exc.is_reset();
29412953Sgabeblack@google.com        }
29512953Sgabeblack@google.com    } while (reset);
29612953Sgabeblack@google.com    _running = false;
29712953Sgabeblack@google.com}
29812952Sgabeblack@google.com
29912957Sgabeblack@google.comvoid
30012957Sgabeblack@google.comProcess::addStatic(PendingSensitivity *s)
30112957Sgabeblack@google.com{
30212957Sgabeblack@google.com    pendingStaticSensitivities.push_back(s);
30312957Sgabeblack@google.com}
30412957Sgabeblack@google.com
30512957Sgabeblack@google.comvoid
30612957Sgabeblack@google.comProcess::setDynamic(Sensitivity *s)
30712957Sgabeblack@google.com{
30812957Sgabeblack@google.com    delete dynamicSensitivity;
30912957Sgabeblack@google.com    dynamicSensitivity = s;
31012957Sgabeblack@google.com}
31112957Sgabeblack@google.com
31212953Sgabeblack@google.comProcess::Process(const char *name, ProcessFuncWrapper *func, bool _dynamic) :
31312953Sgabeblack@google.com    ::sc_core::sc_object(name), excWrapper(nullptr), func(func),
31412953Sgabeblack@google.com    _running(false), _dynamic(_dynamic), _isUnwinding(false),
31512953Sgabeblack@google.com    _terminated(false), _suspended(false), _disabled(false),
31612957Sgabeblack@google.com    _syncReset(false), refCount(0), stackSize(::Fiber::DefaultStackSize),
31712957Sgabeblack@google.com    dynamicSensitivity(nullptr)
31812953Sgabeblack@google.com{
31912953Sgabeblack@google.com    _newest = this;
32012957Sgabeblack@google.com    if (_dynamic)
32112957Sgabeblack@google.com        finalize();
32212957Sgabeblack@google.com    else
32312957Sgabeblack@google.com        scheduler.reg(this);
32412953Sgabeblack@google.com}
32512952Sgabeblack@google.com
32612953Sgabeblack@google.comProcess *Process::_newest;
32712952Sgabeblack@google.com
32812952Sgabeblack@google.comvoid
32912952Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
33012952Sgabeblack@google.com{
33112952Sgabeblack@google.com    p->throw_it(exc, inc_kids);
33212952Sgabeblack@google.com}
33312952Sgabeblack@google.com
33412952Sgabeblack@google.com} // namespace sc_gem5
335