From 4daf99fc2cb6d873e804d24d56ddd849fc4e514b Mon Sep 17 00:00:00 2001 From: Adriaan Schmidt Date: Wed, 10 Aug 2022 05:05:03 +0000 Subject: [PATCH] feat(scheduler): match thread names in addition to process names This is a first try at matching thread names (comm) in addition to the process cmdline for changing scheduling policies and priorities with the `scheduler` plugin. It adds an optional second regex field to the end of `group.*` options (defaults to ".*"). The first regex is to match the process cmdline, the second one is used to match the thread's comm. If both match, scheduling options are applied. Note that you can have multiple `group.*` options with the same process regex and different thread regexes. You can even have one rule to match a specific thread name, and another with no thread regex (matching all threads). In this case you need to assign rule priorities (higher number -> higher priority). Signed-off-by: Adriaan Schmidt --- profiles/realtime-virtual-guest/tuned.conf | 2 +- profiles/realtime-virtual-host/tuned.conf | 2 +- tuned/plugins/plugin_scheduler.py | 67 ++++++++++++++++------ 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/profiles/realtime-virtual-guest/tuned.conf b/profiles/realtime-virtual-guest/tuned.conf index a381f41..288f9d0 100644 --- a/profiles/realtime-virtual-guest/tuned.conf +++ b/profiles/realtime-virtual-guest/tuned.conf @@ -22,7 +22,7 @@ non_isolated_cores=${f:cpulist_invert:${isolated_cores}} assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}} [scheduler] -# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex +# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex[:thread_name_regex] # for i in `pgrep ksoftirqd` ; do grep Cpus_allowed_list /proc/$i/status ; done group.ksoftirqd=0:f:2:*:^\[ksoftirqd group.ktimers=0:f:2:*:^\[ktimers diff --git a/profiles/realtime-virtual-host/tuned.conf b/profiles/realtime-virtual-host/tuned.conf index b0e8846..0f520df 100644 --- a/profiles/realtime-virtual-host/tuned.conf +++ b/profiles/realtime-virtual-host/tuned.conf @@ -27,7 +27,7 @@ non_isolated_cores=${f:cpulist_invert:${isolated_cores}} assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}} [scheduler] -# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex +# group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex[:thread_name_regex] # for i in `pgrep ksoftirqd` ; do grep Cpus_allowed_list /proc/$i/status ; done group.ksoftirqd=0:f:2:*:^\[ksoftirqd group.ktimers=0:f:2:*:^\[ktimers diff --git a/tuned/plugins/plugin_scheduler.py b/tuned/plugins/plugin_scheduler.py index 10ff4e7..74678d9 100644 --- a/tuned/plugins/plugin_scheduler.py +++ b/tuned/plugins/plugin_scheduler.py @@ -565,10 +565,11 @@ class SchedulerPlugin(base.Plugin): if not isinstance(process, procfs.process): pid = process process = procfs.process(pid) - cmdline = procfs.process_cmdline(process) + cmd = procfs.process_cmdline(process) + comm = process['stat']['comm'] if self._is_kthread(process): - cmdline = "[" + cmdline + "]" - return cmdline + return "[" + cmd + "]", "[" + comm + "]" + return cmd, comm # Raises OSError, IOError def get_processes(self): @@ -582,7 +583,7 @@ class SchedulerPlugin(base.Plugin): processes[pid] = cmd if "threads" in proc: for pid in proc["threads"].keys(): - cmd = self._get_cmdline(proc) + cmd = self._get_cmdline(pid) processes[pid] = cmd except (OSError, IOError) as e: if e.errno == errno.ENOENT \ @@ -817,7 +818,16 @@ class SchedulerPlugin(base.Plugin): (scheduler, priority) = self._convert_sched_params( scheduler, priority) affinity = self._convert_affinity(affinity) - return (rule_prio, scheduler, priority, affinity, regex) + # split regex into two, one to match the cmdline, and one the comm + # if there is only one regex for the cmdline, then the comm is matched by ".*" + # allow escaping of colons in regexes (-> '\:' is not a delimiter in the split) + regexes = re.split(r'(?