The current command-line interface allows for chaining of multiple
actions, which results in ambiguous user input, a need for maintaining
variable states (thread-list, cpu-list, etc.) in the program, and a need
to type check input after parsing. The help menu can also be
overwhelming.
Allow for the use of argparse rather than getopt to significantly
simplify the program.
Provide subcommands and clearer usage menus for the user,
introduce type checking at the parser level, and remove
ambiguity for user input.
Signed-off-by: Leah Leshchinsky <lleshchi(a)redhat.com>
diff --git a/tuna-cmd.py b/tuna-cmd.py
index ac21481df554..97042e431ee6 100755
--- a/tuna-cmd.py
+++ b/tuna-cmd.py
@@ -16,6 +16,7 @@
""" tuna - Application Tuning GUI """
+import argparse
import os
import sys
import errno
@@ -41,67 +42,131 @@ except:
nr_cpus = None
ps = None
irqs = None
-version = "0.17"
-
-
-def usage():
- print(_('Usage: tuna [OPTIONS]'))
- fmt = '\t%-40s %s'
- print(fmt % ('-h, --help', _('Give this help
list')))
- print(fmt % ('-a, --config_file_apply=profilename',
- _('Apply changes described in profile')))
- print(fmt % ('-l, --config_file_list',
- _('List preloaded profiles')))
- print(fmt % ('-g, --gui', _('Start the GUI')))
- print(fmt % ('-G, --cgroup',
- _('Display the processes with the type of cgroups they are
in')))
- print(fmt % ('-c, --cpus=' + _('CPU-LIST'), _('%(cpulist)s
affected by commands') %
- {"cpulist": _('CPU-LIST')}))
- print(fmt % ('-C, --affect_children',
- _('Operation will affect children threads')))
- print(fmt % ('-d, --disable_perf',
- _('Explicitly disable usage of perf in GUI for process view')))
- print(fmt % ('-f, --filter',
- _('Display filter the selected entities')))
- print(fmt % ('-i, --isolate', _('Move all allowed threads
and IRQs away from %(cpulist)s') %
- {"cpulist": _('CPU-LIST')}))
- print(fmt % ('-I, --include', _('Allow all allowed threads
and IRQs to run on %(cpulist)s') %
- {"cpulist": _('CPU-LIST')}))
- print(fmt % ('-K, --no_kthreads',
- _('Operations will not affect kernel threads')))
- print(fmt % ('-m, --move', _('Move selected entities to
%(cpulist)s') %
- {"cpulist": _('CPU-LIST')}))
- print(fmt % ('-N, --nohz_full',
- _('CPUs in nohz_full= kernel command line will be affected by
operations')))
+
+class HelpMessageParser(argparse.ArgumentParser):
+ def error(self, message):
+ sys.stderr.write('error: %s\n' % message)
+ self.print_help()
+ sys.exit(2)
+
+def gen_parser():
+
+
+ POS = {
+ "cpu_list": dict(metavar='CPU-LIST',
type=tuna.cpustring_to_list, help="CPU-LIST affected by commands"),
+ "thread_list": dict(metavar='THREAD-LIST',
type=threadstring_to_list, help="THREAD-LIST affected by commands"),
+ "filename": dict(metavar='FILENAME', type=str,
help="Save kthreads sched tunables to this file"),
+ "profilename": dict(type=str, help="Apply changes described in
this file"),
+ "run_command": dict(metavar='COMMAND', type=str,
help="fork a new process and run the \"COMMAND\""),
+ "priority": dict(type=str, help="policy/priority help"),
+ }
+
+ MODS = {
+ "version": dict(action='version', version='0.16',
help="show version"),
+ "threads": dict(dest='thread_list', default=[],
metavar='THREAD-LIST', type=threadstring_to_list, help="THREAD-LIST affected
by commands"),
+ "irqs": dict(dest='irq_list', default=[],
metavar='IRQ-LIST', type=irqstring_to_list, help="IRQ-LIST affect by
commands"),
+ "cpus": dict(dest='cpu_list', default=[],
metavar='CPU-LIST', type=tuna.cpustring_to_list, help='CPU-LIST affected by
commands'),
+ "sockets": dict(default=[], nargs='+', type=int,
help="CPU-SOCKET-LIST affected by commands"),
+ "show_sockets": dict(action='store_true', help='Show
network sockets in use by threads'),
+ "cgroups": dict(action='store_true',
dest='cgroups', help='Display the processes with the type of cgroups they are
in'),
+ "affect_children": dict(action='store_true',
help="Operation will affect children threads"),
+ "nohz_full": dict(action='store_true', help="CPUs in
nohz_full kernel command line will be affected by operations"),
+ "no_uthreads": dict(action='store_false',
dest='uthreads', help="Operations will not affect user threads"),
+ "no_kthreads": dict(action='store_false',
dest='kthreads', help="Operations will not affect kernel threads"),
+ "disable_perf": dict(action='store_true',
help="Explicitly disable usage of perf in GUI for process view"),
+ "refresh": dict(default=2500, metavar='MSEC', type=int,
help="Refresh the GUI every MSEC milliseconds"),
+ "priority": dict(default=(None, None),
type=tuna.get_policy_and_rtprio, help="Set thread scheduler tunables: POLICY and
RTPRIO"),
+ "background": dict(action='store_true', help="Run
command as background task")
+ }
+
+ parser = HelpMessageParser(description="tuna - Application Tuning GUI")
+
+ parser._positionals.title = "subcommands"
+ parser.add_argument('-v', '--version', **MODS['version'])
+
+ subparser = parser.add_subparsers(dest='command')
+
+ isolate = subparser.add_parser('isolate', help="Allow all threads to run
on CPU-LIST")
+ include = subparser.add_parser('include', help="Allow all threads to run
on CPU-LIST")
+ move = subparser.add_parser('move', help="Move selected entities to
CPU-LIST")
+ spread = subparser.add_parser('spread', help="Spread selected entities
over CPU-LIST")
+ priority = subparser.add_parser('priority', help="Set thread scheduler
tunables: POLICY and RTPRIO")
+ run = subparser.add_parser('run', help="fork a new process and run the
COMMAND")
+ save = subparser.add_parser('save', help="Save kthreads sched tunables
to FILENAME")
+ apply = subparser.add_parser('apply', help="Apply changes described in
profile")
+ show = subparser.add_parser('show', help='Show a list for given
SUBCOMMAND')
+ what_is = subparser.add_parser('what_is', help='Provides help about
selected entities')
+ gui = subparser.add_parser('gui', help="Start the GUI")
+
+ show._positionals.title = "subcommands"
+
+ show_parser = show.add_subparsers(dest='show_command')
+ show_parser.required = True
+ show_configs = show_parser.add_parser('configs', help='List preloaded
profiles')
+ show_threads = show_parser.add_parser('threads', help='Show thread
list')
+ show_irqs = show_parser.add_parser('irqs', help='Show IRQ list')
+
+ isolate_group = isolate.add_mutually_exclusive_group(required=True)
+ isolate_group.add_argument('-c', '--cpus', **MODS['cpus'])
+ isolate_group.add_argument('-N', '--nohz_full',
**MODS['nohz_full'])
+
+ include_group = include.add_mutually_exclusive_group(required=True)
+ include_group.add_argument('-c', '--cpus', **MODS['cpus'])
+ include_group.add_argument('-N', '--nohz_full',
**MODS['nohz_full'])
+
+ move_group = move.add_mutually_exclusive_group(required=True)
+ move_group.add_argument('-c', '--cpus', **MODS['cpus'])
+ move_group.add_argument('-N', '--nohz_full',
**MODS['nohz_full'])
+ move.add_argument('-t', '--threads', **MODS['threads'])
+ move.add_argument('-q', '--irqs', **MODS['irqs'])
+
+ spread_group = spread.add_mutually_exclusive_group(required=True)
+ spread_group.add_argument('-c', '--cpus', **MODS['cpus'])
+ spread_group.add_argument('-N', '--nohz_full',
**MODS['nohz_full'])
+ spread.add_argument('-t', '--threads', **MODS['threads'])
+ spread.add_argument('-q', '--irqs', **MODS['irqs'])
+
+ priority.add_argument('priority', **POS['priority'])
+ priority.add_argument('-t', '--threads', **MODS['threads'],
required=True)
+ priority.add_argument('-C', '--affect_children',
**MODS['affect_children'])
+
+ run.add_argument('run_command', **POS['run_command'])
+ run.add_argument('-c', '--cpus', **MODS['cpus'])
+ run.add_argument('-p', '--priority', **MODS['priority'])
+ run.add_argument('-b', '--background', **MODS['background'])
+
+ save.add_argument('filename', **POS['filename'])
+ save.add_argument('-c', '--cpus', **MODS['cpus'])
+ save.add_argument('-t', '--threads', **MODS['threads'])
+
+ apply.add_argument('profilename', **POS['profilename'])
+
+ show_threads_group1 = show_threads.add_mutually_exclusive_group(required=False)
+ show_threads_group1.add_argument('-c', '--cpus',
**MODS['cpus'])
+ show_threads_group1.add_argument('-N', '--nohz_full',
**MODS['nohz_full'])
+ show_threads_group2 = show_threads.add_mutually_exclusive_group(required=False)
+ show_threads_group2.add_argument('-t', '--threads',
**MODS['threads'])
+ show_threads_group2.add_argument('-q', '--irqs',
**MODS['irqs'])
+ show_threads.add_argument('-U', '--no_uthreads',
**MODS['no_uthreads'])
+ show_threads.add_argument('-K', '--no_kthreads',
**MODS['no_kthreads'])
+ show_threads.add_argument('-C', '--affect_children',
**MODS['affect_children'])
+
if have_inet_diag:
- print(fmt % ('-n, --show_sockets',
- _('Show network sockets in use by threads')))
- print(fmt % ('-p, --priority=[' +
- _('POLICY') + ':]' +
- _('RTPRIO'), _('Set thread scheduler
tunables: %(policy)s and %(rtprio)s') %
- {"policy": _('POLICY'), "rtprio":
_('RTPRIO')}))
- print(fmt % ('-P, --show_threads', _('Show thread list')))
- print(fmt % ('-Q, --show_irqs', _('Show IRQ list')))
- print(fmt % ('-q, --irqs=' + _('IRQ-LIST'), _('%(irqlist)s
affected by commands') %
- {"irqlist": _('IRQ-LIST')}))
- print(fmt % ('-r, --run=' + _('COMMAND'), _('fork a new process
and run the %(command)s') %
- {"command": _('COMMAND')}))
- print(fmt % ('-R, --refresh=' + _('MSEC'), _('Refresh the GUI
every MSEC milliseconds')))
- print(fmt % ('-s, --save=' + _('FILENAME'), _('Save kthreads
sched tunables to %(filename)s') %
- {"filename": _('FILENAME')}))
- print(fmt % ('-S, --sockets=' +
- _('CPU-SOCKET-LIST'), _('%(cpusocketlist)s affected
by commands') %
- {"cpusocketlist": _('CPU-SOCKET-LIST')}))
- print(fmt % ('-t, --threads=' +
- _('THREAD-LIST'), _('%(threadlist)s affected by
commands') %
- {"threadlist": _('THREAD-LIST')}))
- print(fmt % ('-U, --no_uthreads',
- _('Operations will not affect user threads')))
- print(fmt % ('-v, --version', _('Show version')))
- print(fmt % ('-W, --what_is',
- _('Provides help about selected entities')))
- print(fmt % ('-x, --spread', _('Spread selected entities
over %(cpulist)s') %
- {"cpulist": _('CPU-LIST')}))
+ show_threads.add_argument('-n', '--show_sockets',
**MODS['show_sockets'])
+ show_threads.add_argument('-G', '--cgroups',
**MODS['cgroups'])
+
+ show_irqs.add_argument('-c', '--cpus', **MODS['cpus'])
+ show_irqs.add_argument('-q', '--irqs', **MODS['irqs'])
+
+ what_is.add_argument('thread_list', **POS['thread_list'])
+
+ gui.add_argument('-d', '--disable_perf',
**MODS['disable_perf'])
+ gui.add_argument('-R', '--refresh', **MODS['refresh'])
+ gui.add_argument('-c', '--cpus', **MODS['cpus'])
+ gui.add_argument('-U', '--no_uthreads',
**MODS['no_uthreads'])
+ gui.add_argument('-K', '--no_kthreads',
**MODS['no_kthreads'])
+
+ return parser
def get_nr_cpus():
@@ -400,39 +465,34 @@ def do_list_op(op, current_list, op_list):
return list(set(current_list) - set(op_list))
return list(set(op_list))
-
-def thread_mapper(s):
+def threadstring_to_list(threadstr):
global ps
- try:
- return [int(s), ]
- except:
- pass
-
- ps = procfs.pidstats()
-
- try:
- return ps.find_by_regex(re.compile(fnmatch.translate(s)))
- except:
- return ps.find_by_name(s)
-
+ thread_list = []
+ thread_strings = list(set(threadstr.split(',')))
+ print(thread_strings)
+ for s in thread_strings:
+ if s.isdigit():
+ thread_list.append(int(s))
+ else:
+ ps = procfs.pidstats()
+ try:
+ thread_list += ps.find_by_regex(re.compile(fnmatch.translate(s)))
+ except:
+ thread_list += ps.find_by_name(s)
+ return thread_list
-def irq_mapper(s):
- global irqs
- try:
- return [int(s), ]
- except:
- pass
- if not irqs:
- irqs = procfs.interrupts()
+def irqstring_to_list(irqstr):
- irq_list_str = irqs.find_by_user_regex(re.compile(fnmatch.translate(s)))
irq_list = []
- for i in irq_list_str:
- try:
- irq_list.append(int(i))
- except:
- pass
-
+ irq_strings = list(set(irqstr.split(',')))
+ print(irq_strings)
+ for s in irq_strings:
+ if s.isdigit():
+ irq_list.append(int(s))
+ else:
+ # find_by_user_regex returns a list of strings corresponding to irq number
+ irq_list_str =
procfs.interrupts().find_by_user_regex(re.compile(fnmatch.translate(s)))
+ irq_list += [int(i) for i in irq_list_str if i.isdigit()]
return irq_list
@@ -484,272 +544,108 @@ def list_config():
print(value)
sys.exit(1)
+def nohz_full_to_cpu():
+
+ try:
+ return tuna.nohz_full_list()
+ except:
+ print("tuna: --nohz_full " +
+ _(" needs nohz_full=cpulist on the kernel command line"))
+ sys.exit(2)
def main():
global ps
i18n_init()
- try:
- short = "a:c:dCfgGhiIKlmNp:PQq:r:R:s:S:t:UvWx"
- long = ["cpus=", "affect_children", "filter",
"gui", "help",
- "isolate", "include", "no_kthreads",
"move", "nohz_full",
- "show_sockets", "priority=",
"show_threads",
- "show_irqs", "irqs=",
- "save=", "sockets=", "threads=",
"no_uthreads",
- "version", "what_is", "spread",
"cgroup", "config_file_apply=",
- "config_file_list", "run=", "refresh=",
"disable_perf"]
- if have_inet_diag:
- short += "n"
- long.append("show_sockets")
- opts, args = getopt.getopt(sys.argv[1:], short, long)
- except getopt.GetoptError as err:
- usage()
- print(str(err))
- sys.exit(2)
- run_gui = not opts
- kthreads = True
- uthreads = True
- cgroups = False
- cpu_list = None
- irq_list = None
- irq_list_str = None
- rtprio = None
- policy = None
- thread_list = []
- thread_list_str = None
- filter = False
- affect_children = False
- show_sockets = False
- p_waiting_action = False
- gui_refresh = 2500
- disable_perf = False
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- return
- if o in ("-a", "--config_file_apply"):
- apply_config(a)
- elif o in ("-l", "--config_file_list"):
- list_config()
- elif o in ("-c", "--cpus"):
- (op, a) = pick_op(a)
- try:
- op_list = tuna.cpustring_to_list(a)
- except ValueError:
- usage()
- return
- cpu_list = do_list_op(op, cpu_list, op_list)
- elif o in ("-N", "--nohz_full"):
- try:
- cpu_list = tuna.nohz_full_list()
- except:
- print("tuna: --nohz_full " +
- _(" needs nohz_full=cpulist on the kernel command
line"))
- sys.exit(2)
- elif o in ("-C", "--affect_children"):
- affect_children = True
- elif o in ("-G", "--cgroup"):
- cgroups = True
- elif o in ("-t", "--threads"):
- # The -t - will reset thread list
- if a == '-':
- thread_list = []
- thread_list_str = ''
- else:
- (op, a) = pick_op(a)
- op_list = reduce(lambda i, j: i + j,
- list(map(thread_mapper, a.split(","))))
- op_list = list(set(op_list))
- thread_list = do_list_op(op, thread_list, op_list)
- # Check if a process name was specified and no
- # threads was found, which would result in an empty
- # thread list, i.e. we would print all the threads
- # in the system when we should print nothing.
- if not op_list and isinstance(a, type('')):
- thread_list_str = do_list_op(op, thread_list_str,
- a.split(","))
- if not op:
- irq_list = None
- elif o in ("-f", "--filter"):
- filter = True
- elif o in ("-g", "--gui"):
- run_gui = True
- elif o in ("-R", "--refresh"):
- run_gui = True
- (op, a) = pick_op(a)
- try:
- gui_refresh=int(a)
- except Exception as err:
- print("tuna: --refresh %s" % err)
- sys.exit(2)
- elif o in ("-d", "--disable_perf"):
- run_gui = True
- disable_perf = True
- elif o in ("-i", "--isolate"):
- if not cpu_list:
- print("tuna: --isolate " + _("requires a cpu
list!"))
- sys.exit(2)
- tuna.isolate_cpus(cpu_list, get_nr_cpus())
- elif o in ("-I", "--include"):
- if not cpu_list:
- print("tuna: --include " + _("requires a cpu
list!"))
- sys.exit(2)
- tuna.include_cpus(cpu_list, get_nr_cpus())
- elif o in ("-p", "--priority"):
- # Save policy and rtprio for future Actions (e.g. --run).
- try:
- (policy, rtprio) = tuna.get_policy_and_rtprio(a)
- except ValueError:
- print("tuna: " + _("\"%s\" is an unsupported
priority value!") % a)
- sys.exit(2)
- if not thread_list:
- # For backward compatibility
- p_waiting_action = True
- else:
- try:
- tuna.threads_set_priority(thread_list, a, affect_children)
- except OSError as err:
- print("tuna: %s" % err)
- sys.exit(2)
- elif o in ("-P", "--show_threads"):
- # If the user specified process names that weren't
- # resolved to pids, don't show all threads.
- if not thread_list and not irq_list:
- if thread_list_str or irq_list_str:
- continue
- do_ps(thread_list, cpu_list, irq_list, uthreads,
- kthreads, affect_children, show_sockets, cgroups)
- elif o in ("-Q", "--show_irqs"):
- # If the user specified IRQ names that weren't
- # resolved to IRQs, don't show all IRQs.
- if not irq_list and irq_list_str:
- continue
- show_irqs(irq_list, cpu_list)
- elif o in ("-n", "--show_sockets"):
- show_sockets = True
- elif o in ("-m", "--move", "-x",
"--spread"):
- spread = o in ("-x", "--spread")
- if not cpu_list:
- print("tuna: %s " % ("--spread" if spread else
"--move") + _("requires a cpu list!"))
- sys.exit(2)
- if not (thread_list or irq_list):
- print("tuna: %s " % ("--spread" if spread else
"--move") + _("requires a list of threads/irqs!"))
- sys.exit(2)
-
- if thread_list:
- tuna.move_threads_to_cpu(cpu_list, thread_list, spread=spread)
-
- if irq_list:
- tuna.move_irqs_to_cpu(cpu_list, irq_list, spread=spread)
- elif o in ("-s", "--save"):
- save(cpu_list, thread_list, a)
- elif o in ("-S", "--sockets"):
- (op, a) = pick_op(a)
- sockets = list(a.split(','))
-
- if not cpu_list:
- cpu_list = []
-
- cpu_info = sysfs.cpus()
- op_list = []
- for socket in sockets:
- if socket not in cpu_info.sockets:
- print("tuna: %s" %
- (_("invalid socket %(socket)s sockets available:
%(available)s") %
- {"socket": socket,
- "available":
",".join(list(cpu_info.sockets.keys()))}))
- sys.exit(2)
- op_list += [int(cpu.name[3:])
- for cpu in cpu_info.sockets[socket]]
- cpu_list = do_list_op(op, cpu_list, op_list)
- elif o in ("-K", "--no_kthreads"):
- kthreads = False
- elif o in ("-q", "--irqs"):
- (op, a) = pick_op(a)
- op_list = reduce(lambda i, j: i + j,
- list(map(irq_mapper, list(set(a.split(","))))))
- irq_list = do_list_op(op, irq_list, op_list)
- # See comment above about thread_list_str
- if not op_list and isinstance(a, type('')):
- irq_list_str = do_list_op(op, irq_list_str, a.split(","))
- if not op:
- thread_list = []
- if not ps:
- ps = procfs.pidstats()
- if tuna.has_threaded_irqs(ps):
- for irq in irq_list:
- irq_re = tuna.threaded_irq_re(irq)
- irq_threads = ps.find_by_regex(irq_re)
- if irq_threads:
- # Change the affinity of the thread too
- # as we can't rely on changing the irq
- # affinity changing the affinity of the
- # thread or vice versa. We need to change
- # both.
- thread_list += irq_threads
-
- elif o in ("-U", "--no_uthreads"):
- uthreads = False
- elif o in ("-v", "--version"):
- print(version)
- elif o in ("-W", "--what_is"):
- if not thread_list:
- print("tuna: --what_is " + _("requires a thread
list!"))
- sys.exit(2)
- for tid in thread_list:
- thread_help(tid)
- elif o in ("-r", "--run"):
- # If -p is set, it will be consumed. So, no backward compatible
- # error handling action must be taken.
- p_waiting_action = False
-
- # pick_op() before run the command: to remove the prefix
- # + or - from command line.
- (op, a) = pick_op(a)
-
- # In order to include the new process, it must run
- # the command first, and then get the list of pids,
- tuna.run_command(a, policy, rtprio, cpu_list)
-
- op_list = reduce(lambda i, j: i + j,
- list(map(thread_mapper, a.split(","))))
- op_list = list(set(op_list))
- thread_list = do_list_op(op, thread_list, op_list)
-
- # Check if a process name was specified and no
- # threads was found, which would result in an empty
- # thread list, i.e. we would print all the threads
- # in the system when we should print nothing.
- if not op_list and isinstance(a, type('')):
- thread_list_str = do_list_op(op, thread_list_str,
a.split(","))
- if not op:
- irq_list = None
-
- # For backward compatibility: when -p used to be only an Action, it
- # used to exit(2) if no action was taken (i.e. if no threads_list
- # was set).
- if p_waiting_action:
- print(("tuna: -p ") + _("requires a thread list!"))
- sys.exit(2)
+ parser = gen_parser()
+ # Set all necessary defaults for gui subparser if no arguments provided
+ args = parser.parse_args() if len(sys.argv) > 1 else
parser.parse_args(['gui'])
+
+ if 'irq_list' in vars(args):
+ ps = procfs.pidstats()
+ if tuna.has_threaded_irqs(ps):
+ for irq in args.irq_list:
+ irq_re = tuna.threaded_irq_re(irq)
+ irq_threads = ps.find_by_regex(irq_re)
+ if irq_threads:
+ # Change the affinity of the thread too
+ # as we can't rely on changing the irq
+ # affinity changing the affinity of the
+ # thread or vice versa. We need to change
+ # both.
+ if 'thread_list' in vars(args):
+ args.thread_list += irq_threads
+
+ if 'nohz_full' in vars(args) and args.nohz_full:
+ args.cpu_list = nohz_full_to_cpu()
+
+ if args.command in ['apply', 'a']:
+ apply_config(args.profilename)
+
+ elif args.command in ['include', 'I']:
+ tuna.include_cpus(args.cpu_list, get_nr_cpus())
+
+ elif args.command in ['isolate', 'i']:
+ tuna.isolate_cpus(args.cpu_list, get_nr_cpus())
+
+ elif args.command in ['run', 'r']:
+
+ tuna.run_command(args.run_command, args.priority[0], args.priority[1],
args.cpu_list, args.background)
+
+ elif args.command in ['priority', 'p']:
+
+ try:
+ tuna.threads_set_priority(args.thread_list, args.priority,
args.affect_children)
+ except OSError as err:
+ print("tuna: %s" % err)
+ sys.exit(2)
+
+ elif args.command in ['show', 'l']:
+ if args.show_command in ['configs']:
+ list_config()
+ elif args.show_command in ['threads']:
+ do_ps(args.thread_list, args.cpu_list, args.irq_list, args.uthreads,
+ args.kthreads, args.affect_children, args.show_sockets if
"show_sockets" in args else None, args.cgroups)
+ elif args.show_command in ['irqs']:
+ show_irqs(args.irq_list, args.cpu_list)
+ else:
+ raise Exception("No args.show_command for `show` command")
+
+ elif args.command in ['move', 'm', 'spread', 'x']:
+ spread = args.command in ['spread', 'x']
+
+ if not (args.thread_list or args.irq_list):
+ parser.error("tuna: %s " % (args.command) + _("requires a
thread/irq list!\n"))
+
+ if args.thread_list:
+ tuna.move_threads_to_cpu(args.cpu_list, args.thread_list, spread=spread)
+
+ if args.irq_list:
+ tuna.move_irqs_to_cpu(args.cpu_list, args.irq_list, spread=spread)
+
+ elif args.command in ['s', 'save']:
+ save(args.cpu_list, args.thread_list, args.filename)
+
+ elif args.command in ['W', 'what_is']:
+ for tid in args.thread_list:
+ thread_help(tid)
- if run_gui:
+ elif args.command in ['g', 'gui']:
try:
from tuna import tuna_gui
except ImportError:
# gui packages not installed
print(_('tuna: packages needed for the GUI missing.'))
print(_(' Make sure xauth, pygtk2-libglade are installed.'))
- usage()
+ parser.print_help()
return
except RuntimeError:
print("tuna: machine needs to be authorized via xhost or ssh -X?")
return
try:
- cpus_filtered = filter if cpu_list else []
- app = tuna_gui.main_gui(kthreads, uthreads, cpus_filtered, gui_refresh,
disable_perf)
+ app = tuna_gui.main_gui(args.kthreads, args.uthreads, args.cpu_list,
args.refresh, args.disable_perf)
app.run()
except KeyboardInterrupt:
pass
diff --git a/tuna/tuna.py b/tuna/tuna.py
index 31707c9cb69c..8650f11c81c3 100755
--- a/tuna/tuna.py
+++ b/tuna/tuna.py
@@ -618,7 +618,7 @@ def get_kthread_sched_tunings(proc=None):
return kthreads
-def run_command(cmd, policy, rtprio, cpu_list):
+def run_command(cmd, policy, rtprio, cpu_list, background):
newpid = os.fork()
if newpid == 0:
cmd_list = shlex.split(cmd)
@@ -642,7 +642,8 @@ def run_command(cmd, policy, rtprio, cpu_list):
print("tuna: %s" % err)
sys.exit(2)
else:
- os.waitpid(newpid, 0)
+ if not background:
+ os.waitpid(newpid, 0)
def generate_rtgroups(filename, kthreads, nr_cpus):
f = open(filename, "w")
--
2.27.0