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