ruby: Fix multiple wakeups in Ruby Eventqueue
authorTushar Krishna <tushar@csail.mit.edu>
Mon, 22 Mar 2010 04:22:21 +0000 (21:22 -0700)
committerTushar Krishna <tushar@csail.mit.edu>
Mon, 22 Mar 2010 04:22:21 +0000 (21:22 -0700)
Fix bug in Ruby Event queue to avoid multiple wakeups of same consumer in
same cycle

src/mem/ruby/common/Consumer.hh
src/mem/ruby/eventqueue/RubyEventQueue.cc
src/mem/ruby/eventqueue/RubyEventQueueNode.hh

index 955c1ffa93c3e0ac6c81e1fb2931e328c49f9125..e541ef615f599c424fb933c861306da0a6583c70 100644 (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;
 };
 
index c497f239a003a3da6532ddb8e910f7c12a3ff635..3cfb52ff117fa4d64efa84ed7b4c618cccc4d291 100644 (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);
   }
 }
 
index dc2fc92e7d7c67946791e743c05df3c5dc6df4e3..46d8b317c95dc7eae96bf86b3157d72a0f950057 100644 (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