From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Thomas Falcon <thomas.falcon@intel.com>,
Thomas Richter <tmricht@linux.ibm.com>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Andi Kleen <ak@linux.intel.com>
Subject: [PATCH v2 3/4] perf tool_pmu: Add schedstat events
Date: Fri, 13 Nov 2026 15:37:38 -0800 [thread overview]
Message-ID: <20261113233739.3626499-4-irogers@google.com> (raw)
In-Reply-To: <20261113233739.3626499-1-irogers@google.com>
Add per-CPU tool PMU events backed by /proc/schedstat runqueue
statistics:
- schedstat_yield: Calls to sched_yield().
- schedstat_schedule: Calls to schedule().
- schedstat_schedule_idle: Calls to schedule() leaving the CPU idle.
- schedstat_wake: Calls to try_to_wake_up().
- schedstat_wake_local: Calls to try_to_wake_up() for the local CPU.
- schedstat_runtime: Task runtime on this CPU in nanoseconds.
- schedstat_wait: Task runqueue wait time on this CPU in nanoseconds.
- schedstat_timeslices: Number of timeslices run on this CPU.
Because /proc/schedstat reports per-CPU runqueue counters, reject
per-process and cgroup modes, exclude schedstat events from
perf_pmu__reads_only_on_cpu_idx0(), and update should_skip_zero_counter()
so zero-valued per-CPU tool events are not suppressed on CPUs > 0. Track
initial and accumulated values across enable/disable transitions to
report deltas over the measurement interval.
Example system-wide and per-CPU output:
$ perf stat -a -e schedstat_yield,schedstat_schedule \
-e schedstat_runtime,schedstat_wait,schedstat_timeslices sleep 0.1
Performance counter stats for 'system wide':
0 schedstat_yield
0 schedstat_schedule
455,566,105 schedstat_runtime
348,262 schedstat_wait
63,336 schedstat_timeslices
0.112807668 seconds time elapsed
$ perf stat -A -C 0,1 -e schedstat_schedule,schedstat_runtime \
-e schedstat_wait,schedstat_timeslices sleep 0.1
Performance counter stats for 'CPU(s) 0,1':
CPU0 0 tool/schedstat_schedule/
CPU1 0 tool/schedstat_schedule/
CPU0 6,217,341 tool/schedstat_runtime/
CPU1 25,243,949 tool/schedstat_runtime/
CPU0 11,005 tool/schedstat_wait/
CPU1 20,921 tool/schedstat_wait/
CPU0 115 tool/schedstat_timeslices/
CPU1 3,535 tool/schedstat_timeslices/
0.101808548 seconds time elapsed
Signed-off-by: Ian Rogers <irogers@google.com>
---
.../pmu-events/arch/common/common/tool.json | 48 ++++
tools/perf/pmu-events/empty-pmu-events.c | 254 ++++++++++--------
tools/perf/util/pmu.c | 4 +-
tools/perf/util/stat-display.c | 8 +-
tools/perf/util/tool_pmu.c | 133 ++++++++-
tools/perf/util/tool_pmu.h | 9 +
6 files changed, 340 insertions(+), 116 deletions(-)
diff --git a/tools/perf/pmu-events/arch/common/common/tool.json b/tools/perf/pmu-events/arch/common/common/tool.json
index a332cbf842f7..7c6e03055ca3 100644
--- a/tools/perf/pmu-events/arch/common/common/tool.json
+++ b/tools/perf/pmu-events/arch/common/common/tool.json
@@ -334,5 +334,53 @@
"EventName": "net_tx_compressed",
"BriefDescription": "System-wide network transmitted compressed packets",
"ConfigCode": "56"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_yield",
+ "BriefDescription": "Number of times sched_yield() was called",
+ "ConfigCode": "57"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_schedule",
+ "BriefDescription": "Number of times schedule() was called",
+ "ConfigCode": "58"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_schedule_idle",
+ "BriefDescription": "Number of times schedule() left the processor idle",
+ "ConfigCode": "59"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_wake",
+ "BriefDescription": "Number of times try_to_wake_up() was called",
+ "ConfigCode": "60"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_wake_local",
+ "BriefDescription": "Number of times try_to_wake_up() was called to wake up the local cpu",
+ "ConfigCode": "61"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_runtime",
+ "BriefDescription": "Sum of all time spent running by tasks on this processor (in nanoseconds)",
+ "ConfigCode": "62"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_wait",
+ "BriefDescription": "Sum of all time spent waiting to run by tasks on this processor (in nanoseconds)",
+ "ConfigCode": "63"
+ },
+ {
+ "Unit": "tool",
+ "EventName": "schedstat_timeslices",
+ "BriefDescription": "Number of timeslices run on this cpu",
+ "ConfigCode": "64"
}
]
diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 8705f32563a6..49e2d3f8b3f1 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -2628,116 +2628,132 @@ static const char *const big_c_string =
/* offset=130002 */
"net_tx_compressed\000tool\000System-wide network transmitted compressed packets\000config=0x38\000\00000\000\000\000\000\000"
/* offset=130096 */
+"schedstat_yield\000tool\000Number of times sched_yield() was called\000config=0x39\000\00000\000\000\000\000\000"
+/* offset=130178 */
+"schedstat_schedule\000tool\000Number of times schedule() was called\000config=0x3a\000\00000\000\000\000\000\000"
+/* offset=130260 */
+"schedstat_schedule_idle\000tool\000Number of times schedule() left the processor idle\000config=0x3b\000\00000\000\000\000\000\000"
+/* offset=130360 */
+"schedstat_wake\000tool\000Number of times try_to_wake_up() was called\000config=0x3c\000\00000\000\000\000\000\000"
+/* offset=130444 */
+"schedstat_wake_local\000tool\000Number of times try_to_wake_up() was called to wake up the local cpu\000config=0x3d\000\00000\000\000\000\000\000"
+/* offset=130559 */
+"schedstat_runtime\000tool\000Sum of all time spent running by tasks on this processor (in nanoseconds)\000config=0x3e\000\00000\000\000\000\000\000"
+/* offset=130676 */
+"schedstat_wait\000tool\000Sum of all time spent waiting to run by tasks on this processor (in nanoseconds)\000config=0x3f\000\00000\000\000\000\000\000"
+/* offset=130797 */
+"schedstat_timeslices\000tool\000Number of timeslices run on this cpu\000config=0x40\000\00000\000\000\000\000\000"
+/* offset=130880 */
"bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000\000\000\000"
-/* offset=130158 */
+/* offset=130942 */
"bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000\000\000\000"
-/* offset=130220 */
+/* offset=131004 */
"l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\000\000Attributable Level 3 cache access, read\000"
-/* offset=130318 */
+/* offset=131102 */
"segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000\000\000\000"
-/* offset=130420 */
+/* offset=131204 */
"dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000\000\000\000"
-/* offset=130553 */
+/* offset=131337 */
"eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000\000\000\000"
-/* offset=130671 */
+/* offset=131455 */
"hisi_sccl,ddrc\000"
-/* offset=130686 */
+/* offset=131470 */
"uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000\000\000\000\000"
-/* offset=130756 */
+/* offset=131540 */
"uncore_cbox\000"
-/* offset=130768 */
+/* offset=131552 */
"unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000\000\000\000\000"
-/* offset=130922 */
+/* offset=131706 */
"event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000\000"
-/* offset=130976 */
+/* offset=131760 */
"event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000\000\000"
-/* offset=131034 */
+/* offset=131818 */
"hisi_sccl,l3c\000"
-/* offset=131048 */
+/* offset=131832 */
"uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000\000\000\000\000"
-/* offset=131116 */
+/* offset=131900 */
"uncore_imc_free_running\000"
-/* offset=131140 */
+/* offset=131924 */
"uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000\000\000\000\000"
-/* offset=131220 */
+/* offset=132004 */
"uncore_imc\000"
-/* offset=131231 */
+/* offset=132015 */
"uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\000\000\000\000"
-/* offset=131296 */
+/* offset=132080 */
"uncore_sys_ddr_pmu\000"
-/* offset=131315 */
+/* offset=132099 */
"sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000\000\000\000"
-/* offset=131391 */
+/* offset=132175 */
"uncore_sys_ccn_pmu\000"
-/* offset=131410 */
+/* offset=132194 */
"sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000\000\000\000"
-/* offset=131487 */
+/* offset=132271 */
"uncore_sys_cmn_pmu\000"
-/* offset=131506 */
+/* offset=132290 */
"sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000\000\000\000"
-/* offset=131649 */
+/* offset=132433 */
"CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@) / (duration_time * 1e9)\000\000Average CPU utilization\000\0001CPUs\000\000\000\000011"
-/* offset=131835 */
+/* offset=132619 */
"cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switches@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Context switches per CPU second\000\0001cs/sec\000\000\000\000011"
-/* offset=132068 */
+/* offset=132852 */
"migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-migrations@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Process migrations to a new CPU per CPU second\000\0001migrations/sec\000\000\000\000011"
-/* offset=132328 */
+/* offset=133112 */
"page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faults@ * 1e9 / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Page faults per CPU second\000\0001faults/sec\000\000\000\000011"
-/* offset=132559 */
+/* offset=133343 */
"insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\000Instructions Per Cycle\000\0001instructions\000\000\000\000001"
-/* offset=132672 */
+/* offset=133456 */
"stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, stalled\\-cycles\\-backend) / instructions if has_event(stalled\\-cycles\\-frontend) & has_event(stalled\\-cycles\\-backend) else (stalled\\-cycles\\-frontend / instructions if has_event(stalled\\-cycles\\-frontend) else (stalled\\-cycles\\-backend / instructions if has_event(stalled\\-cycles\\-backend) else 0)))\000\000Max front or backend stalls per instruction\000\000\000\000\000\000001"
-/* offset=133097 */
+/* offset=133881 */
"frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles if has_event(stalled\\-cycles\\-frontend) else 0)\000frontend_cycles_idle > 0.1\000Frontend stalls per cycle\000\000\000\000\000\000001"
-/* offset=133276 */
+/* offset=134060 */
"backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if has_event(stalled\\-cycles\\-backend) else 0)\000backend_cycles_idle > 0.2\000Backend stalls per cycle\000\000\000\000\000\000001"
-/* offset=133450 */
+/* offset=134234 */
"cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Cycles per CPU second\000\0001GHz\000\000\000\000011"
-/* offset=133626 */
+/* offset=134410 */
"branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-clock@ if #target_cpu else software@task\\-clock\\,name\\=task\\-clock@)\000\000Branches per CPU second\000\0001000M/sec\000\000\000\000011"
-/* offset=133806 */
+/* offset=134590 */
"branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > 0.05\000Branch miss rate\000\000100%\000\000\000\000001"
-/* offset=133910 */
+/* offset=134694 */
"l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\000l1d_miss_rate > 0.05\000L1D miss rate\000\000100%\000\000\000\000001"
-/* offset=134026 */
+/* offset=134810 */
"llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate > 0.05\000LLC miss rate\000\000100%\000\000\000\000001"
-/* offset=134127 */
+/* offset=134911 */
"l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\000l1i_miss_rate > 0.05\000L1I miss rate\000\000100%\000\000\000\000001"
-/* offset=134242 */
+/* offset=135026 */
"dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_rate > 0.05\000dTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=134348 */
+/* offset=135132 */
"itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_rate > 0.05\000iTLB miss rate\000\000100%\000\000\000\000001"
-/* offset=134454 */
+/* offset=135238 */
"l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcache\\-prefetches\000l1_prefetch_miss_rate > 0.05\000L1 prefetch miss rate\000\000100%\000\000\000\000001"
-/* offset=134602 */
+/* offset=135386 */
"CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000"
-/* offset=134625 */
+/* offset=135409 */
"IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\000000"
-/* offset=134689 */
+/* offset=135473 */
"Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\000000"
-/* offset=134856 */
+/* offset=135640 */
"dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=134921 */
+/* offset=135705 */
"icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\000000"
-/* offset=134989 */
+/* offset=135773 */
"cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\000000"
-/* offset=135061 */
+/* offset=135845 */
"DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\000000"
-/* offset=135156 */
+/* offset=135940 */
"DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\000000"
-/* offset=135291 */
+/* offset=136075 */
"DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\000000"
-/* offset=135356 */
+/* offset=136140 */
"DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=135425 */
+/* offset=136209 */
"DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\000000"
-/* offset=135496 */
+/* offset=136280 */
"M1\000\000ipc + M2\000\000\000\000\000\000\000\000000"
-/* offset=135519 */
+/* offset=136303 */
"M2\000\000ipc + M1\000\000\000\000\000\000\000\000000"
-/* offset=135542 */
+/* offset=136326 */
"M3\000\0001 / M3\000\000\000\000\000\000\000\000000"
-/* offset=135563 */
+/* offset=136347 */
"L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\000000"
;
@@ -5336,6 +5352,22 @@ static const struct compact_pmu_event pmu_events__common_tool[] = {
{ 125728 },
/* num_packages\000tool\000Number of packages. Each package has 1 or more die\000co... */
{ 125804 },
+ /* schedstat_runtime\000tool\000Sum of all time spent running by tasks on this proc... */
+ { 130559 },
+ /* schedstat_schedule\000tool\000Number of times schedule() was called\000config=0x... */
+ { 130178 },
+ /* schedstat_schedule_idle\000tool\000Number of times schedule() left the processor... */
+ { 130260 },
+ /* schedstat_timeslices\000tool\000Number of timeslices run on this cpu\000config=0... */
+ { 130797 },
+ /* schedstat_wait\000tool\000Sum of all time spent waiting to run by tasks on this ... */
+ { 130676 },
+ /* schedstat_wake\000tool\000Number of times try_to_wake_up() was called\000config=... */
+ { 130360 },
+ /* schedstat_wake_local\000tool\000Number of times try_to_wake_up() was called to w... */
+ { 130444 },
+ /* schedstat_yield\000tool\000Number of times sched_yield() was called\000config=0x... */
+ { 130096 },
/* slots\000tool\000Number of functional units that in parallel can execute parts o... */
{ 125890 },
/* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enabl... */
@@ -5371,39 +5403,39 @@ static const struct pmu_table_entry pmu_events__common[] = {
static const struct compact_pmu_event pmu_metrics__common_default_core[] = {
/* CPUs_utilized\000Default\000(software@cpu\\-clock\\,name\\=cpu\\-clock@ if #targ... */
- { 131649 },
+ { 132433 },
/* backend_cycles_idle\000Default\000(stalled\\-cycles\\-backend / cpu\\-cycles if ... */
- { 133276 },
+ { 134060 },
/* branch_frequency\000Default\000branches / (software@cpu\\-clock\\,name\\=cpu\\-c... */
- { 133626 },
+ { 134410 },
/* branch_miss_rate\000Default\000branch\\-misses / branches\000branch_miss_rate > ... */
- { 133806 },
+ { 134590 },
/* cs_per_second\000Default\000software@context\\-switches\\,name\\=context\\-switc... */
- { 131835 },
+ { 132619 },
/* cycles_frequency\000Default\000cpu\\-cycles / (software@cpu\\-clock\\,name\\=cpu... */
- { 133450 },
+ { 134234 },
/* dtlb_miss_rate\000Default3\000dTLB\\-load\\-misses / dTLB\\-loads\000dtlb_miss_r... */
- { 134242 },
+ { 135026 },
/* frontend_cycles_idle\000Default\000(stalled\\-cycles\\-frontend / cpu\\-cycles i... */
- { 133097 },
+ { 133881 },
/* insn_per_cycle\000Default\000instructions / cpu\\-cycles\000insn_per_cycle < 1\0... */
- { 132559 },
+ { 133343 },
/* itlb_miss_rate\000Default3\000iTLB\\-load\\-misses / iTLB\\-loads\000itlb_miss_r... */
- { 134348 },
+ { 135132 },
/* l1_prefetch_miss_rate\000Default4\000L1\\-dcache\\-prefetch\\-misses / L1\\-dcac... */
- { 134454 },
+ { 135238 },
/* l1d_miss_rate\000Default2\000L1\\-dcache\\-load\\-misses / L1\\-dcache\\-loads\0... */
- { 133910 },
+ { 134694 },
/* l1i_miss_rate\000Default3\000L1\\-icache\\-load\\-misses / L1\\-icache\\-loads\0... */
- { 134127 },
+ { 134911 },
/* llc_miss_rate\000Default2\000LLC\\-load\\-misses / LLC\\-loads\000llc_miss_rate ... */
- { 134026 },
+ { 134810 },
/* migrations_per_second\000Default\000software@cpu\\-migrations\\,name\\=cpu\\-mig... */
- { 132068 },
+ { 132852 },
/* page_faults_per_second\000Default\000software@page\\-faults\\,name\\=page\\-faul... */
- { 132328 },
+ { 133112 },
/* stalled_cycles_per_instruction\000Default\000(max(stalled\\-cycles\\-frontend, s... */
- { 132672 },
+ { 133456 },
};
@@ -5417,41 +5449,41 @@ static const struct pmu_table_entry pmu_metrics__common[] = {
static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = {
/* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000... */
- { 130096 },
+ { 130880 },
/* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000... */
- { 130158 },
+ { 130942 },
/* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispat... */
- { 130420 },
+ { 131204 },
/* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) t... */
- { 130553 },
+ { 131337 },
/* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000\000\00... */
- { 130220 },
+ { 131004 },
/* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,pe... */
- { 130318 },
+ { 131102 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = {
/* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000... */
- { 130686 },
+ { 131470 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = {
/* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\0... */
- { 131048 },
+ { 131832 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = {
/* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000\000\000\000... */
- { 130922 },
+ { 131706 },
/* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000\000\000... */
- { 130976 },
+ { 131760 },
/* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted fro... */
- { 130768 },
+ { 131552 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = {
/* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000\... */
- { 131231 },
+ { 132015 },
};
static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = {
/* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12... */
- { 131140 },
+ { 131924 },
};
@@ -5464,61 +5496,61 @@ static const struct pmu_table_entry pmu_events__test_soc_cpu[] = {
{
.entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc),
- .pmu_name = { 130671 /* hisi_sccl,ddrc\000 */ },
+ .pmu_name = { 131455 /* hisi_sccl,ddrc\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_hisi_sccl_l3c,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c),
- .pmu_name = { 131034 /* hisi_sccl,l3c\000 */ },
+ .pmu_name = { 131818 /* hisi_sccl,l3c\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_uncore_cbox,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox),
- .pmu_name = { 130756 /* uncore_cbox\000 */ },
+ .pmu_name = { 131540 /* uncore_cbox\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_uncore_imc,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc),
- .pmu_name = { 131220 /* uncore_imc\000 */ },
+ .pmu_name = { 132004 /* uncore_imc\000 */ },
},
{
.entries = pmu_events__test_soc_cpu_uncore_imc_free_running,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running),
- .pmu_name = { 131116 /* uncore_imc_free_running\000 */ },
+ .pmu_name = { 131900 /* uncore_imc_free_running\000 */ },
},
};
static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = {
/* CPI\000\0001 / IPC\000\000\000\000\000\000\000\000000 */
- { 134602 },
+ { 135386 },
/* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000... */
- { 135291 },
+ { 136075 },
/* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqs... */
- { 135061 },
+ { 135845 },
/* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data... */
- { 135156 },
+ { 135940 },
/* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000... */
- { 135356 },
+ { 136140 },
/* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\0... */
- { 135425 },
+ { 136209 },
/* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.t... */
- { 134689 },
+ { 135473 },
/* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\... */
- { 134625 },
+ { 135409 },
/* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\... */
- { 135563 },
+ { 136347 },
/* M1\000\000ipc + M2\000\000\000\000\000\000\000\000000 */
- { 135496 },
+ { 136280 },
/* M2\000\000ipc + M1\000\000\000\000\000\000\000\000000 */
- { 135519 },
+ { 136303 },
/* M3\000\0001 / M3\000\000\000\000\000\000\000\000000 */
- { 135542 },
+ { 136326 },
/* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\... */
- { 134989 },
+ { 135773 },
/* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\0... */
- { 134856 },
+ { 135640 },
/* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\00... */
- { 134921 },
+ { 135705 },
};
@@ -5532,15 +5564,15 @@ static const struct pmu_table_entry pmu_metrics__test_soc_cpu[] = {
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = {
/* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x0... */
- { 131410 },
+ { 132194 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = {
/* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first looku... */
- { 131506 },
+ { 132290 },
};
static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = {
/* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8... */
- { 131315 },
+ { 132099 },
};
@@ -5548,17 +5580,17 @@ static const struct pmu_table_entry pmu_events__test_soc_sys[] = {
{
.entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu),
- .pmu_name = { 131391 /* uncore_sys_ccn_pmu\000 */ },
+ .pmu_name = { 132175 /* uncore_sys_ccn_pmu\000 */ },
},
{
.entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu),
- .pmu_name = { 131487 /* uncore_sys_cmn_pmu\000 */ },
+ .pmu_name = { 132271 /* uncore_sys_cmn_pmu\000 */ },
},
{
.entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu,
.num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu),
- .pmu_name = { 131296 /* uncore_sys_ddr_pmu\000 */ },
+ .pmu_name = { 132080 /* uncore_sys_ddr_pmu\000 */ },
},
};
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 01753d5c69d1..f4560a0ec1db 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2830,5 +2830,7 @@ bool perf_pmu__reads_only_on_cpu_idx0(const struct perf_event_attr *attr)
return false;
event = (enum tool_pmu_event)attr->config;
- return event != TOOL_PMU__EVENT_USER_TIME && event != TOOL_PMU__EVENT_SYSTEM_TIME;
+ return event != TOOL_PMU__EVENT_USER_TIME &&
+ event != TOOL_PMU__EVENT_SYSTEM_TIME &&
+ !tool_pmu__is_sched_stat_event(event);
}
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
index b337cc23f413..6671403c587c 100644
--- a/tools/perf/util/stat-display.c
+++ b/tools/perf/util/stat-display.c
@@ -929,9 +929,13 @@ static bool should_skip_zero_counter(struct perf_stat_config *config,
* system_time, but for many the first index is the only one used, for
* example num_cores. Don't skip for the first index.
*/
- if (evsel__is_tool(counter)) {
+ if (evsel__is_tool(counter) &&
+ (counter->core.reads_only_on_cpu_idx0 || counter->pid_stat)) {
+ struct perf_cpu first_cpu = perf_cpu_map__cpu(counter->core.cpus, 0);
struct aggr_cpu_id own_id =
- config->aggr_get_id(config, (struct perf_cpu){ .cpu = 0 });
+ config->aggr_get_id(config,
+ first_cpu.cpu >= 0 ? first_cpu
+ : (struct perf_cpu){ .cpu = 0 });
return !aggr_cpu_id__equal(id, &own_id);
}
diff --git a/tools/perf/util/tool_pmu.c b/tools/perf/util/tool_pmu.c
index 655b22104320..b92aaf0d7671 100644
--- a/tools/perf/util/tool_pmu.c
+++ b/tools/perf/util/tool_pmu.c
@@ -84,6 +84,14 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
"net_tx_colls",
"net_tx_carrier",
"net_tx_compressed",
+ "schedstat_yield",
+ "schedstat_schedule",
+ "schedstat_schedule_idle",
+ "schedstat_wake",
+ "schedstat_wake_local",
+ "schedstat_runtime",
+ "schedstat_wait",
+ "schedstat_timeslices",
};
bool tool_pmu__skip_event(const char *name __maybe_unused)
@@ -205,6 +213,83 @@ static int read_stat_field(int fd, struct perf_cpu cpu, int field, __u64 *val)
return -EINVAL;
}
+bool tool_pmu__is_sched_stat_event(enum tool_pmu_event ev)
+{
+ return ev >= TOOL_PMU__EVENT_SCHEDSTAT_YIELD &&
+ ev <= TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES;
+}
+
+static int sched_stat_event_to_field(enum tool_pmu_event ev)
+{
+ if (!tool_pmu__is_sched_stat_event(ev))
+ return -EINVAL;
+ if (ev == TOOL_PMU__EVENT_SCHEDSTAT_YIELD)
+ return 1;
+ /* Field 2 is legacy 0 in /proc/schedstat v15+. */
+ return (ev - TOOL_PMU__EVENT_SCHEDSTAT_YIELD) + 2;
+}
+
+static int read_sched_stat(int fd, struct perf_cpu cpu, enum tool_pmu_event ev, __u64 *val)
+{
+ int field = sched_stat_event_to_field(ev);
+ char buf[4096];
+ struct io io;
+ int ch;
+
+ if (field < 0)
+ return field;
+
+ io__init(&io, fd, buf, sizeof(buf));
+ lseek(fd, 0, SEEK_SET);
+
+ /* Search for "cpu<N> " */
+ while ((ch = io__get_char(&io)) != -1) {
+ __u64 cpu_num;
+ int i = 1, c;
+
+ if (ch != 'c') {
+ if (ch != '\n')
+ read_until_char(&io, '\n');
+ continue;
+ }
+ c = io__get_char(&io);
+ if (c != 'p') {
+ if (c != '\n' && c != -1)
+ read_until_char(&io, '\n');
+ continue;
+ }
+ c = io__get_char(&io);
+ if (c != 'u') {
+ if (c != '\n' && c != -1)
+ read_until_char(&io, '\n');
+ continue;
+ }
+ c = io__get_dec(&io, &cpu_num);
+ if (c != ' ' || (int)cpu_num != cpu.cpu) {
+ if (c != '\n' && c != -1)
+ read_until_char(&io, '\n');
+ continue;
+ }
+
+ /* Found our CPU. Now read the field. */
+ while (true) {
+ __u64 v;
+ int sep = io__get_dec(&io, &v);
+
+ if (sep < 0)
+ return -EINVAL;
+ if (i == field) {
+ *val = v;
+ return 0;
+ }
+ if (sep == '\n')
+ return -EINVAL; /* Field not found on line */
+ i++;
+ }
+ }
+ return -EINVAL;
+}
+
static int read_pid_stat_field(int fd, int field, __u64 *val)
{
char buf[256];
@@ -303,6 +388,14 @@ static const char *tool_pmu__memory_event_to_key(enum tool_pmu_event ev)
case TOOL_PMU__EVENT_NET_TX_COLLS:
case TOOL_PMU__EVENT_NET_TX_CARRIER:
case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
+ case TOOL_PMU__EVENT_SCHEDSTAT_YIELD:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL:
+ case TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAIT:
+ case TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
case TOOL_PMU__EVENT_SYSTEM_TIME:
@@ -477,7 +570,8 @@ static bool tool_pmu__has_start_times(enum tool_pmu_event ev)
{
return ev == TOOL_PMU__EVENT_USER_TIME ||
ev == TOOL_PMU__EVENT_SYSTEM_TIME ||
- tool_pmu__is_net_event(ev);
+ tool_pmu__is_net_event(ev) ||
+ tool_pmu__is_sched_stat_event(ev);
}
static int read_net_dev_col(struct io *io, __u64 *val, int *term)
@@ -609,6 +703,16 @@ static int tool_pmu__read_stat(struct evsel *evsel, int cpu_map_idx, int thread,
return 0;
}
+ if (tool_pmu__is_sched_stat_event(ev)) {
+ if (thread == 0) {
+ struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, cpu_map_idx);
+
+ return read_sched_stat(fd, cpu, ev, val);
+ }
+ *val = 0;
+ return 0;
+ }
+
lseek(fd, 0, SEEK_SET);
if (evsel->pid_stat) {
if (cpu_map_idx == 0)
@@ -702,6 +806,15 @@ static int evsel__tool_pmu_open_one(struct evsel *evsel, enum tool_pmu_event ev,
if (fd < 0)
return -errno;
}
+ } else if (tool_pmu__is_sched_stat_event(ev)) {
+ if (pid > -1 || evsel->cgrp)
+ return -EINVAL;
+ if (thread == 0) {
+ snprintf(buf, sizeof(buf), "%s/schedstat", procfs__mountpoint());
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+ }
} else {
if (pid > -1) {
snprintf(buf, sizeof(buf), "%s/%d/stat", procfs__mountpoint(), pid);
@@ -1005,6 +1118,14 @@ bool tool_pmu__read_event(enum tool_pmu_event ev,
case TOOL_PMU__EVENT_NET_TX_COLLS:
case TOOL_PMU__EVENT_NET_TX_CARRIER:
case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
+ case TOOL_PMU__EVENT_SCHEDSTAT_YIELD:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL:
+ case TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAIT:
+ case TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES:
case TOOL_PMU__EVENT_NONE:
case TOOL_PMU__EVENT_DURATION_TIME:
case TOOL_PMU__EVENT_USER_TIME:
@@ -1261,7 +1382,15 @@ int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread)
case TOOL_PMU__EVENT_NET_TX_FIFO:
case TOOL_PMU__EVENT_NET_TX_COLLS:
case TOOL_PMU__EVENT_NET_TX_CARRIER:
- case TOOL_PMU__EVENT_NET_TX_COMPRESSED: {
+ case TOOL_PMU__EVENT_NET_TX_COMPRESSED:
+ case TOOL_PMU__EVENT_SCHEDSTAT_YIELD:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL:
+ case TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME:
+ case TOOL_PMU__EVENT_SCHEDSTAT_WAIT:
+ case TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES: {
__u64 *accumulated_ptr = evsel->process_time.accumulated_times ?
xyarray__entry(evsel->process_time.accumulated_times, cpu_map_idx, thread) :
NULL;
diff --git a/tools/perf/util/tool_pmu.h b/tools/perf/util/tool_pmu.h
index f972995bb8ed..5a290a9e7555 100644
--- a/tools/perf/util/tool_pmu.h
+++ b/tools/perf/util/tool_pmu.h
@@ -66,6 +66,14 @@ enum tool_pmu_event {
TOOL_PMU__EVENT_NET_TX_COLLS,
TOOL_PMU__EVENT_NET_TX_CARRIER,
TOOL_PMU__EVENT_NET_TX_COMPRESSED,
+ TOOL_PMU__EVENT_SCHEDSTAT_YIELD,
+ TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE,
+ TOOL_PMU__EVENT_SCHEDSTAT_SCHEDULE_IDLE,
+ TOOL_PMU__EVENT_SCHEDSTAT_WAKE,
+ TOOL_PMU__EVENT_SCHEDSTAT_WAKE_LOCAL,
+ TOOL_PMU__EVENT_SCHEDSTAT_RUNTIME,
+ TOOL_PMU__EVENT_SCHEDSTAT_WAIT,
+ TOOL_PMU__EVENT_SCHEDSTAT_TIMESLICES,
TOOL_PMU__EVENT_MAX,
};
@@ -77,6 +85,7 @@ const char *tool_pmu__event_to_str(enum tool_pmu_event ev);
enum tool_pmu_event tool_pmu__str_to_event(const char *str);
bool tool_pmu__skip_event(const char *name);
int tool_pmu__num_skip_events(void);
+bool tool_pmu__is_sched_stat_event(enum tool_pmu_event ev);
bool tool_pmu__read_event(enum tool_pmu_event ev,
struct evsel *evsel,
--
2.56.1.703.gf848ed807c-goog
next prev parent reply other threads:[~2026-11-13 23:37 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 23:37 [PATCH v2 0/4] perf tool_pmu: Add procfs memory, network and " Ian Rogers
2026-11-13 23:37 ` [PATCH v2 1/4] perf tool_pmu: Add memory events Ian Rogers
2026-11-13 23:37 ` [PATCH v2 2/4] perf tool_pmu: Add network events Ian Rogers
2026-11-13 23:37 ` Ian Rogers [this message]
2026-11-13 23:37 ` [PATCH v2 4/4] perf test tool_pmu: Add memory, network and schedstat tests Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113233739.3626499-4-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=thomas.falcon@intel.com \
--cc=tmricht@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®