1
0
Fork 0

Merge pull request #323 from CZerta/scheduler_os_interface

Changes to scheduler plugin to support os interface instead of schedutils in newer python versions.
This commit is contained in:
Jaroslav Škarvada 2021-03-01 13:00:40 +01:00 committed by GitHub
commit 16f50af056
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 20 deletions

View file

@ -69,7 +69,10 @@ BuildRequires: %{_py}-mock
BuildRequires: %{_py}-configobj
BuildRequires: %{_py}-decorator, %{_py}-pyudev
Requires: %{_py}-decorator, %{_py}-pyudev, %{_py}-configobj
Requires: %{_py}-schedutils, %{_py}-linux-procfs, %{_py}-perf
Requires: %{_py}-linux-procfs, %{_py}-perf
%if %{without python3}
Requires: %{_py}-schedutils
%endif
# requires for packages with inconsistent python2/3 names
%if %{with python3}
# BuildRequires for 'make test'

View file

@ -12,12 +12,16 @@ import perf
import select
import tuned.consts as consts
import procfs
import schedutils
from tuned.utils.commands import commands
import errno
import os
import collections
import math
# Check existence of scheduler API in os module
try:
os.SCHED_FIFO
except AttributeError:
import schedutils
log = tuned.logs.get()
@ -52,20 +56,90 @@ class IRQAffinities(object):
# IRQs that don't support changing CPU affinity:
self.unchangeable = []
class SchedulerUtils(object):
"""
Class encapsulating scheduler implementation in os module
"""
_dict_schedcfg2schedconst = {
"f": "SCHED_FIFO",
"b": "SCHED_BATCH",
"r": "SCHED_RR",
"o": "SCHED_OTHER",
"i": "SCHED_IDLE",
}
def __init__(self):
# {"f": os.SCHED_FIFO...}
self._dict_schedcfg2num = dict((k, getattr(os, name)) for k, name in self._dict_schedcfg2schedconst.items())
# { os.SCHED_FIFO: "SCHED_FIFO"... }
self._dict_num2schedconst = dict((getattr(os, name), name) for name in self._dict_schedcfg2schedconst.values())
def sched_cfg_to_num(self, str_scheduler):
return self._dict_schedcfg2num.get(str_scheduler)
# Reimplementation of schedstr from schedutils for logging purposes
def sched_num_to_const(self, scheduler):
return self._dict_num2schedconst.get(scheduler)
def get_scheduler(self, pid):
return os.sched_getscheduler(pid)
def set_scheduler(self, pid, sched, prio):
os.sched_setscheduler(pid, sched, os.sched_param(prio))
def get_affinity(self, pid):
return os.sched_getaffinity(pid)
def set_affinity(self, pid, affinity):
os.sched_setaffinity(pid, affinity)
def get_priority(self, pid):
return os.sched_getparam(pid).sched_priority
def get_priority_min(self, sched):
return os.sched_get_priority_min(sched)
def get_priority_max(self, sched):
return os.sched_get_priority_max(sched)
class SchedulerUtilsSchedutils(SchedulerUtils):
"""
Class encapsulating scheduler implementation in schedutils module
"""
def __init__(self):
# { "f": schedutils.SCHED_FIFO... }
self._dict_schedcfg2num = dict((k, getattr(schedutils, name)) for k, name in self._dict_schedcfg2schedconst.items())
# { schedutils.SCHED_FIFO: "SCHED_FIFO"... }
self._dict_num2schedconst = dict((getattr(schedutils, name), name) for name in self._dict_schedcfg2schedconst.values())
def get_scheduler(self, pid):
return schedutils.get_scheduler(pid)
def set_scheduler(self, pid, sched, prio):
schedutils.set_scheduler(pid, sched, prio)
def get_affinity(self, pid):
return schedutils.get_affinity(pid)
def set_affinity(self, pid, affinity):
schedutils.set_affinity(pid, affinity)
def get_priority(self, pid):
return schedutils.get_priority(pid)
def get_priority_min(self, sched):
return schedutils.get_priority_min(sched)
def get_priority_max(self, sched):
return schedutils.get_priority_max(sched)
class SchedulerPlugin(base.Plugin):
"""
Plugin for tuning of scheduler. Currently it can control scheduling
priorities of system threads (it is substitution for the rtctl tool).
"""
_dict_schedcfg2num = {
"f": schedutils.SCHED_FIFO,
"b": schedutils.SCHED_BATCH,
"r": schedutils.SCHED_RR,
"o": schedutils.SCHED_OTHER,
"i": schedutils.SCHED_IDLE,
}
def __init__(self, monitor_repository, storage_factory, hardware_inventory, device_matcher, device_matcher_udev, plugin_instance_factory, global_cfg, variables):
super(SchedulerPlugin, self).__init__(monitor_repository, storage_factory, hardware_inventory, device_matcher, device_matcher_udev, plugin_instance_factory, global_cfg, variables)
self._has_dynamic_options = True
@ -83,6 +157,10 @@ class SchedulerPlugin(base.Plugin):
command_name = "scheduler")
self._irq_storage_key = self._storage_key(
command_name = "irq")
try:
self._scheduler_utils = SchedulerUtils()
except AttributeError:
self._scheduler_utils = SchedulerUtilsSchedutils()
def _calc_mmap_pages(self, mmap_pages):
if mmap_pages is None:
@ -216,20 +294,20 @@ class SchedulerPlugin(base.Plugin):
# instead of OSError
# If PID doesn't exist, errno == ESRCH
def _get_rt(self, pid):
scheduler = schedutils.get_scheduler(pid)
sched_str = schedutils.schedstr(scheduler)
priority = schedutils.get_priority(pid)
scheduler = self._scheduler_utils.get_scheduler(pid)
sched_str = self._scheduler_utils.sched_num_to_const(scheduler)
priority = self._scheduler_utils.get_priority(pid)
log.debug("Read scheduler policy '%s' and priority '%d' of PID '%d'"
% (sched_str, priority, pid))
return (scheduler, priority)
def _set_rt(self, pid, sched, prio):
sched_str = schedutils.schedstr(sched)
sched_str = self._scheduler_utils.sched_num_to_const(sched)
log.debug("Setting scheduler policy to '%s' and priority to '%d' of PID '%d'."
% (sched_str, prio, pid))
try:
prio_min = schedutils.get_priority_min(sched)
prio_max = schedutils.get_priority_max(sched)
prio_min = self._scheduler_utils.get_priority_min(sched)
prio_max = self._scheduler_utils.get_priority_max(sched)
if prio < prio_min or prio > prio_max:
log.error("Priority for %s must be in range %d - %d. '%d' was given."
% (sched_str, prio_min,
@ -240,7 +318,7 @@ class SchedulerPlugin(base.Plugin):
log.error("Failed to get allowed priority range: %s"
% e)
try:
schedutils.set_scheduler(pid, sched, prio)
self._scheduler_utils.set_scheduler(pid, sched, prio)
except (SystemError, OSError) as e:
if hasattr(e, "errno") and e.errno == errno.ESRCH:
log.debug("Failed to set scheduling parameters of PID %d, the task vanished."
@ -404,7 +482,7 @@ class SchedulerPlugin(base.Plugin):
self._scheduler_original[pid].cmdline = cmd
def _convert_sched_params(self, str_scheduler, str_priority):
scheduler = self._dict_schedcfg2num.get(str_scheduler)
scheduler = self._scheduler_utils.sched_cfg_to_num(str_scheduler)
if scheduler is None and str_scheduler != "*":
log.error("Invalid scheduler: %s. Scheduler and priority will be ignored."
% str_scheduler)
@ -759,14 +837,14 @@ class SchedulerPlugin(base.Plugin):
# instead of OSError
# If PID doesn't exist, errno == ESRCH
def _get_affinity(self, pid):
res = schedutils.get_affinity(pid)
res = self._scheduler_utils.get_affinity(pid)
log.debug("Read affinity '%s' of PID %d" % (res, pid))
return res
def _set_affinity(self, pid, affinity):
log.debug("Setting CPU affinity of PID %d to '%s'." % (pid, affinity))
try:
schedutils.set_affinity(pid, affinity)
self._scheduler_utils.set_affinity(pid, affinity)
return True
# Workaround for old python-schedutils (pre-0.4) which
# incorrectly raised SystemError instead of OSError