Commit 77f4f663 authored by yonghong-song's avatar yonghong-song Committed by GitHub

fix cpuunclaimed.py with cfs_rq structure change (#2164)

Similar to runqlen.py, make proper adjustment for
cfs_rq_partial structure so it can align with
what the kernel expects.
Signed-off-by: default avatarYonghong Song <yhs@fb.com>
parent 9e0817a9
...@@ -62,8 +62,9 @@ from time import sleep, strftime ...@@ -62,8 +62,9 @@ from time import sleep, strftime
from ctypes import c_int from ctypes import c_int
import argparse import argparse
import multiprocessing import multiprocessing
from os import getpid, system from os import getpid, system, open, close, dup, unlink, O_WRONLY
import ctypes as ct import ctypes as ct
from tempfile import NamedTemporaryFile
# arguments # arguments
examples = """examples: examples = """examples:
...@@ -98,6 +99,66 @@ wakeup_s = float(1) / wakeup_hz ...@@ -98,6 +99,66 @@ wakeup_s = float(1) / wakeup_hz
ncpu = multiprocessing.cpu_count() # assume all are online ncpu = multiprocessing.cpu_count() # assume all are online
debug = 0 debug = 0
# Linux 4.15 introduced a new field runnable_weight
# in linux_src:kernel/sched/sched.h as
# struct cfs_rq {
# struct load_weight load;
# unsigned long runnable_weight;
# unsigned int nr_running, h_nr_running;
# ......
# }
# and this tool requires to access nr_running to get
# runqueue len information.
#
# The commit which introduces cfs_rq->runnable_weight
# field also introduces the field sched_entity->runnable_weight
# where sched_entity is defined in linux_src:include/linux/sched.h.
#
# To cope with pre-4.15 and 4.15/post-4.15 releases,
# we run a simple BPF program to detect whether
# field sched_entity->runnable_weight exists. The existence of
# this field should infer the existence of cfs_rq->runnable_weight.
#
# This will need maintenance as the relationship between these
# two fields may change in the future.
#
def check_runnable_weight_field():
# Define the bpf program for checking purpose
bpf_check_text = """
#include <linux/sched.h>
unsigned long dummy(struct sched_entity *entity)
{
return entity->runnable_weight;
}
"""
# Get a temporary file name
tmp_file = NamedTemporaryFile(delete=False)
tmp_file.close();
# Duplicate and close stderr (fd = 2)
old_stderr = dup(2)
close(2)
# Open a new file, should get fd number 2
# This will avoid printing llvm errors on the screen
fd = open(tmp_file.name, O_WRONLY)
try:
t = BPF(text=bpf_check_text)
success_compile = True
except:
success_compile = False
# Release the fd 2, and next dup should restore old stderr
close(fd)
dup(old_stderr)
close(old_stderr)
# remove the temporary file and return
unlink(tmp_file.name)
return success_compile
# process arguments # process arguments
if args.fullcsv: if args.fullcsv:
args.csv = True args.csv = True
...@@ -128,6 +189,7 @@ BPF_PERF_OUTPUT(events); ...@@ -128,6 +189,7 @@ BPF_PERF_OUTPUT(events);
// header. This will need maintenance. It is from kernel/sched/sched.h: // header. This will need maintenance. It is from kernel/sched/sched.h:
struct cfs_rq_partial { struct cfs_rq_partial {
struct load_weight load; struct load_weight load;
RUNNABLE_WEIGHT_FIELD
unsigned int nr_running, h_nr_running; unsigned int nr_running, h_nr_running;
}; };
...@@ -156,6 +218,11 @@ int do_perf_event(struct bpf_perf_event_data *ctx) ...@@ -156,6 +218,11 @@ int do_perf_event(struct bpf_perf_event_data *ctx)
} }
""" """
if check_runnable_weight_field():
bpf_text = bpf_text.replace('RUNNABLE_WEIGHT_FIELD', 'unsigned long runnable_weight;')
else:
bpf_text = bpf_text.replace('RUNNABLE_WEIGHT_FIELD', '')
# code substitutions # code substitutions
if debug or args.ebpf: if debug or args.ebpf:
print(bpf_text) print(bpf_text)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment