Gabe Black has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/12456
Change subject: systemc: Store timed notifications in a list instead of a
set.
......................................................................
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
---
M src/systemc/core/sched_event.hh
M src/systemc/core/scheduler.cc
M src/systemc/core/scheduler.hh
3 files changed, 42 insertions(+), 31 deletions(-)
diff --git a/src/systemc/core/sched_event.hh
b/src/systemc/core/sched_event.hh
index 9aefb74..ca55215 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 e340f4d..c74d5cf 100644
--- a/src/systemc/core/scheduler.cc
+++ b/src/systemc/core/scheduler.cc
@@ -61,15 +61,14 @@
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 @@
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);
@@ -280,9 +278,8 @@
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 2bac934..7f28035 100644
--- a/src/systemc/core/scheduler.hh
+++ b/src/systemc/core/scheduler.hh
@@ -145,7 +145,7 @@
class Scheduler
{
public:
- typedef std::set<ScEvent *> ScEvents;
+ typedef std::list<ScEvent *> ScEvents;
class TimeSlot : public ::Event
{
@@ -226,11 +226,9 @@
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 @@
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 @@
"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.
@@ -416,8 +413,8 @@
inline void
Scheduler::TimeSlot::process()
{
- for (auto &e: events)
- e->run();
+ while (!events.empty())
+ events.front()->run();
scheduler.completeTimeSlot(this);
}
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/12456
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: Icad51a63f153297c88e65f85d22ac721e6c571d8
Gerrit-Change-Number: 12456
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev