ruby: Fix multiple wakeups in Ruby Eventqueue
Fix bug in Ruby Event queue to avoid multiple wakeups of same consumer in same cycle
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#define CONSUMER_H
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
#include "mem/ruby/common/Global.hh"
|
||||
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
|
||||
@@ -55,18 +56,43 @@ public:
|
||||
virtual ~Consumer() { }
|
||||
|
||||
// Public Methods - pure virtual methods
|
||||
// void triggerWakeup() { Time time = g_eventQueue_ptr->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }}
|
||||
void triggerWakeup(RubyEventQueue * eventQueue) { Time time = eventQueue->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }}
|
||||
void triggerWakeup(RubyEventQueue * eventQueue)
|
||||
{
|
||||
Time time = eventQueue->getTime();
|
||||
if (m_last_wakeup != time) {
|
||||
wakeup(); m_last_wakeup = time;
|
||||
}
|
||||
}
|
||||
virtual void wakeup() = 0;
|
||||
virtual void print(std::ostream& out) const = 0;
|
||||
const Time& getLastScheduledWakeup() const { return m_last_scheduled_wakeup; }
|
||||
void setLastScheduledWakeup(const Time& time) { m_last_scheduled_wakeup = time; }
|
||||
const Time& getLastScheduledWakeup() const
|
||||
{
|
||||
return m_last_scheduled_wakeup;
|
||||
}
|
||||
void setLastScheduledWakeup(const Time& time)
|
||||
{
|
||||
m_last_scheduled_wakeup = time;
|
||||
}
|
||||
bool alreadyScheduled(Time time)
|
||||
{
|
||||
return (m_scheduled_wakeups.find(time) != m_scheduled_wakeups.end());
|
||||
}
|
||||
void insertScheduledWakeupTime(Time time)
|
||||
{
|
||||
m_scheduled_wakeups.insert(time);
|
||||
}
|
||||
void removeScheduledWakeupTime(Time time)
|
||||
{
|
||||
assert(alreadyScheduled(time));
|
||||
m_scheduled_wakeups.erase(time);
|
||||
}
|
||||
|
||||
private:
|
||||
// Private Methods
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
Time m_last_scheduled_wakeup;
|
||||
std::set<Time> m_scheduled_wakeups;
|
||||
Time m_last_wakeup;
|
||||
};
|
||||
|
||||
|
||||
@@ -56,12 +56,12 @@ void RubyEventQueue::scheduleEventAbsolute(Consumer* consumer, Time timeAbs)
|
||||
{
|
||||
// Check to see if this is a redundant wakeup
|
||||
ASSERT(consumer != NULL);
|
||||
if (consumer->getLastScheduledWakeup() != timeAbs) {
|
||||
if (!consumer->alreadyScheduled(timeAbs)) {
|
||||
// This wakeup is not redundant
|
||||
RubyEventQueueNode *thisNode = new RubyEventQueueNode(consumer);
|
||||
RubyEventQueueNode *thisNode = new RubyEventQueueNode(consumer, this);
|
||||
assert(timeAbs > getTime());
|
||||
schedule(thisNode, (timeAbs * m_clock));
|
||||
consumer->setLastScheduledWakeup(timeAbs * m_clock);
|
||||
consumer->insertScheduledWakeupTime(timeAbs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
class RubyEventQueueNode : public Event {
|
||||
public:
|
||||
// Constructors
|
||||
RubyEventQueueNode(Consumer* _consumer)
|
||||
: m_consumer_ptr(_consumer)
|
||||
RubyEventQueueNode(Consumer* _consumer, RubyEventQueue* _eventq)
|
||||
: m_consumer_ptr(_consumer), m_eventq_ptr(_eventq)
|
||||
{
|
||||
setFlags(AutoDelete);
|
||||
}
|
||||
@@ -56,7 +56,11 @@ public:
|
||||
|
||||
// Public Methods
|
||||
void print(std::ostream& out) const;
|
||||
virtual void process() { m_consumer_ptr->wakeup(); }
|
||||
virtual void process()
|
||||
{
|
||||
m_consumer_ptr->wakeup();
|
||||
m_consumer_ptr->removeScheduledWakeupTime(m_eventq_ptr->getTime());
|
||||
}
|
||||
virtual const char *description() const { return "Ruby Event"; }
|
||||
|
||||
private:
|
||||
@@ -67,6 +71,7 @@ private:
|
||||
|
||||
// Data Members (m_ prefix)
|
||||
Consumer* m_consumer_ptr;
|
||||
RubyEventQueue* m_eventq_ptr;
|
||||
};
|
||||
|
||||
// Output operator declaration
|
||||
|
||||
Reference in New Issue
Block a user