sim: Fix broken event unserialization
authorAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 7 Jul 2015 08:51:04 +0000 (09:51 +0100)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 7 Jul 2015 08:51:04 +0000 (09:51 +0100)
Events expected to be unserialized using an event-specific
unserializeEvent call. This call was never actually used, which meant
the events relying on it never got unserialized (or scheduled after
unserialization).

Instead of relying on a custom call, we now use the normal
serialization code again. In order to schedule the event correctly,
the parrent object is expected to use the
EventQueue::checkpointReschedule() call. This happens automatically
for events that are serialized using the AutoSerialize mechanism.

src/dev/etherlink.cc
src/sim/eventq.cc
src/sim/eventq.hh
src/sim/serialize.hh
src/sim/sim_events.cc
src/sim/sim_events.hh

index 27179d508a0afe1a00e723b090a343b053873154..7b24fe9f7173d8d2a22213e244cf9f8cde1995bb 100644 (file)
@@ -142,9 +142,7 @@ class LinkDelayEvent : public Event
     void process();
 
     void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
-    void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE {}
-    void unserializeEvent(CheckpointIn &cp,
-                          EventQueue *eventq) M5_ATTR_OVERRIDE;
+    void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
     static Serializable *createForUnserialize(CheckpointIn &cp,
                                               const string &section);
 };
@@ -260,9 +258,9 @@ LinkDelayEvent::serialize(CheckpointOut &cp) const
 
 
 void
-LinkDelayEvent::unserializeEvent(CheckpointIn &cp, EventQueue *eventq)
+LinkDelayEvent::unserialize(CheckpointIn &cp)
 {
-    Event::unserializeEvent(cp, eventq);
+    Event::unserialize(cp);
 
     EtherLink *parent;
     bool number;
index f75ada47cdbb9cbad73ecda441a404cfa15193f1..48664f8e8f06bf4bebbfdf0f766402c2743fb028 100644 (file)
@@ -41,7 +41,7 @@
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "cpu/smt.hh"
-#include "debug/Config.hh"
+#include "debug/Checkpoint.hh"
 #include "sim/core.hh"
 #include "sim/eventq_impl.hh"
 
@@ -253,18 +253,12 @@ Event::serialize(CheckpointOut &cp) const
 void
 Event::unserialize(CheckpointIn &cp)
 {
-}
-
-void
-Event::unserializeEvent(CheckpointIn &cp, EventQueue *eventq)
-{
-    if (scheduled())
-        eventq->deschedule(this);
+    assert(!scheduled());
 
     UNSERIALIZE_SCALAR(_when);
     UNSERIALIZE_SCALAR(_priority);
 
-    short _flags;
+    FlagsType _flags;
     UNSERIALIZE_SCALAR(_flags);
 
     // Old checkpoints had no concept of the Initialized flag
@@ -280,12 +274,11 @@ Event::unserializeEvent(CheckpointIn &cp, EventQueue *eventq)
     // need to see if original event was in a scheduled, unsquashed
     // state, but don't want to restore those flags in the current
     // object itself (since they aren't immediately true)
-    bool wasScheduled = flags.isSet(Scheduled) && !flags.isSet(Squashed);
-    flags.clear(Squashed | Scheduled);
-
-    if (wasScheduled) {
-        DPRINTF(Config, "rescheduling at %d\n", _when);
-        eventq->schedule(this, _when);
+    if (flags.isSet(Scheduled) && !flags.isSet(Squashed)) {
+        flags.clear(Squashed | Scheduled);
+    } else {
+        DPRINTF(Checkpoint, "Event '%s' need to be scheduled @%d\n",
+                name(), _when);
     }
 }
 
@@ -329,10 +322,24 @@ EventQueue::unserialize(CheckpointIn &cp)
         paramIn(cp, csprintf("event%d", i), eventName);
 
         // create the event based on its pointer value
-        Serializable::create(cp, eventName);
+        Serializable *obj(Serializable::create(cp, eventName));
+        Event *event(dynamic_cast<Event *>(obj));
+        fatal_if(!event,
+                 "Event queue unserialized something that wasn't an event.\n");
+
+        checkpointReschedule(event);
     }
 }
 
