summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-08-31 16:18:10 -0700
committerGabe Black <gabeblack@google.com>2018-10-03 00:28:55 +0000
commite99a575c78735ad9e35e30ee8714d5e2798e3014 (patch)
tree984e45897e33ab064d730550d7163be06403fcf0
parent3c40f3c0c420dc4215c97a646359f7cda5de829e (diff)
downloadgem5-e99a575c78735ad9e35e30ee8714d5e2798e3014.tar.xz
systemc: Store timed notifications in a list instead of a set.
This has three advantages. First, the data structure doesn't have to try to keep track of whether or not an event is already listed there. Second, it's easier to delete an item by storing an iterator for it when it gets inserted. Third, the ordering of events is not dependent on the arbitrary ordering of the set, it's bsaed on the fixed order the events get added to the list. One part of this change makes ScEvent-s keep track of what list they're on, and handle their own insertion and deletion when they're scheduled or descheduled. A side effect of that is that it's no longer safe to simply use a range based for loop to loop over all of an ScEvent and deschedule all its events or to run then (which deschedules them internally once they execute). That can be avoided by looping until the list is empty, and operating on the first element. As the first element is processed and removed from the list, the next element will become first and will get picked up in the next iteration. Change-Id: Icad51a63f153297c88e65f85d22ac721e6c571d8 Reviewed-on: https://gem5-review.googlesource.com/c/12456 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
-rw-r--r--src/systemc/core/sched_event.hh29
-rw-r--r--src/systemc/core/scheduler.cc19
-rw-r--r--src/systemc/core/scheduler.hh25
3 files changed, 42 insertions, 31 deletions
diff --git a/src/systemc/core/sched_event.hh b/src/systemc/core/sched_event.hh
index 9aefb7440..ca5521574 100644
--- a/src/systemc/core/sched_event.hh
+++ b/src/systemc/core/sched_event.hh
@@ -31,37 +31,54 @@
#define __SYSTEMC_CORE_SCHED_EVENT_HH__
#include <functional>
+#include <list>
#include "base/types.hh"
namespace sc_gem5
{
+class ScEvent;
+
+typedef std::list<ScEvent *> ScEvents;
+
class ScEvent
{
private:
std::function<void()> work;
Tick _when;
- bool _scheduled;
+ ScEvents *_events;
+ ScEvents::iterator _it;
friend class Scheduler;
void
- schedule(Tick w)
+ schedule(ScEvents &events, Tick w)
{
when(w);
- _scheduled = true;
+ assert(!scheduled());
+ _events = &events;
+ _events->push_back(this);
+ _it = _events->end();
+ _it--;
}
- void deschedule() { _scheduled = false; }
+ void
+ deschedule()
+ {
+ assert(scheduled());
+ _events->erase(_it);
+ _events = nullptr;
+ }
public:
ScEvent(std::function<void()> work) :
- work(work), _when(MaxTick), _scheduled(false)
+ work(work), _when(MaxTick), _events(nullptr)
{}
~ScEvent();
- bool scheduled() { return _scheduled; }
+ bool scheduled() { return _events != nullptr; }
+ ScEvents *scheduledOn() { return _events; }
void when(Tick w) { _when = w; }
Tick when() { return _when; }
diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc
index e2d8e62f4..d5081c667 100644
--- a/src/systemc/core/scheduler.cc
+++ b/src/systemc/core/scheduler.cc
@@ -61,15 +61,14 @@ void
Scheduler::clear()
{
// Delta notifications.
- for (auto &e: deltas)
- e->deschedule();
- deltas.clear();
+ while (!deltas.empty())
+ deltas.front()->deschedule();
// Timed notifications.
for (auto &tsp: timeSlots) {
TimeSlot *&ts = tsp.second;
- for (auto &e: ts->events)
- e->deschedule();
+ while (!ts->events.empty())
+ ts->events.front()->deschedule();
deschedule(ts);
}
timeSlots.clear();
@@ -115,9 +114,8 @@ Scheduler::initPhase()
update();
- for (auto &e: deltas)
- e->run();
- deltas.clear();
+ while (!deltas.empty())
+ deltas.front()->run();
for (auto ets: eventsToSchedule)
eq->schedule(ets.first, ets.second);
@@ -281,9 +279,8 @@ Scheduler::runReady()
update();
// The delta phase.
- for (auto &e: deltas)
- e->run();
- deltas.clear();
+ while (!deltas.empty())
+ deltas.front()->run();
if (!runToTime && starved())
scheduleStarvationEvent();
diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh
index 2bee0b090..924cfb29e 100644
--- a/src/systemc/core/scheduler.hh
+++ b/src/systemc/core/scheduler.hh
@@ -145,7 +145,7 @@ typedef NodeList<Channel> ChannelList;
class Scheduler
{
public:
- typedef std::set<ScEvent *> ScEvents;
+ typedef std::list<ScEvent *> ScEvents;
class TimeSlot : public ::Event
{
@@ -226,11 +226,9 @@ class Scheduler
if (tick < getCurTick())
tick = getCurTick();
- event->schedule(tick);
-
// Delta notification/timeout.
if (delay.value() == 0) {
- deltas.insert(event);
+ event->schedule(deltas, tick);
scheduleReadyEvent();
return;
}
@@ -241,19 +239,18 @@ class Scheduler
ts = new TimeSlot;
schedule(ts, tick);
}
- ts->events.insert(event);
+ event->schedule(ts->events, tick);
}
// For descheduling delayed/timed notifications/timeouts.
void
deschedule(ScEvent *event)
{
- if (event->when() == getCurTick()) {
- // Attempt to remove from delta notifications.
- if (deltas.erase(event) == 1) {
- event->deschedule();
- return;
- }
+ ScEvents *on = event->scheduledOn();
+
+ if (on == &deltas) {
+ event->deschedule();
+ return;
}
// Timed notification/timeout.
@@ -262,7 +259,7 @@ class Scheduler
"Descheduling event at time with no events.");
TimeSlot *ts = tsit->second;
ScEvents &events = ts->events;
- assert(events.erase(event));
+ assert(on == &events);
event->deschedule();
// If no more events are happening at this time slot, get rid of it.
@@ -424,8 +421,8 @@ extern Scheduler scheduler;
inline void
Scheduler::TimeSlot::process()
{
- for (auto &e: events)
- e->run();
+ while (!events.empty())
+ events.front()->run();
scheduler.completeTimeSlot(this);
}