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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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() { }
|
||||
};
|
||||
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user