+void
+EventQueue::checkpointReschedule(Event *event)
+{
+    // It's safe to call insert() directly here since this method
+    // should only be called when restoring from a checkpoint (which
+    // happens before thread creation).
+    if (event->flags.isSet(Event::Scheduled))
+        insert(event);
+}
 void
 EventQueue::dump() const
 {
index b90e5d3827a68c056cf16e8a54dcea1f60aa91d8..cfb79614faaa8023fe70b432606d454650e8a5b0 100644 (file)
@@ -352,12 +352,6 @@ class Event : public EventBase, public Serializable
 #ifndef SWIG
     void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
     void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
-
-    //! This function is required to support restoring from checkpoints
-    //! when running with multiple queues. Since we still have not thrashed
-    //! out all the details on checkpointing, this function is most likely
-    //! to be revisited in future.
-    virtual void unserializeEvent(CheckpointIn &cp, EventQueue *eventq);
 #endif
 };
 
@@ -650,6 +644,19 @@ class EventQueue : public Serializable
     void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
 #endif
 
+    /**
+     * Reschedule an event after a checkpoint.
+     *
+     * Since events don't know which event queue they belong to,
+     * parent objects need to reschedule events themselves. This
+     * method conditionally schedules an event that has the Scheduled
+     * flag set. It should be called by parent objects after
+     * unserializing an object.
+     *
+     * @warn Only use this method after unserializing an Event.
+     */
+    void checkpointReschedule(Event *event);
+
     virtual ~EventQueue() { }
 };
 
index 644ef400583f5b9816c9885a4bf8cc5ffb369796..a0d4bafe7490eaf6155b3ef1d1ceb498a059187a 100644 (file)
@@ -178,6 +178,15 @@ void fromSimObject(T &t, SimObject *s)
 #define UNSERIALIZE_CONTAINER(member)           \
         arrayParamIn(cp, #member, member)
 
+#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event);
+
+#define UNSERIALIZE_EVENT(event)                        \
+    do {                                                \
+        event.unserializeSection(cp, #event);           \
+        eventQueue()->checkpointReschedule(&event);     \
+    } while(0)
+
+
 #define SERIALIZE_OBJPTR(objptr)        paramOut(cp, #objptr, (objptr)->name())
 
 #define UNSERIALIZE_OBJPTR(objptr)                      \
index 719a732ab4c430b3bc5141c53a2748357868ce15..94bd06191dd4eff1a871ff375423e472a0fe854d 100644 (file)
@@ -137,16 +137,6 @@ LocalSimLoopExitEvent::unserialize(CheckpointIn &cp)
     UNSERIALIZE_SCALAR(repeat);
 }
 
-void
-LocalSimLoopExitEvent::unserializeEvent(CheckpointIn &cp, EventQueue *eventq)
-{
-    Event::unserializeEvent(cp, eventq);
-
-    UNSERIALIZE_SCALAR(cause);
-    UNSERIALIZE_SCALAR(code);
-    UNSERIALIZE_SCALAR(repeat);
-}
-
 Serializable *
 LocalSimLoopExitEvent::createForUnserialize(CheckpointIn &cp,
                                             const string &section)
index 8d5d5da7b5bb40ce3f9cc7da91827db41d077f21..7c239301023d2f0cb153058fdc8e84f7c0d65af0 100644 (file)
@@ -95,8 +95,6 @@ class LocalSimLoopExitEvent : public Event
 
     void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
     void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
-    void unserializeEvent(CheckpointIn &cp,
-                          EventQueue *eventq) M5_ATTR_OVERRIDE;
     static Serializable *createForUnserialize(CheckpointIn &cp,
                                               const std::string &section);
 };