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:
Tushar Krishna
2010-03-21 21:22:21 -07:00
parent 103f5a2c94
commit 7c20d5511a
3 changed files with 41 additions and 10 deletions

View File

@@ -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;
};

View File

@@ -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);
}
}

View File

@@ -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