sim: Add support for forking
authorAndreas Sandberg <andreas@sandberg.pp.se>
Thu, 26 Nov 2015 10:11:57 +0000 (10:11 +0000)
committerAndreas Sandberg <andreas@sandberg.pp.se>
Thu, 26 Nov 2015 10:11:57 +0000 (10:11 +0000)
This changeset adds forking capabilities to the gem5 python scripts. A fork
method is added to simulate.py. This method is responsible for forking the
simulator itself, and will direct all output files to a new output directory
based on the fork sequence number. The default name of the output directory is
the same as the parent with the suffix ".fN" added where N is the fork sequence
number. The fork method provides the option to specify if the system should be
drained prior to forking, or not. By default the system is drained to ensure
that there are no in-flight transactions.

When forking the simulator, the fork method returns the PID of the child
process, or returns 0 if running in the child. This is in line with the standard
Python forking interface.

Signed-off-by: Andreas Sandberg <andreas@sandberg.pp.se>
[sascha.bischoff@arm.com: Rebased patches onto a newer gem5 version]
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
[andreas.sandberg@arm.com: Updated to comply with modern draining semantics ]
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
src/python/m5/simulate.py
src/python/swig/core.i

index d89629d2df6d4c6c5db0b61a9c3a7c6229f46595..5d70f4b18a8d61feb4da4bc8fca6f391c9c974b8 100644 (file)
@@ -312,4 +312,57 @@ def notifyFork(root):
     for obj in root.descendants():
         obj.notifyFork()
 
+fork_count = 0
+def fork(simout="%(parent)s.f%(fork_seq)i"):
+    """Fork the simulator.
+
+    This function forks the simulator. After forking the simulator,
+    the child process gets its output files redirected to a new output
+    directory. The default name of the output directory is the same as
+    the parent with the suffix ".fN" added where N is the fork
+    sequence number. The name of the output directory can be
+    overridden using the simout keyword argument.
+
+    Output file formatting dictionary:
+      parent -- Path to the parent process's output directory.
+      fork_seq -- Fork sequence number.
+      pid -- PID of the child process.
+
+    Keyword Arguments:
+      simout -- New simulation output directory.
+
+    Return Value:
+      pid of the child process or 0 if running in the child.
+    """
+    from m5 import options
+    global fork_count
+
+    if not internal.core.listenersDisabled():
+        raise RuntimeError, "Can not fork a simulator with listeners enabled"
+
+    drain()
+
+    try:
+        pid = os.fork()
+    except OSError, e:
+        raise e
+
+    if pid == 0:
+        # In child, notify objects of the fork
+        root = objects.Root.getInstance()
+        notifyFork(root)
+        # Setup a new output directory
+        parent = options.outdir
+        options.outdir = simout % {
+                "parent" : parent,
+                "fork_seq" : fork_count,
+                "pid" : os.getpid(),
+                }
+        core.setOutputDir(options.outdir)
+    else:
+        fork_count += 1
+
+    return pid
+
 from internal.core import disableAllListeners
+from internal.core import listenersDisabled
index 862c0e37e469bce296b9077c20202f8e7c32327c..08fbe01d191c2d9fec2e7ff3418cede4562d5aac 100644 (file)
@@ -55,6 +55,8 @@ const bool flag_TRACING_ON = TRACING_ON;
 
 inline void disableAllListeners() { ListenSocket::disableAll(); }
 
+inline bool listenersDisabled() { return ListenSocket::allDisabled(); }
+
 inline void
 seedRandom(uint64_t seed)
 {
@@ -71,6 +73,7 @@ seedRandom(uint64_t seed)
 void setOutputDir(const std::string &dir);
 void doExitCleanup();
 void disableAllListeners();
+bool listenersDisabled();
 void seedRandom(uint64_t seed);
 
 %immutable compileDate;