sim: Ensure draining is deterministic
authorAndreas Hansson <andreas.hansson@arm.com>
Sun, 19 Feb 2017 10:30:31 +0000 (05:30 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Sun, 19 Feb 2017 10:30:31 +0000 (05:30 -0500)
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.

src/mem/cache/cache.hh
src/mem/coherent_xbar.hh
src/sim/drain.cc
src/sim/drain.hh

index 4f9142f7c286af72a311a0469669cc634aad1891..7f9130d620e8655bd32847e256452475490a01c7 100644 (file)
@@ -52,6 +52,8 @@
 #ifndef __MEM_CACHE_CACHE_HH__
 #define __MEM_CACHE_CACHE_HH__
 
+#include <unordered_set>
+
 #include "base/misc.hh" // fatal, panic, and warn
 #include "enums/Clusivity.hh"
 #include "mem/cache/base.hh"
index 0f641664d299eb859579bb1ccc96c30157808ae9..edfc47d4bd9b5805f2c5295079e61333a8c55920 100644 (file)
@@ -51,6 +51,8 @@
 #ifndef __MEM_COHERENT_XBAR_HH__
 #define __MEM_COHERENT_XBAR_HH__
 
+#include <unordered_set>
+
 #include "mem/snoop_filter.hh"
 #include "mem/xbar.hh"
 #include "params/CoherentXBar.hh"
index 085f781dc27f25ac3a12771c0a4b22661650271b..bb8abd735151a0fadf8a0ef70e0b98e584cf88eb 100644 (file)
@@ -39,6 +39,8 @@
 
 #include "sim/drain.hh"
 
+#include <algorithm>
+
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "debug/Drain.hh"
@@ -126,6 +128,7 @@ DrainManager::preCheckpointRestore()
 void
 DrainManager::signalDrainDone()
 {
+    assert(_count > 0);
     if (--_count == 0) {
         DPRINTF(Drain, "All %u objects drained..\n", drainableCount());
         exitSimLoop("Finished drain", 0);
@@ -137,14 +140,18 @@ void
 DrainManager::registerDrainable(Drainable *obj)
 {
     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
 DrainManager::unregisterDrainable(Drainable *obj)
 {
     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
index b3145e7ed6022536acd4185af1459068ae20ec85..663946616b5854731c2b5bf143690a26fc717b95 100644 (file)
@@ -42,7 +42,7 @@
 
 #include <atomic>
 #include <mutex>
-#include <unordered_set>
+#include <vector>
 
 class Drainable;
 
@@ -162,7 +162,7 @@ class DrainManager
     mutable std::mutex globalLock;
 
     /** Set of all drainable objects */
-    std::unordered_set<Drainable *> _allDrainable;
+    std::vector<Drainable *> _allDrainable;
 
     /**
      * Number of objects still draining. This is flagged atomic since