gem5  v22.1.0.0
process.cc
Go to the documentation of this file.
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 
28 #include "systemc/core/process.hh"
29 
30 #include "systemc/core/event.hh"
31 #include "systemc/core/port.hh"
38 
39 namespace sc_gem5
40 {
41 
43 {
44  public:
46 };
47 
49 {
50  public:
52 };
53 
54 template <typename T>
56 {
57  public:
58  T t;
59  void throw_it() override { throw t; }
60 };
61 
64 
65 
66 void
67 Process::forEachKid(const std::function<void(Process *)> &work)
68 {
69  for (auto &kid: get_child_objects()) {
70  Process *p_kid = dynamic_cast<Process *>(kid);
71  if (p_kid)
72  work(p_kid);
73  }
74 }
75 
76 void
77 Process::suspend(bool inc_kids)
78 {
79  if (inc_kids)
80  forEachKid([](Process *p) { p->suspend(true); });
81 
82  if (!_suspended && !_terminated) {
83  _suspended = true;
85 
87  scheduler.current() == this) {
88  // This isn't in the spec, but Accellera says that a thread that
89  // self suspends should be marked ready immediately when it's
90  // resumed.
91  _suspendedReady = true;
92  scheduler.yield();
93  }
94  }
95 }
96 
97 void
98 Process::resume(bool inc_kids)
99 {
100  if (inc_kids)
101  forEachKid([](Process *p) { p->resume(true); });
102 
103  if (_suspended && !_terminated) {
104  _suspended = false;
105  if (_suspendedReady)
106  scheduler.resume(this);
107  _suspendedReady = false;
108  }
109 }
110 
111 void
112 Process::disable(bool inc_kids)
113 {
114  if (inc_kids)
115  forEachKid([](Process *p) { p->disable(true); });
116 
119  std::string message("attempt to disable a thread with timeout wait: ");
120  message += name();
122  message.c_str());
123  }
124 
125  if (!_terminated)
126  _disabled = true;
127 }
128 
129 void
130 Process::enable(bool inc_kids)
131 {
132 
133  if (inc_kids)
134  forEachKid([](Process *p) { p->enable(true); });
135 
136  if (!_terminated)
137  _disabled = false;
138 }
139 
140 void
141 Process::kill(bool inc_kids)
142 {
145  name());
146  }
147 
148  // Propogate the kill to our children no matter what happens to us.
149  if (inc_kids)
150  forEachKid([](Process *p) { p->kill(true); });
151 
152  // If we're unwinding or terminated, ignore the kill request.
153  if (_isUnwinding || _terminated)
154  return;
155 
156  // Update our state.
157  terminate();
158  _isUnwinding = true;
159 
160  // Make sure this process isn't marked ready
161  popListNode();
162 
163  // Inject the kill exception into this process if it's started.
164  if (!_needsStart)
166 }
167 
168 void
169 Process::reset(bool inc_kids)
170 {
173  name());
174  }
175 
176  // Propogate the reset to our children no matter what happens to us.
177  if (inc_kids)
178  forEachKid([](Process *p) { p->reset(true); });
179 
180  // If we're already unwinding or terminated, ignore the reset request.
181  if (_isUnwinding || _terminated)
182  return;
183 
184  // Clear suspended ready since we're about to run regardless.
185  _suspendedReady = false;
186 
188 
189  if (_needsStart) {
190  scheduler.runNow(this);
191  } else {
192  _isUnwinding = true;
194  }
195 }
196 
197 void
199 {
202 
203  if (inc_kids)
204  forEachKid([&exc](Process *p) { p->throw_it(exc, true); });
205 
206  if (_needsStart || _terminated ||
209  return;
210  }
211 
212  injectException(exc);
213 }
214 
215 void
217 {
218  excWrapper = &exc;
219  scheduler.runNow(this);
220 };
221 
222 void
223 Process::syncResetOn(bool inc_kids)
224 {
225  if (inc_kids)
226  forEachKid([](Process *p) { p->syncResetOn(true); });
227 
228  _syncReset = true;
229 }
230 
231 void
232 Process::syncResetOff(bool inc_kids)
233 {
234  if (inc_kids)
235  forEachKid([](Process *p) { p->syncResetOff(true); });
236 
237  _syncReset = false;
238 }
239 
240 void
241 Process::signalReset(bool set, bool sync)
242 {
243  if (set) {
244  waitCount(0);
245  if (sync) {
246  syncResetCount++;
247  } else {
248  asyncResetCount++;
249  cancelTimeout();
250  clearDynamic();
251  scheduler.runNext(this);
252  }
253  } else {
254  if (sync)
255  syncResetCount--;
256  else
257  asyncResetCount--;
258  }
259 }
260 
261 void
263 {
264  bool reset;
265  do {
266  reset = false;
267  try {
268  func->call();
269  } catch(ScHalt) {
270  std::cout << "Terminating process " << name() << std::endl;
271  } catch(const ::sc_core::sc_unwind_exception &exc) {
272  reset = exc.is_reset();
273  _isUnwinding = false;
274  } catch (...) {
275  throw;
276  }
277  } while (reset);
278  needsStart(true);
279 }
280 
281 void
283 {
284  staticSensitivities.push_back(s);
285 }
286 
287 void
289 {
290  if (dynamicSensitivity) {
292  delete dynamicSensitivity;
293  }
295 }
296 
297 void
299 {
300  resets.push_back(reset);
301 }
302 
303 void
305 {
306  if (timeoutEvent.scheduled())
308 }
309 
310 void
312 {
313  cancelTimeout();
315 }
316 
317 void
319 {
320  // A process is considered timed_out only if it was also waiting for an
321  // event but got a timeout instead.
322  _timedOut = (dynamicSensitivity != nullptr);
323 
324  setDynamic(nullptr);
325  if (disabled())
326  return;
327 
328  ready();
329 }
330 
331 void
333 {
334  if (_waitCount) {
335  _waitCount--;
336  return;
337  }
338 
339  // If there's a dynamic sensitivity and this wasn't it, ignore.
341  dynamicSensitivity != s) {
342  return;
343  }
344 
345  _timedOut = false;
346  // This sensitivity should already be cleared by this point, or the event
347  // which triggered it will take care of it.
348  delete dynamicSensitivity;
349  dynamicSensitivity = nullptr;
350  cancelTimeout();
351  ready();
352 }
353 
354 void
356 {
357  if (disabled())
358  return;
359  if (suspended())
360  _suspendedReady = true;
361  else if (!scheduled())
362  scheduler.ready(this);
363 }
364 
365 void
367 {
368  if (report) {
369  _lastReport = std::unique_ptr<::sc_core::sc_report>(
370  new ::sc_core::sc_report(*report));
371  } else {
372  _lastReport = nullptr;
373  }
374 }
375 
377 
378 Process::Process(const char *name, ProcessFuncWrapper *func, bool internal) :
379  ::sc_core::sc_process_b(name), excWrapper(nullptr),
380  timeoutEvent([this]() { this->timeout(); }),
381  func(func), _internal(internal), _timedOut(false), _dontInitialize(false),
382  _needsStart(true), _isUnwinding(false), _terminated(false),
383  _scheduled(false), _suspended(false), _disabled(false),
384  _syncReset(false), syncResetCount(0), asyncResetCount(0), _waitCount(0),
385  refCount(0), stackSize(gem5::Fiber::DefaultStackSize),
386  dynamicSensitivity(nullptr)
387 {
388  _dynamic =
391  _newest = this;
392 }
393 
394 void
396 {
397  _terminated = true;
398  _suspendedReady = false;
399  _suspended = false;
400  _syncReset = false;
401  clearDynamic();
402  cancelTimeout();
403  for (auto s: staticSensitivities) {
404  s->clear();
405  delete s;
406  }
407  staticSensitivities.clear();
408 
410 
411  for (auto jw: joinWaiters)
412  jw->signal();
413  joinWaiters.clear();
414 }
415 
417 
418 void
420 {
421  p->throw_it(exc, inc_kids);
422 }
423 
424 void
425 newReset(const sc_core::sc_port_base *pb, Process *p, bool s, bool v)
426 {
427  Port *port = Port::fromPort(pb);
428  port->addReset(new Reset(p, s, v));
429 }
430 
431 void
433 {
434  Reset *reset = new Reset(p, s, v);
435  if (!reset->install(sig))
436  delete reset;
437 }
438 
439 } // namespace sc_gem5
const char * name() const
Definition: sc_object.cc:44
virtual const std::vector< sc_object * > & get_child_objects() const
Definition: sc_object.cc:68
void addReset(Reset *reset)
Definition: port.cc:85
static Port * fromPort(const ::sc_core::sc_port_base *pb)
Definition: port.hh:121
static Process * _newest
Definition: process.hh:147
ScEvent timeoutEvent
Definition: process.hh:113
void kill(bool inc_kids)
Definition: process.cc:141
void suspend(bool inc_kids)
Definition: process.cc:77
void cancelTimeout()
Definition: process.cc:304
void forEachKid(const std::function< void(Process *)> &work)
Definition: process.cc:67
DynamicSensitivity * dynamicSensitivity
Definition: process.hh:196
virtual ::sc_core::sc_curr_proc_kind procKind() const =0
void resume(bool inc_kids)
Definition: process.cc:98
void addReset(Reset *)
Definition: process.cc:298
void disable(bool inc_kids)
Definition: process.cc:112
bool _suspendedReady
Definition: process.hh:181
std::unique_ptr<::sc_core::sc_report > _lastReport
Definition: process.hh:199
void syncResetOn(bool inc_kids)
Definition: process.cc:223
std::vector<::sc_core::sc_join * > joinWaiters
Definition: process.hh:201
void clearDynamic()
Definition: process.hh:110
void satisfySensitivity(Sensitivity *)
Definition: process.cc:332
::sc_core::sc_report * lastReport() const
Definition: process.cc:376
std::vector< Reset * > resets
Definition: process.hh:197
void timeout()
Definition: process.cc:318
void signalReset(bool set, bool sync)
Definition: process.cc:241
void waitCount(int count)
Definition: process.hh:138
StaticSensitivities staticSensitivities
Definition: process.hh:195
InternalScEvent _resetEvent
Definition: process.hh:160
bool suspended() const
Definition: process.hh:78
bool disabled() const
Definition: process.hh:79
void setTimeout(::sc_core::sc_time t)
Definition: process.cc:311
bool scheduled() const
Definition: process.hh:73
InternalScEvent _terminatedEvent
Definition: process.hh:161
ProcessFuncWrapper * func
Definition: process.hh:163
void terminate()
Definition: process.cc:395
void setDynamic(DynamicSensitivity *)
Definition: process.cc:288
void addStatic(StaticSensitivity *)
Definition: process.cc:282
Process(const char *name, ProcessFuncWrapper *func, bool internal=false)
Definition: process.cc:378
void reset(bool inc_kids)
Definition: process.cc:169
void throw_it(ExceptionWrapperBase &exc, bool inc_kids)
Definition: process.cc:198
ExceptionWrapperBase * excWrapper
Definition: process.hh:91
bool needsStart() const
Definition: process.hh:66
void syncResetOff(bool inc_kids)
Definition: process.cc:232
void injectException(ExceptionWrapperBase &exc)
Definition: process.cc:216
void enable(bool inc_kids)
Definition: process.cc:130
void resume(Process *p)
Definition: scheduler.cc:216
bool suspend(Process *p)
Definition: scheduler.cc:235
void deschedule(ScEvent *event)
Definition: scheduler.hh:280
void runNext(Process *p)
Definition: scheduler.hh:230
void schedule(ScEvent *event, const ::sc_core::sc_time &delay)
Definition: scheduler.hh:253
void ready(Process *p)
Definition: scheduler.cc:199
Process * current()
Definition: scheduler.hh:185
void runNow(Process *p)
Definition: scheduler.hh:213
virtual void clear()=0
static const size_t DefaultStackSize
Definition: fiber.hh:77
Bitfield< 12, 11 > set
Definition: misc_types.hh:709
Bitfield< 1 > s
Definition: pagetable.hh:64
Bitfield< 0 > v
Definition: pagetable.hh:65
Bitfield< 51 > t
Definition: pagetable.hh:56
Bitfield< 54 > p
Definition: pagetable.hh:70
@ Reset
Definition: types.hh:70
const char SC_ID_THROW_IT_IGNORED_[]
Definition: messages.cc:128
const char SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_[]
Definition: messages.cc:160
sc_status sc_get_status()
Definition: sc_main.cc:172
@ SC_RUNNING
Definition: sc_main.hh:87
@ SC_BEFORE_END_OF_ELABORATION
Definition: sc_main.hh:84
const char SC_ID_PROCESS_CONTROL_CORNER_CASE_[]
Definition: messages.cc:135
const char SC_ID_THROW_IT_WHILE_NOT_RUNNING_[]
Definition: messages.cc:163
const char SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_[]
Definition: messages.cc:158
bool sc_allow_process_control_corners
BuiltinExceptionWrapper< UnwindExceptionReset > resetException
Definition: process.cc:62
void newReset(const sc_core::sc_port_base *pb, Process *p, bool s, bool v)
Definition: process.cc:425
void throw_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
Definition: process.cc:419
Scheduler scheduler
Definition: scheduler.cc:494
BuiltinExceptionWrapper< UnwindExceptionKill > killException
Definition: process.cc:63
#define SC_REPORT_WARNING(msg_type, msg)
#define SC_REPORT_ERROR(msg_type, msg)
void popListNode()
Definition: list.hh:51
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:26 for gem5 by doxygen 1.9.1