process.cc revision 12952
1/* 2 * Copyright 2018 Google, Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer; 8 * redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution; 11 * neither the name of the copyright holders nor the names of its 12 * contributors may be used to endorse or promote products derived from 13 * this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * Authors: Gabe Black 28 */ 29 30#include "systemc/core/process.hh" 31 32namespace sc_gem5 33{ 34 35class UnwindExceptionReset : public ::sc_core::sc_unwind_exception 36{ 37 public: 38 const char *what() const throw() override { return "RESET"; } 39 bool is_reset() const override { return true; } 40}; 41 42class UnwindExceptionKill : public ::sc_core::sc_unwind_exception 43{ 44 public: 45 const char *what() const throw() override { return "KILL"; } 46 bool is_reset() const override { return false; } 47}; 48 49template <typename T> 50struct BuiltinExceptionWrapper : public ExceptionWrapperBase 51{ 52 public: 53 T t; 54 void throw_it() override { throw t; } 55}; 56 57BuiltinExceptionWrapper<UnwindExceptionReset> resetException; 58BuiltinExceptionWrapper<UnwindExceptionKill> killException; 59 60 61void 62Process::forEachKid(const std::function<void(Process *)> &work) 63{ 64 for (auto &kid: get_child_objects()) { 65 Process *p_kid = dynamic_cast<Process *>(kid); 66 if (p_kid) 67 work(p_kid); 68 } 69} 70 71void 72Process::suspend(bool inc_kids) 73{ 74 if (inc_kids) 75 forEachKid([](Process *p) { p->suspend(true); }); 76 77 if (!_suspended) { 78 _suspended = true; 79 //TODO Suspend this process. 80 } 81 82 if (procKind() != ::sc_core::SC_METHOD_PROC_ /* && we're running */) { 83 // We suspended this thread or cthread. Stop running. 84 } 85} 86 87void 88Process::resume(bool inc_kids) 89{ 90 if (inc_kids) 91 forEachKid([](Process *p) { p->resume(true); }); 92 93 if (_suspended) { 94 _suspended = false; 95 //TODO Resume this process. 96 } 97} 98 99void 100Process::disable(bool inc_kids) 101{ 102 if (inc_kids) 103 forEachKid([](Process *p) { p->disable(true); }); 104 105 _disabled = true; 106} 107 108void 109Process::enable(bool inc_kids) 110{ 111 112 if (inc_kids) 113 forEachKid([](Process *p) { p->enable(true); }); 114 115 _disabled = false; 116} 117 118void 119Process::kill(bool inc_kids) 120{ 121 // Update our state. 122 _terminated = true; 123 _isUnwinding = true; 124 125 // Propogate the kill to our children no matter what happens to us. 126 if (inc_kids) 127 forEachKid([](Process *p) { p->kill(true); }); 128 129 // If we're in the middle of unwinding, ignore the kill request. 130 if (_isUnwinding) 131 return; 132 133 // Inject the kill exception into this process. 134 injectException(killException); 135 136 _terminatedEvent.notify(); 137} 138 139void 140Process::reset(bool inc_kids) 141{ 142 // Update our state. 143 _isUnwinding = true; 144 145 // Propogate the reset to our children no matter what happens to us. 146 if (inc_kids) 147 forEachKid([](Process *p) { p->reset(true); }); 148 149 // If we're in the middle of unwinding, ignore the reset request. 150 if (_isUnwinding) 151 return; 152 153 // Inject the reset exception into this process. 154 injectException(resetException); 155 156 _resetEvent.notify(); 157} 158 159void 160Process::throw_it(ExceptionWrapperBase &exc, bool inc_kids) 161{ 162 if (inc_kids) 163 forEachKid([&exc](Process *p) { p->throw_it(exc, true); }); 164} 165 166void 167Process::injectException(ExceptionWrapperBase &exc) 168{ 169 excWrapper = &exc; 170 // Let this process preempt us. 171}; 172 173void 174Process::syncResetOn(bool inc_kids) 175{ 176 if (inc_kids) 177 forEachKid([](Process *p) { p->syncResetOn(true); }); 178 179 _syncReset = true; 180} 181 182void 183Process::syncResetOff(bool inc_kids) 184{ 185 if (inc_kids) 186 forEachKid([](Process *p) { p->syncResetOff(true); }); 187 188 _syncReset = false; 189} 190 191void 192Thread::throw_it(ExceptionWrapperBase &exc, bool inc_kids) 193{ 194 Process::throw_it(exc, inc_kids); 195 196 if (_terminated) 197 return; 198 199 injectException(exc); 200} 201 202void 203throw_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids) 204{ 205 p->throw_it(exc, inc_kids); 206} 207 208} // namespace sc_gem5 209