sim: tag-based checkpoint versioning

This commit addresses gem5 checkpoints' linear versioning bottleneck.
Since development is distributed across many private trees, there exists
a sort of 'race' for checkpoint version numbers: internally a checkpoint
version may be used but then resynchronizing with the external tree causes
a conflict on that version.  This change replaces the linear version number
with a set of unique strings called tags.  Now the only conflicts that can
arise are of tag names, where collisions are much easier to avoid.

The checkpoint upgrader (util/cpt_upgrader.py) upgrades the version
representation, as one would expect. Each tag version implements its
upgrader code in a python file in the util/cpt_upgraders directory
rather than adding a function to the upgrader script itself.

The version tags are stored in the 'Globals' section rather than 'root'
(as the version was previously) because 'Globals' gets unserialized
first and can provide a warning before any other unserialization errors
can occur.
This commit is contained in:
Curtis Dunham
2015-09-02 15:23:30 -05:00
parent 62e0344aef
commit 87b9da2df4
20 changed files with 773 additions and 664 deletions

View File

@@ -916,6 +916,11 @@ env.Command('debug/flags.cc', Value(debug_flags),
env.Depends(SWIG, 'debug/flags.cc')
Source('debug/flags.cc')
# version tags
env.Command('sim/tags.cc', None,
MakeAction('util/cpt_upgrader.py --get-cc-file > $TARGET',
Transform("VER TAGS")))
# Embed python files. All .py files that have been indicated by a
# PySource() call in a SConscript need to be embedded into the M5
# library. To do that, we compile the file to byte code, marshal the

View File

@@ -42,6 +42,7 @@ SimObject('SubSystem.py')
Source('arguments.cc')
Source('async.cc')
Source('core.cc')
Source('tags.cc')
Source('cxx_config.cc')
Source('cxx_manager.cc')
Source('cxx_config_ini.cc')

View File

@@ -132,8 +132,6 @@ Root::loadState(CheckpointIn &cp)
void
Root::serialize(CheckpointOut &cp) const
{
uint64_t cpt_ver = gem5CheckpointVersion;
SERIALIZE_SCALAR(cpt_ver);
SERIALIZE_SCALAR(FullSystem);
std::string isa = THE_ISA_STR;
SERIALIZE_SCALAR(isa);
@@ -141,27 +139,7 @@ Root::serialize(CheckpointOut &cp) const
void
Root::unserialize(CheckpointIn &cp)
{
uint64_t cpt_ver = 0;
UNSERIALIZE_OPT_SCALAR(cpt_ver);
if (cpt_ver < gem5CheckpointVersion) {
warn("**********************************************************\n");
warn("!!!! Checkpoint ver %#x is older than current ver %#x !!!!\n",
cpt_ver, gem5CheckpointVersion);
warn("You might experience some issues when restoring and should run "
"the checkpoint upgrader (util/cpt_upgrader.py) on your "
"checkpoint\n");
warn("**********************************************************\n");
} else if (cpt_ver > gem5CheckpointVersion) {
warn("**********************************************************\n");
warn("!!!! Checkpoint ver %#x is newer than current ver %#x !!!!\n",
cpt_ver, gem5CheckpointVersion);
warn("Running a new checkpoint with an older version of gem5 is not "
"supported. While it might work, you may experience incorrect "
"behavior or crashes.\n");
warn("**********************************************************\n");
}
}
{}
bool FullSystem;

View File

@@ -496,16 +496,73 @@ class Globals : public Serializable
/// The one and only instance of the Globals class.
Globals globals;
/// The version tags for this build of the simulator, to be stored in the
/// Globals section during serialization and compared upon unserialization.
extern std::set<std::string> version_tags;
void
Globals::serialize(CheckpointOut &cp) const
{
paramOut(cp, "curTick", curTick());
SERIALIZE_CONTAINER(version_tags);
}
void
Globals::unserialize(CheckpointIn &cp)
{
paramIn(cp, "curTick", unserializedCurTick);
const std::string &section(Serializable::currentSection());
std::string str;
if (!cp.find(section, "version_tags", str)) {
warn("**********************************************************\n");
warn("!!!! Checkpoint uses an old versioning scheme. !!!!\n");
warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your "
"checkpoint\n");
warn("**********************************************************\n");
return;
}
std::set<std::string> cpt_tags;
arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER
bool err = false;
for (const auto& t : version_tags) {
if (cpt_tags.find(t) == cpt_tags.end()) {
// checkpoint is missing tag that this binary has
if (!err) {
warn("*****************************************************\n");
warn("!!!! Checkpoint is missing the following version tags:\n");
err = true;
}
warn(" %s\n", t);
}
}
if (err) {
warn("You might experience some issues when restoring and should run "
"the checkpoint upgrader (util/cpt_upgrader.py) on your "
"checkpoint\n");
warn("**********************************************************\n");
}
err = false;
for (const auto& t : cpt_tags) {
if (version_tags.find(t) == version_tags.end()) {
// gem5 binary is missing tag that this checkpoint has
if (!err) {
warn("*****************************************************\n");
warn("!!!! gem5 is missing the following version tags:\n");
err = true;
}
warn(" %s\n", t);
}
}
if (err) {
warn("Running a checkpoint with incompatible version tags is not "
"supported. While it might work, you may experience incorrect "
"behavior or crashes.\n");
warn("**********************************************************\n");
}
}
Serializable::Serializable()

View File

@@ -71,15 +71,6 @@ class EventQueue;
typedef std::ostream CheckpointOut;
/** The current version of the checkpoint format.
* This should be incremented by 1 and only 1 for every new version, where a new
* version is defined as a checkpoint created before this version won't work on
* the current version until the checkpoint format is updated. Adding a new
* SimObject shouldn't cause the version number to increase, only changes to
* existing objects such as serializing/unserializing more state, changing sizes
* of serialized arrays, etc. */
static const uint64_t gem5CheckpointVersion = 0x000000000000000f;
template <class T>
void paramOut(CheckpointOut &cp, const std::string &name, const T &param);