Linux-rt-users archive mirror
 help / color / mirror / Atom feed
From: John Kacur <jkacur@redhat.com>
To: RT <linux-rt-users@vger.kernel.org>
Cc: Clark Williams <williams@redhat.com>,
	Kate Carcia Poulin <kcarcia@redhat.com>,
	Juri Lelli <juri.lelli@redhat.com>,
	Daniel Bristot de Oliveria <bristot@redhat.com>,
	John Kacur <jkacur@redhat.com>
Subject: [PATCH 2/2] rteval: Add rtla timerlat as a measurement module
Date: Fri, 12 Apr 2024 14:50:52 -0400	[thread overview]
Message-ID: <20240412185052.87056-2-jkacur@redhat.com> (raw)
In-Reply-To: <20240412185052.87056-1-jkacur@redhat.com>

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

diff --git a/rteval-cmd b/rteval-cmd
index c72bc614ad78..5cb6d7a44523 100755
--- a/rteval-cmd
+++ b/rteval-cmd
@@ -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
diff --git a/rteval/modules/measurement/timerlat.py b/rteval/modules/measurement/timerlat.py
new file mode 100644
index 000000000000..d4e78de8d2a2
--- /dev/null
+++ b/rteval/modules/measurement/timerlat.py
@@ -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()
-- 
2.44.0


      reply	other threads:[~2024-04-12 18:51 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-12 18:50 [PATCH 1/2] rteval: Cyclictest.py: Make standalone file work again John Kacur
2024-04-12 18:50 ` John Kacur [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240412185052.87056-2-jkacur@redhat.com \
    --to=jkacur@redhat.com \
    --cc=bristot@redhat.com \
    --cc=juri.lelli@redhat.com \
    --cc=kcarcia@redhat.com \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=williams@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).