@@ -247,6 +247,7 @@ if __name__ == '__main__':
if not config.HasSection('measurement'):
config.AppendConfig('measurement', {
'cyclictest' : 'module',
+ 'timerlat' : 'module',
'sysstat' : 'module'})
# Prepare log levels before loading modules, not to have unwanted log messages
new file mode 100644
@@ -0,0 +1,131 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright 2024 John Kacur <jkacur@redhat.com>
+#
+""" timerlat.py - objectd to manage rtla timerlat """
+import os
+import subprocess
+import signal
+import time
+import tempfile
+import libxml2
+from rteval.Log import Log
+from rteval.modules import rtevalModulePrototype
+from rteval.systopology import cpuinfo, SysTopology
+from rteval.cpulist_utils import expand_cpulist, collapse_cpulist
+
+class Timerlat(rtevalModulePrototype):
+ """ measurement modules for rteval """
+ def __init__(self, config, logger=None):
+ rtevalModulePrototype.__init__(self, 'measurement', 'timerlat', logger)
+
+ self.__cfg = config
+
+ self.__numanodes = int(self.__cfg.setdefault('numanodes', 0))
+ self.__priority = int(self.__cfg.setdefault('priority', 95))
+
+ self.__cpulist = self.__cfg.setdefault('cpulist', "")
+ self.__cpus = [str(c) for c in expand_cpulist(self.__cpulist)]
+ self.__numcores = len(self.__cpus)
+
+ self.__timerlat_out = None
+ self.__timerlat_err = None
+ self.__started = False
+ self._log(Log.DEBUG, f"system using {self.__numcores} cpu cores")
+
+
+ def _WorkloadSetup(self):
+ self.__timerlat_process = None
+
+ def _WorkloadBuild(self):
+ self._setReady()
+
+ def _WorkloadPrepare(self):
+ self.__cmd = ['rtla', 'timerlat', 'hist', '-P', f'f:{int(self.__priority)}', '-u']
+ self.__cmd.append(f'-c{self.__cpulist}')
+ self._log(Log.DEBUG, f'self.__cmd = {self.__cmd}')
+ self.__timerlat_out = tempfile.SpooledTemporaryFile(mode='w+b')
+ self.__timerlat_err = tempfile.SpooledTemporaryFile(mode='w+b')
+
+ def _WorkloadTask(self):
+ if self.__started:
+ return
+
+ self._log(Log.DEBUG, f'starting with cmd: {" ".join(self.__cmd)}')
+
+ self.__timerlat_out.seek(0)
+ self.__timerlat_err.seek(0)
+ try:
+ self.__timerlat_process = subprocess.Popen(self.__cmd,
+ stdout=self.__timerlat_out,
+ stderr=self.__timerlat_err,
+ stdin=None)
+ self.__started = True
+ except OSError:
+ self.__started = False
+
+ def WorkloadAlive(self):
+ if self.__started:
+ return self.__timerlat_process.poll() is None
+ return False
+
+ def _WorkloadCleanup(self):
+ if not self.__started:
+ return
+ while self.__timerlat_process.poll() is None:
+ self._log(Log.DEBUG, "Sending SIGINT")
+ os.kill(self.__timerlat_process.pid, signal.SIGINT)
+ time.sleep(2)
+
+ self._setFinished()
+ self.__started = False
+
+ def MakeReport(self):
+ self.__timerlat_out.seek(0)
+ for line in self.__timerlat_out:
+ line = bytes.decode(line)
+ print(line)
+ self.__timerlat_out.close()
+
+
+def ModuleInfo():
+ """ Required measurement module information """
+ return {"parallel": True,
+ "loads": True}
+
+def ModuleParameters():
+ """ default parameters """
+ return {"priority": {"descr": "Run rtla timerlat with this priority",
+ "default": 95,
+ "metavar": "PRIO" }
+ }
+
+def create(params, logger):
+ """ Instantiate a Timerlat measurement module object"""
+ return Timerlat(params, logger)
+
+if __name__ == '__main__':
+ from rteval.rtevalConfig import rtevalConfig
+
+ l = Log()
+ l.SetLogVerbosity(Log.INFO|Log.DEBUG|Log.ERR|Log.WARN)
+
+ cfg = rtevalConfig({}, logger=l)
+ prms = {}
+ modprms = ModuleParameters()
+ for c, p in list(modprms.items()):
+ prms[c] = p['default']
+ cfg.AppendConfig('timerlat', prms)
+
+ cfg_tl = cfg.GetSection('timerlat')
+ cfg_tl.cpulist = collapse_cpulist(SysTopology().online_cpus())
+
+ RUNTIME = 10
+
+ tl = Timerlat(cfg_tl, l)
+ tl._WorkloadSetup()
+ tl._WorkloadPrepare()
+ tl._WorkloadTask()
+ time.sleep(RUNTIME)
+ tl._WorkloadCleanup()
+ tl.MakeReport()
This is the first step to adding timerlat as a measurement module With this change you can run timerlat as a standalone rteval file like this (as root) python rteval/modules/measurement/timerlat.py You can also modify your rteval.conf to list timerlat in the [measurement] section, for example like this [measurement] cyclictest: module timerlat: module and then both measurement moduels will be run from rteval, for example rteval -D -d5m --measurement-cpulist=1-5 Will run rteval with Debug info, for 5m and cyclictest and timerlat will run on cpus 1-5 and load modules will run on the other available cpus. Currently MakeReport just prints to standard out the same information that timerlat outputs, in otherwords, there is no processing into xml yet. Also, there is no way to invoke tracing at the time, but that will be added soon! Signed-off-by: John Kacur <jkacur@redhat.com> --- rteval-cmd | 1 + rteval/modules/measurement/timerlat.py | 131 +++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 rteval/modules/measurement/timerlat.py