Add support for multiple PID/TID for offwaketime (#2951)
Instead of filtering on a single process allow up to 5 pid/tgid to be
used for filtering. The limit of 5 is arbitrary and can be increased
should the need arise. Also remove unnecessary thread_context variable.
Co-authored-by: Nikolay Borisov <nborisov@suse.com>
diff --git a/tools/offwaketime.py b/tools/offwaketime.py
index 88dc68c..117c6e7 100755
--- a/tools/offwaketime.py
+++ b/tools/offwaketime.py
@@ -20,6 +20,16 @@
# arg validation
def positive_int(val):
+ dest = []
+ # Filter up to 5 pids, arbitrary
+ args_list = val.split(",", 5)
+ pids_to_add = min(len(args_list), 5)
+ for i in range(pids_to_add):
+ dest.append(_positive_int(args_list[i]))
+
+ return dest
+
+def _positive_int(val):
try:
ival = int(val)
except ValueError:
@@ -30,11 +40,21 @@
return ival
def positive_nonzero_int(val):
- ival = positive_int(val)
+ ival = _positive_int(val)
if ival == 0:
raise argparse.ArgumentTypeError("must be nonzero")
return ival
+def build_filter(filter_name, values):
+ filter_string = "((%s == %d)" % (filter_name, values[0])
+
+ for val in values[1:]:
+ filter_string += " || (%s == %d )" % (filter_name , val)
+
+ filter_string += ")"
+
+ return filter_string
+
def stack_id_err(stack_id):
# -EFAULT in get_stackid normally means the stack-trace is not available,
# Such as getting kernel stack trace in userspace code
@@ -61,10 +81,12 @@
thread_group = parser.add_mutually_exclusive_group()
# Note: this script provides --pid and --tid flags but their arguments are
# referred to internally using kernel nomenclature: TGID and PID.
-thread_group.add_argument("-p", "--pid", metavar="PID", dest="tgid",
- help="trace this PID only", type=positive_int)
-thread_group.add_argument("-t", "--tid", metavar="TID", dest="pid",
- help="trace this TID only", type=positive_int)
+thread_group.add_argument("-p", "--pid", metavar="PIDS", dest="tgid",
+ type=positive_int,
+ help="trace these PIDS only. Can be a comma separated list of PIDS.")
+thread_group.add_argument("-t", "--tid", metavar="TIDS", dest="pid",
+ type=positive_int,
+ help="trace these TIDS only. Can be a comma separated list of TIDS.")
thread_group.add_argument("-u", "--user-threads-only", action="store_true",
help="user threads only (no kernel threads)")
thread_group.add_argument("-k", "--kernel-threads-only", action="store_true",
@@ -93,7 +115,7 @@
type=positive_nonzero_int,
help="the amount of time in microseconds under which we " +
"store traces (default U64_MAX)")
-parser.add_argument("--state", type=positive_int,
+parser.add_argument("--state", type=_positive_int,
help="filter on this thread state bitmask (eg, 2 == TASK_UNINTERRUPTIBLE" +
") see include/linux/sched.h")
parser.add_argument("--ebpf", action="store_true",
@@ -221,21 +243,15 @@
"""
# set thread filter
-thread_context = ""
if args.tgid is not None:
- thread_context = "PID %d" % args.tgid
- thread_filter = 'tgid == %d' % args.tgid
+ thread_filter = build_filter("tgid", args.tgid)
elif args.pid is not None:
- thread_context = "TID %d" % args.pid
- thread_filter = 'pid == %d' % args.pid
+ thread_filter = build_filter("pid", args.pid)
elif args.user_threads_only:
- thread_context = "user threads"
thread_filter = '!(p->flags & PF_KTHREAD)'
elif args.kernel_threads_only:
- thread_context = "kernel threads"
thread_filter = 'p->flags & PF_KTHREAD'
else:
- thread_context = "all threads"
thread_filter = '1'
if args.state == 0:
state_filter = 'p->state == 0'