From 888ec455cba4174863be5ed9148aaf093a061101 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Tue, 7 Jul 2015 09:51:04 +0100 Subject: [PATCH] sim: Fix broken event unserialization 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 | 8 +++----- src/sim/eventq.cc | 39 +++++++++++++++++++++++---------------- src/sim/eventq.hh | 19 +++++++++++++------ src/sim/serialize.hh | 9 +++++++++ src/sim/sim_events.cc | 10 ---------- src/sim/sim_events.hh | 2 -- 6 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/dev/etherlink.cc b/src/dev/etherlink.cc index 27179d508..7b24fe9f7 100644 --- a/src/dev/etherlink.cc +++ b/src/dev/etherlink.cc @@ -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 §ion); }; @@ -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; diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index f75ada47c..48664f8e8 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -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(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 { diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index b90e5d382..cfb79614f 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -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() { } }; diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index 644ef4005..a0d4bafe7 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -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) \ diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 719a732ab..94bd06191 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -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 §ion) diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 8d5d5da7b..7c2393010 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -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 §ion); }; -- 2.30.2