process.cc revision 12952:94fca7e8120b
112854Sgabeblack@google.com/*
212854Sgabeblack@google.com * Copyright 2018 Google, Inc.
312854Sgabeblack@google.com *
412854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
512854Sgabeblack@google.com * modification, are permitted provided that the following conditions are
612854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
712854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
812854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
912854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1012854Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1112854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1212854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1312854Sgabeblack@google.com * this software without specific prior written permission.
1412854Sgabeblack@google.com *
1512854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1612854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1712854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1812854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1912854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2012854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2112854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2212854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2312854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2412854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2512854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2612854Sgabeblack@google.com *
2712854Sgabeblack@google.com * Authors: Gabe Black
2812854Sgabeblack@google.com */
2912854Sgabeblack@google.com
3012854Sgabeblack@google.com#include "systemc/core/process.hh"
3112854Sgabeblack@google.com
3212854Sgabeblack@google.comnamespace sc_gem5
3312854Sgabeblack@google.com{
3412854Sgabeblack@google.com
3512854Sgabeblack@google.comclass UnwindExceptionReset : public ::sc_core::sc_unwind_exception
3612854Sgabeblack@google.com{
3712854Sgabeblack@google.com  public:
3812854Sgabeblack@google.com    const char *what() const throw() override { return "RESET"; }
3912854Sgabeblack@google.com    bool is_reset() const override { return true; }
4012854Sgabeblack@google.com};
4112854Sgabeblack@google.com
4212854Sgabeblack@google.comclass UnwindExceptionKill : public ::sc_core::sc_unwind_exception
4312854Sgabeblack@google.com{
4412854Sgabeblack@google.com  public:
4512854Sgabeblack@google.com    const char *what() const throw() override { return "KILL"; }
4612854Sgabeblack@google.com    bool is_reset() const override { return false; }
4712854Sgabeblack@google.com};
4812854Sgabeblack@google.com
4912854Sgabeblack@google.comtemplate <typename T>
5012854Sgabeblack@google.comstruct BuiltinExceptionWrapper : public ExceptionWrapperBase
5112854Sgabeblack@google.com{
5212854Sgabeblack@google.com  public:
5312854Sgabeblack@google.com    T t;
5412854Sgabeblack@google.com    void throw_it() override { throw t; }
5512854Sgabeblack@google.com};
5612854Sgabeblack@google.com
5712854Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionReset> resetException;
5812854Sgabeblack@google.comBuiltinExceptionWrapper<UnwindExceptionKill> killException;
5912854Sgabeblack@google.com
6012854Sgabeblack@google.com
6112854Sgabeblack@google.comvoid
6212854Sgabeblack@google.comProcess::forEachKid(const std::function<void(Process *)> &work)
6312854Sgabeblack@google.com{
6412854Sgabeblack@google.com    for (auto &kid: get_child_objects()) {
6512854Sgabeblack@google.com        Process *p_kid = dynamic_cast<Process *>(kid);
6612854Sgabeblack@google.com        if (p_kid)
6712854Sgabeblack@google.com            work(p_kid);
6812854Sgabeblack@google.com    }
6912854Sgabeblack@google.com}
7012854Sgabeblack@google.com
7112854Sgabeblack@google.comvoid
7212854Sgabeblack@google.comProcess::suspend(bool inc_kids)
7312854Sgabeblack@google.com{
7412854Sgabeblack@google.com    if (inc_kids)
7512854Sgabeblack@google.com        forEachKid([](Process *p) { p->suspend(true); });
7612854Sgabeblack@google.com
7712854Sgabeblack@google.com    if (!_suspended) {
7812854Sgabeblack@google.com        _suspended = true;
7912854Sgabeblack@google.com        //TODO Suspend this process.
8012854Sgabeblack@google.com    }
8112854Sgabeblack@google.com
8212854Sgabeblack@google.com    if (procKind() != ::sc_core::SC_METHOD_PROC_ /* && we're running */) {
8312854Sgabeblack@google.com        // We suspended this thread or cthread. Stop running.
8412854Sgabeblack@google.com    }
8512854Sgabeblack@google.com}
8612854Sgabeblack@google.com
8712854Sgabeblack@google.comvoid
8812854Sgabeblack@google.comProcess::resume(bool inc_kids)
8912854Sgabeblack@google.com{
9012854Sgabeblack@google.com    if (inc_kids)
9112854Sgabeblack@google.com        forEachKid([](Process *p) { p->resume(true); });
9212854Sgabeblack@google.com
9312854Sgabeblack@google.com    if (_suspended) {
9412854Sgabeblack@google.com        _suspended = false;
9512854Sgabeblack@google.com        //TODO Resume this process.
9612854Sgabeblack@google.com    }
9712854Sgabeblack@google.com}
9812854Sgabeblack@google.com
9912854Sgabeblack@google.comvoid
10012854Sgabeblack@google.comProcess::disable(bool inc_kids)
10112854Sgabeblack@google.com{
10212854Sgabeblack@google.com    if (inc_kids)
10312854Sgabeblack@google.com        forEachKid([](Process *p) { p->disable(true); });
10412854Sgabeblack@google.com
10512854Sgabeblack@google.com    _disabled = true;
10612854Sgabeblack@google.com}
10712854Sgabeblack@google.com
10812854Sgabeblack@google.comvoid
10912854Sgabeblack@google.comProcess::enable(bool inc_kids)
11012854Sgabeblack@google.com{
11112854Sgabeblack@google.com
11212854Sgabeblack@google.com    if (inc_kids)
11312854Sgabeblack@google.com        forEachKid([](Process *p) { p->enable(true); });
11412854Sgabeblack@google.com
11512854Sgabeblack@google.com    _disabled = false;
11612854Sgabeblack@google.com}
11712854Sgabeblack@google.com
11812854Sgabeblack@google.comvoid
11912854Sgabeblack@google.comProcess::kill(bool inc_kids)
12012854Sgabeblack@google.com{
12112854Sgabeblack@google.com    // Update our state.
12212854Sgabeblack@google.com    _terminated = true;
12312854Sgabeblack@google.com    _isUnwinding = true;
12412854Sgabeblack@google.com
12512854Sgabeblack@google.com    // Propogate the kill to our children no matter what happens to us.
12612854Sgabeblack@google.com    if (inc_kids)
12712854Sgabeblack@google.com        forEachKid([](Process *p) { p->kill(true); });
12812854Sgabeblack@google.com
12912854Sgabeblack@google.com    // If we're in the middle of unwinding, ignore the kill request.
13012854Sgabeblack@google.com    if (_isUnwinding)
13112854Sgabeblack@google.com        return;
13212854Sgabeblack@google.com
13312854Sgabeblack@google.com    // Inject the kill exception into this process.
13412854Sgabeblack@google.com    injectException(killException);
13512854Sgabeblack@google.com
13612854Sgabeblack@google.com    _terminatedEvent.notify();
13712854Sgabeblack@google.com}
13812854Sgabeblack@google.com
13912854Sgabeblack@google.comvoid
14012854Sgabeblack@google.comProcess::reset(bool inc_kids)
14112854Sgabeblack@google.com{
14212854Sgabeblack@google.com    // Update our state.
14312854Sgabeblack@google.com    _isUnwinding = true;
14412854Sgabeblack@google.com
14512854Sgabeblack@google.com    // Propogate the reset to our children no matter what happens to us.
14612854Sgabeblack@google.com    if (inc_kids)
14712854Sgabeblack@google.com        forEachKid([](Process *p) { p->reset(true); });
14812854Sgabeblack@google.com
14912854Sgabeblack@google.com    // If we're in the middle of unwinding, ignore the reset request.
15012854Sgabeblack@google.com    if (_isUnwinding)
15112854Sgabeblack@google.com        return;
15212854Sgabeblack@google.com
15312854Sgabeblack@google.com    // Inject the reset exception into this process.
15412854Sgabeblack@google.com    injectException(resetException);
15512854Sgabeblack@google.com
15612854Sgabeblack@google.com    _resetEvent.notify();
15712854Sgabeblack@google.com}
15812854Sgabeblack@google.com
15912854Sgabeblack@google.comvoid
16012854Sgabeblack@google.comProcess::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
16112854Sgabeblack@google.com{
16212854Sgabeblack@google.com    if (inc_kids)
16312854Sgabeblack@google.com        forEachKid([&exc](Process *p) { p->throw_it(exc, true); });
16412854Sgabeblack@google.com}
16512854Sgabeblack@google.com
16612854Sgabeblack@google.comvoid
16712854Sgabeblack@google.comProcess::injectException(ExceptionWrapperBase &exc)
16812854Sgabeblack@google.com{
16912854Sgabeblack@google.com    excWrapper = &exc;
17012854Sgabeblack@google.com    // Let this process preempt us.
17112854Sgabeblack@google.com};
17212854Sgabeblack@google.com
17312854Sgabeblack@google.comvoid
17412854Sgabeblack@google.comProcess::syncResetOn(bool inc_kids)
17512854Sgabeblack@google.com{
17612854Sgabeblack@google.com    if (inc_kids)
17712854Sgabeblack@google.com        forEachKid([](Process *p) { p->syncResetOn(true); });
17812854Sgabeblack@google.com
17912854Sgabeblack@google.com    _syncReset = true;
18012854Sgabeblack@google.com}
18112854Sgabeblack@google.com
18212854Sgabeblack@google.comvoid
18312854Sgabeblack@google.comProcess::syncResetOff(bool inc_kids)
18412854Sgabeblack@google.com{
18512854Sgabeblack@google.com    if (inc_kids)
18612854Sgabeblack@google.com        forEachKid([](Process *p) { p->syncResetOff(true); });
18712854Sgabeblack@google.com
18812854Sgabeblack@google.com    _syncReset = false;
18912854Sgabeblack@google.com}
19012854Sgabeblack@google.com
19112854Sgabeblack@google.comvoid
19212854Sgabeblack@google.comThread::throw_it(ExceptionWrapperBase &exc, bool inc_kids)
19312854Sgabeblack@google.com{
19412854Sgabeblack@google.com    Process::throw_it(exc, inc_kids);
19512854Sgabeblack@google.com
19612854Sgabeblack@google.com    if (_terminated)
19712854Sgabeblack@google.com        return;
19812854Sgabeblack@google.com
19912854Sgabeblack@google.com    injectException(exc);
20012854Sgabeblack@google.com}
20112854Sgabeblack@google.com
20212854Sgabeblack@google.comvoid
20312854Sgabeblack@google.comthrow_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
20412854Sgabeblack@google.com{
20512854Sgabeblack@google.com    p->throw_it(exc, inc_kids);
20612854Sgabeblack@google.com}
20712854Sgabeblack@google.com
20812854Sgabeblack@google.com} // namespace sc_gem5
20912854Sgabeblack@google.com