sim: Ensure draining is deterministic
The traversal of drainable objects could potentially be non-deterministic when using an unordered set containing object pointers. To ensure that the iteration is deterministic, we switch to a vector. Note that the lookup and traversal of the drainable objects is not performance critical, so the change has no negative consequences.
This commit is contained in:
parent
912b20d02a
commit
184c6d7ebd
4 changed files with 15 additions and 4 deletions
2
src/mem/cache/cache.hh
vendored
2
src/mem/cache/cache.hh
vendored
|
@ -52,6 +52,8 @@
|
||||||
#ifndef __MEM_CACHE_CACHE_HH__
|
#ifndef __MEM_CACHE_CACHE_HH__
|
||||||
#define __MEM_CACHE_CACHE_HH__
|
#define __MEM_CACHE_CACHE_HH__
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "base/misc.hh" // fatal, panic, and warn
|
#include "base/misc.hh" // fatal, panic, and warn
|
||||||
#include "enums/Clusivity.hh"
|
#include "enums/Clusivity.hh"
|
||||||
#include "mem/cache/base.hh"
|
#include "mem/cache/base.hh"
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#ifndef __MEM_COHERENT_XBAR_HH__
|
#ifndef __MEM_COHERENT_XBAR_HH__
|
||||||
#define __MEM_COHERENT_XBAR_HH__
|
#define __MEM_COHERENT_XBAR_HH__
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "mem/snoop_filter.hh"
|
#include "mem/snoop_filter.hh"
|
||||||
#include "mem/xbar.hh"
|
#include "mem/xbar.hh"
|
||||||
#include "params/CoherentXBar.hh"
|
#include "params/CoherentXBar.hh"
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
|
|
||||||
#include "sim/drain.hh"
|
#include "sim/drain.hh"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "debug/Drain.hh"
|
#include "debug/Drain.hh"
|
||||||
|
@ -126,6 +128,7 @@ DrainManager::preCheckpointRestore()
|
||||||
void
|
void
|
||||||
DrainManager::signalDrainDone()
|
DrainManager::signalDrainDone()
|
||||||
{
|
{
|
||||||
|
assert(_count > 0);
|
||||||
if (--_count == 0) {
|
if (--_count == 0) {
|
||||||
DPRINTF(Drain, "All %u objects drained..\n", drainableCount());
|
DPRINTF(Drain, "All %u objects drained..\n", drainableCount());
|
||||||
exitSimLoop("Finished drain", 0);
|
exitSimLoop("Finished drain", 0);
|
||||||
|
@ -137,14 +140,18 @@ void
|
||||||
DrainManager::registerDrainable(Drainable *obj)
|
DrainManager::registerDrainable(Drainable *obj)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(globalLock);
|
std::lock_guard<std::mutex> lock(globalLock);
|
||||||
_allDrainable.insert(obj);
|
assert(std::find(_allDrainable.begin(), _allDrainable.end(), obj) ==
|
||||||
|
_allDrainable.end());
|
||||||
|
_allDrainable.push_back(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrainManager::unregisterDrainable(Drainable *obj)
|
DrainManager::unregisterDrainable(Drainable *obj)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(globalLock);
|
std::lock_guard<std::mutex> lock(globalLock);
|
||||||
_allDrainable.erase(obj);
|
auto o = std::find(_allDrainable.begin(), _allDrainable.end(), obj);
|
||||||
|
assert(o != _allDrainable.end());
|
||||||
|
_allDrainable.erase(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <unordered_set>
|
#include <vector>
|
||||||
|
|
||||||
class Drainable;
|
class Drainable;
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class DrainManager
|
||||||
mutable std::mutex globalLock;
|
mutable std::mutex globalLock;
|
||||||
|
|
||||||
/** Set of all drainable objects */
|
/** Set of all drainable objects */
|
||||||
std::unordered_set<Drainable *> _allDrainable;
|
std::vector<Drainable *> _allDrainable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of objects still draining. This is flagged atomic since
|
* Number of objects still draining. This is flagged atomic since
|
||||||
|
|
Loading…
Reference in a new issue