systemc: Handle exceptions "correctly" even if sc_main hasn't been run.
authorGabe Black <gabeblack@google.com>
Thu, 14 Feb 2019 06:30:02 +0000 (22:30 -0800)
committerGabe Black <gabeblack@google.com>
Thu, 21 Feb 2019 22:34:15 +0000 (22:34 +0000)
If sc_main hasn't run, for instance if there isn't an sc_main and gem5
is orchestrating the simulation directly, then exceptions shouldn't be
thrown to the sc_main fiber since it isn't running and may not be able
to run since sc_main may not even exist.

Instead, we need to check whether it makes sense to throw to sc_main,
and if not pass the exception directly to the report handler since
there likely won't be anyone to catch it if we just throw it from the
scheduler or into general purpose gem5.

Since the name throwToScMain is no longer a complete description for
what that function does, this change renames it to throwUp, since it
will now throw exceptions up the stack, either to sc_main or to the
conceptual top level by going directly to the report handler.

Change-Id: Ibdc92c9cf213ec6aa15ad654862057b7bf2e1c8e
Reviewed-on: https://gem5-review.googlesource.com/c/16442
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/core/kernel.cc
src/systemc/core/process_types.hh
src/systemc/core/scheduler.cc
src/systemc/core/scheduler.hh

index 2fd3027da8f34b25caa1695da02c559f09f2481c..13e69d1f4b086f9668df4d952f50e80f35765619 100644 (file)
@@ -103,7 +103,7 @@ Kernel::regStats()
         for (auto c: sc_gem5::allChannels)
             c->sc_chan()->end_of_elaboration();
     } catch (...) {
-        ::sc_gem5::scheduler.throwToScMain();
+        ::sc_gem5::scheduler.throwUp();
     }
 }
 
@@ -127,7 +127,7 @@ Kernel::startup()
         for (auto c: sc_gem5::allChannels)
             c->sc_chan()->start_of_simulation();
     } catch (...) {
-        ::sc_gem5::scheduler.throwToScMain();
+        ::sc_gem5::scheduler.throwUp();
     }
 
     startComplete = true;
@@ -159,7 +159,7 @@ Kernel::stopWork()
         for (auto c: sc_gem5::allChannels)
             c->sc_chan()->end_of_simulation();
     } catch (...) {
-        ::sc_gem5::scheduler.throwToScMain();
+        ::sc_gem5::scheduler.throwUp();
     }
 
     endComplete = true;
index 1361e9745bca04645b6c248d0a5433fab38bfc53..c14ec1f4fdbd26a0a227eeaf9985d797b5771f11 100644 (file)
@@ -94,7 +94,7 @@ class Thread : public Process
                 thread->run();
             } catch (...) {
                 thread->terminate();
-                scheduler.throwToScMain();
+                scheduler.throwUp();
                 return;
             }
             thread->terminate();
index 465da552f6b6be6666812252fda41867ca443265..4b566ca2077c2bfb243459d510b52900573dcb0c 100644 (file)
@@ -47,7 +47,7 @@ namespace sc_gem5
 Scheduler::Scheduler() :
     eq(nullptr), readyEvent(this, false, ReadyPriority),
     pauseEvent(this, false, PausePriority),
-    stopEvent(this, false, StopPriority), _throwToScMain(nullptr),
+    stopEvent(this, false, StopPriority), _throwUp(nullptr),
     starvationEvent(this, false, StarvationPriority),
     _elaborationDone(false), _started(false), _stopNow(false),
     _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
@@ -180,7 +180,7 @@ Scheduler::yield()
             try {
                 _current->run();
             } catch (...) {
-                throwToScMain();
+                throwUp();
             }
         }
     }
@@ -327,7 +327,7 @@ Scheduler::runUpdate()
             channel = updateList.getNext();
         }
     } catch (...) {
-        throwToScMain();
+        throwUp();
     }
 }
 
@@ -340,7 +340,7 @@ Scheduler::runDelta()
         while (!deltas.empty())
             deltas.back()->run();
     } catch (...) {
-        throwToScMain();
+        throwUp();
     }
 }
 
@@ -398,9 +398,9 @@ Scheduler::start(Tick max_tick, bool run_to_time)
     if (starvationEvent.scheduled())
         deschedule(&starvationEvent);
 
-    if (_throwToScMain) {
-        const ::sc_core::sc_report *to_throw = _throwToScMain;
-        _throwToScMain = nullptr;
+    if (_throwUp) {
+        const ::sc_core::sc_report *to_throw = _throwUp;
+        _throwUp = nullptr;
         throw *to_throw;
     }
 }
@@ -423,12 +423,17 @@ Scheduler::schedulePause()
 }
 
 void
-Scheduler::throwToScMain()
+Scheduler::throwUp()
 {
-    ::sc_core::sc_report report = reportifyException();
-    _throwToScMain = &report;
-    status(StatusOther);
-    scMainFiber.run();
+    if (scMainFiber.called() && !scMainFiber.finished()) {
+        ::sc_core::sc_report report = reportifyException();
+        _throwUp = &report;
+        status(StatusOther);
+        scMainFiber.run();
+    } else {
+        reportHandlerProc(reportifyException(),
+                ::sc_core::sc_report_handler::get_catch_actions());
+    }
 }
 
 void
index 64841086d72cfcc65b236423f932a70b2a345bae..63f6ac35d97b402465e7dc9ba263523efbfca47b 100644 (file)
@@ -363,7 +363,9 @@ class Scheduler
     uint64_t changeStamp() { return _changeStamp; }
     void stepChangeStamp() { _changeStamp++; }
 
-    void throwToScMain();
+    // Throw upwards, either to sc_main or to the report handler if sc_main
+    // isn't running.
+    void throwUp();
 
     Status status() { return _status; }
     void status(Status s) { _status = s; }
@@ -424,7 +426,7 @@ class Scheduler
     EventWrapper<Scheduler, &Scheduler::pause> pauseEvent;
     EventWrapper<Scheduler, &Scheduler::stop> stopEvent;
 
-    const ::sc_core::sc_report *_throwToScMain;
+    const ::sc_core::sc_report *_throwUp;
 
     bool
     starved()
@@ -505,7 +507,7 @@ Scheduler::TimeSlot::process()
             scheduler.completeTimeSlot(this);
         else
             scheduler.schedule(this);
-        scheduler.throwToScMain();
+        scheduler.throwUp();
     }
 
     scheduler.status(StatusOther);