^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * builtin-timechart.c - make an svg timechart of system activity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) Copyright 2009 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Arjan van de Ven <arjan@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "builtin.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "util/color.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "util/evlist.h" // for struct evsel_str_handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "util/evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/rbtree.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "util/symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "util/thread.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "util/callchain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "perf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "util/header.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <subcmd/pager.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <subcmd/parse-options.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "util/parse-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "util/event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "util/session.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "util/svghelper.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include "util/tool.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include "util/data.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include "util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) FILE *open_memstream(char **ptr, size_t *sizeloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SUPPORT_OLD_POWER_EVENTS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define PWR_EVENT_EXIT -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct per_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct power_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct wake_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct timechart {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct perf_tool tool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct per_pid *all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct power_event *power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct wake_event *wake_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int proc_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int numcpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u64 min_freq, /* Lowest CPU frequency seen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) max_freq, /* Highest CPU frequency seen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) turbo_frequency,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) first_time, last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) bool power_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) tasks_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) with_backtrace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) topology;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) bool force;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* IO related settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) bool io_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) skip_eagain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u64 io_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u64 min_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) merge_dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct per_pidcomm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct cpu_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct io_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Datastructure layout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * We keep an list of "pid"s, matching the kernels notion of a task struct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * Each "pid" entry, has a list of "comm"s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * this is because we want to track different programs different, while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * exec will reuse the original pid (by design).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * Each comm has a list of samples that will be used to draw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * final graph.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct per_pid {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct per_pid *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int ppid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u64 end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u64 total_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u64 total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int display;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct per_pidcomm *all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct per_pidcomm *current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct per_pidcomm {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct per_pidcomm *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u64 end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u64 total_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u64 max_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u64 total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int display;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) long state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u64 state_since;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) char *comm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct cpu_sample *samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct io_sample *io_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct sample_wrapper {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct sample_wrapper *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u64 timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned char data[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define TYPE_NONE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define TYPE_RUNNING 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define TYPE_WAITING 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define TYPE_BLOCKED 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct cpu_sample {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct cpu_sample *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u64 end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) const char *backtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) IOTYPE_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) IOTYPE_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) IOTYPE_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) IOTYPE_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) IOTYPE_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) IOTYPE_POLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct io_sample {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct io_sample *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u64 end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) u64 bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int merges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define CSTATE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define PSTATE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct power_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct power_event *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u64 start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) u64 end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct wake_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct wake_event *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int waker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int wakee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u64 time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) const char *backtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct process_filter {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct process_filter *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static struct process_filter *process_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static struct per_pid *find_create_pid(struct timechart *tchart, int pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct per_pid *cursor = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) while (cursor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (cursor->pid == pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) cursor = cursor->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) cursor = zalloc(sizeof(*cursor));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) assert(cursor != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) cursor->pid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) cursor->next = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) tchart->all_data = cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void pid_set_comm(struct timechart *tchart, int pid, char *comm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) p = find_create_pid(tchart, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (c->comm && strcmp(c->comm, comm) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) p->current = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!c->comm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) c->comm = strdup(comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) p->current = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) c = zalloc(sizeof(*c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) assert(c != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) c->comm = strdup(comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) p->current = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) c->next = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) p->all = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static void pid_fork(struct timechart *tchart, int pid, int ppid, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct per_pid *p, *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) p = find_create_pid(tchart, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pp = find_create_pid(tchart, ppid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) p->ppid = ppid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (pp->current && pp->current->comm && !p->current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pid_set_comm(tchart, pid, pp->current->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) p->start_time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (p->current && !p->current->start_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) p->current->start_time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) p->current->state_since = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static void pid_exit(struct timechart *tchart, int pid, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) p = find_create_pid(tchart, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) p->end_time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (p->current)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) p->current->end_time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void pid_put_sample(struct timechart *tchart, int pid, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned int cpu, u64 start, u64 end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct cpu_sample *sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) p = find_create_pid(tchart, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) c = p->current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) c = zalloc(sizeof(*c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) assert(c != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) p->current = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) c->next = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) p->all = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) sample = zalloc(sizeof(*sample));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) assert(sample != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) sample->start_time = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) sample->end_time = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) sample->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) sample->next = c->samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) sample->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) sample->backtrace = backtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) c->samples = sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (sample->type == TYPE_RUNNING && end > start && start > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) c->total_time += (end-start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) p->total_time += (end-start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (c->start_time == 0 || c->start_time > start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) c->start_time = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (p->start_time == 0 || p->start_time > start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) p->start_time = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #define MAX_CPUS 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static u64 cpus_cstate_start_times[MAX_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int cpus_cstate_state[MAX_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static u64 cpus_pstate_start_times[MAX_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static u64 cpus_pstate_state[MAX_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int process_comm_event(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct perf_sample *sample __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct machine *machine __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct timechart *tchart = container_of(tool, struct timechart, tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) pid_set_comm(tchart, event->comm.tid, event->comm.comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static int process_fork_event(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct perf_sample *sample __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct machine *machine __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct timechart *tchart = container_of(tool, struct timechart, tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) pid_fork(tchart, event->fork.pid, event->fork.ppid, event->fork.time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int process_exit_event(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct perf_sample *sample __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct machine *machine __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct timechart *tchart = container_of(tool, struct timechart, tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) pid_exit(tchart, event->fork.pid, event->fork.time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) #ifdef SUPPORT_OLD_POWER_EVENTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static int use_old_power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static void c_state_start(int cpu, u64 timestamp, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) cpus_cstate_start_times[cpu] = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) cpus_cstate_state[cpu] = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static void c_state_end(struct timechart *tchart, int cpu, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct power_event *pwr = zalloc(sizeof(*pwr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (!pwr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) pwr->state = cpus_cstate_state[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) pwr->start_time = cpus_cstate_start_times[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pwr->end_time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pwr->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) pwr->type = CSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) pwr->next = tchart->power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) tchart->power_events = pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void p_state_change(struct timechart *tchart, int cpu, u64 timestamp, u64 new_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct power_event *pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (new_freq > 8000000) /* detect invalid data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pwr = zalloc(sizeof(*pwr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!pwr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pwr->state = cpus_pstate_state[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) pwr->start_time = cpus_pstate_start_times[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) pwr->end_time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) pwr->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) pwr->type = PSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) pwr->next = tchart->power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (!pwr->start_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) pwr->start_time = tchart->first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tchart->power_events = pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) cpus_pstate_state[cpu] = new_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) cpus_pstate_start_times[cpu] = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if ((u64)new_freq > tchart->max_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) tchart->max_freq = new_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (new_freq < tchart->min_freq || tchart->min_freq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) tchart->min_freq = new_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (new_freq == tchart->max_freq - 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) tchart->turbo_frequency = tchart->max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int waker, int wakee, u8 flags, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct wake_event *we = zalloc(sizeof(*we));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (!we)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) we->time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) we->waker = waker;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) we->backtrace = backtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) we->waker = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) we->wakee = wakee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) we->next = tchart->wake_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) tchart->wake_events = we;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) p = find_create_pid(tchart, we->wakee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (p && p->current && p->current->state == TYPE_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) p->current->state_since = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) p->current->state = TYPE_WAITING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (p && p->current && p->current->state == TYPE_BLOCKED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) pid_put_sample(tchart, p->pid, p->current->state, cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) p->current->state_since, timestamp, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) p->current->state_since = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) p->current->state = TYPE_WAITING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int prev_pid, int next_pid, u64 prev_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct per_pid *p = NULL, *prev_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) prev_p = find_create_pid(tchart, prev_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) p = find_create_pid(tchart, next_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (prev_p->current && prev_p->current->state != TYPE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) pid_put_sample(tchart, prev_pid, TYPE_RUNNING, cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) prev_p->current->state_since, timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (p && p->current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (p->current->state != TYPE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) pid_put_sample(tchart, next_pid, p->current->state, cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) p->current->state_since, timestamp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) p->current->state_since = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) p->current->state = TYPE_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (prev_p->current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) prev_p->current->state = TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) prev_p->current->state_since = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (prev_state & 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) prev_p->current->state = TYPE_BLOCKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (prev_state == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) prev_p->current->state = TYPE_WAITING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static const char *cat_backtrace(union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct addr_location al;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) char *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) size_t p_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) u8 cpumode = PERF_RECORD_MISC_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct addr_location tal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct ip_callchain *chain = sample->callchain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) FILE *f = open_memstream(&p, &p_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (!f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) perror("open_memstream error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!chain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (machine__resolve(machine, &al, sample) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) fprintf(stderr, "problem processing %d event, skipping it.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) event->header.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) for (i = 0; i < chain->nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) u64 ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (callchain_param.order == ORDER_CALLEE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ip = chain->ips[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ip = chain->ips[chain->nr - i - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (ip >= PERF_CONTEXT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) switch (ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case PERF_CONTEXT_HV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) cpumode = PERF_RECORD_MISC_HYPERVISOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case PERF_CONTEXT_KERNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) cpumode = PERF_RECORD_MISC_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) case PERF_CONTEXT_USER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) cpumode = PERF_RECORD_MISC_USER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pr_debug("invalid callchain context: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) "%"PRId64"\n", (s64) ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * It seems the callchain is corrupted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * Discard all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) zfree(&p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) goto exit_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) tal.filtered = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (thread__find_symbol(al.thread, cpumode, ip, &tal))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) fprintf(f, "..... %016" PRIx64 " %s\n", ip, tal.sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) fprintf(f, "..... %016" PRIx64 "\n", ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) exit_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) addr_location__put(&al);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) typedef int (*tracepoint_handler)(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) const char *backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static int process_sample_event(struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct machine *machine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct timechart *tchart = container_of(tool, struct timechart, tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (!tchart->first_time || tchart->first_time > sample->time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) tchart->first_time = sample->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (tchart->last_time < sample->time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) tchart->last_time = sample->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (evsel->handler != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) tracepoint_handler f = evsel->handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return f(tchart, evsel, sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) cat_backtrace(event, sample, machine));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) const char *backtrace __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) u32 state = evsel__intval(evsel, sample, "state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) u32 cpu_id = evsel__intval(evsel, sample, "cpu_id");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (state == (u32)PWR_EVENT_EXIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) c_state_end(tchart, cpu_id, sample->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) c_state_start(cpu_id, sample->time, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) process_sample_cpu_frequency(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) const char *backtrace __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) u32 state = evsel__intval(evsel, sample, "state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) u32 cpu_id = evsel__intval(evsel, sample, "cpu_id");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) p_state_change(tchart, cpu_id, sample->time, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) process_sample_sched_wakeup(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) u8 flags = evsel__intval(evsel, sample, "common_flags");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int waker = evsel__intval(evsel, sample, "common_pid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int wakee = evsel__intval(evsel, sample, "pid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) process_sample_sched_switch(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int prev_pid = evsel__intval(evsel, sample, "prev_pid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int next_pid = evsel__intval(evsel, sample, "next_pid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) u64 prev_state = evsel__intval(evsel, sample, "prev_state");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) prev_state, backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) #ifdef SUPPORT_OLD_POWER_EVENTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) process_sample_power_start(struct timechart *tchart __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) const char *backtrace __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) u64 cpu_id = evsel__intval(evsel, sample, "cpu_id");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) u64 value = evsel__intval(evsel, sample, "value");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) c_state_start(cpu_id, sample->time, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) process_sample_power_end(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct evsel *evsel __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) const char *backtrace __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) c_state_end(tchart, sample->cpu, sample->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) process_sample_power_frequency(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) const char *backtrace __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) u64 cpu_id = evsel__intval(evsel, sample, "cpu_id");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) u64 value = evsel__intval(evsel, sample, "value");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) p_state_change(tchart, cpu_id, sample->time, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) #endif /* SUPPORT_OLD_POWER_EVENTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * After the last sample we need to wrap up the current C/P state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * and close out each CPU for these.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void end_sample_processing(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) u64 cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct power_event *pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for (cpu = 0; cpu <= tchart->numcpus; cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* C state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) pwr = zalloc(sizeof(*pwr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!pwr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) pwr->state = cpus_cstate_state[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) pwr->start_time = cpus_cstate_start_times[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) pwr->end_time = tchart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) pwr->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) pwr->type = CSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) pwr->next = tchart->power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) tchart->power_events = pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* P state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) pwr = zalloc(sizeof(*pwr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (!pwr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pwr->state = cpus_pstate_state[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) pwr->start_time = cpus_pstate_start_times[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) pwr->end_time = tchart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) pwr->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) pwr->type = PSTATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) pwr->next = tchart->power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!pwr->start_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) pwr->start_time = tchart->first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!pwr->state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) pwr->state = tchart->min_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) tchart->power_events = pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static int pid_begin_io_sample(struct timechart *tchart, int pid, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) u64 start, int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) struct per_pid *p = find_create_pid(tchart, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct per_pidcomm *c = p->current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct io_sample *sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct io_sample *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) c = zalloc(sizeof(*c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) p->current = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) c->next = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) p->all = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) prev = c->io_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (prev && prev->start_time && !prev->end_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) pr_warning("Skip invalid start event: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) "previous event already started!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* remove previous event that has been started,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) * we are not sure we will ever get an end for it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) c->io_samples = prev->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) free(prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) sample = zalloc(sizeof(*sample));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) sample->start_time = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) sample->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) sample->fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) sample->next = c->io_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) c->io_samples = sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (c->start_time == 0 || c->start_time > start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) c->start_time = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) u64 end, long ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct per_pid *p = find_create_pid(tchart, pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) struct per_pidcomm *c = p->current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct io_sample *sample, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (!c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) pr_warning("Invalid pidcomm!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) sample = c->io_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!sample) /* skip partially captured events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (sample->end_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) pr_warning("Skip invalid end event: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) "previous event already ended!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (sample->type != type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) pr_warning("Skip invalid end event: invalid event type!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) sample->end_time = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) prev = sample->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* we want to be able to see small and fast transfers, so make them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * at least min_time long, but don't overlap them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (sample->end_time - sample->start_time < tchart->min_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) sample->end_time = sample->start_time + tchart->min_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (prev && sample->start_time < prev->end_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (prev->err) /* try to make errors more visible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) sample->start_time = prev->end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) prev->end_time = sample->start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) sample->err = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) } else if (type == IOTYPE_READ || type == IOTYPE_WRITE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) type == IOTYPE_TX || type == IOTYPE_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if ((u64)ret > c->max_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) c->max_bytes = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) c->total_bytes += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) p->total_bytes += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) sample->bytes = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* merge two requests to make svg smaller and render-friendly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (prev &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) prev->type == sample->type &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) prev->err == sample->err &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) prev->fd == sample->fd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) prev->end_time + tchart->merge_dist >= sample->start_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) sample->bytes += prev->bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) sample->merges += prev->merges + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) sample->start_time = prev->start_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) sample->next = prev->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) free(prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (!sample->err && sample->bytes > c->max_bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) c->max_bytes = sample->bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) tchart->io_events++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) process_enter_read(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) long fd = evsel__intval(evsel, sample, "fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return pid_begin_io_sample(tchart, sample->tid, IOTYPE_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) sample->time, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) process_exit_read(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) long ret = evsel__intval(evsel, sample, "ret");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return pid_end_io_sample(tchart, sample->tid, IOTYPE_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) sample->time, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) process_enter_write(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) long fd = evsel__intval(evsel, sample, "fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return pid_begin_io_sample(tchart, sample->tid, IOTYPE_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) sample->time, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) process_exit_write(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) long ret = evsel__intval(evsel, sample, "ret");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return pid_end_io_sample(tchart, sample->tid, IOTYPE_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) sample->time, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) process_enter_sync(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) long fd = evsel__intval(evsel, sample, "fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return pid_begin_io_sample(tchart, sample->tid, IOTYPE_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) sample->time, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) process_exit_sync(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) long ret = evsel__intval(evsel, sample, "ret");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return pid_end_io_sample(tchart, sample->tid, IOTYPE_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) sample->time, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) process_enter_tx(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) long fd = evsel__intval(evsel, sample, "fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return pid_begin_io_sample(tchart, sample->tid, IOTYPE_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) sample->time, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) process_exit_tx(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) long ret = evsel__intval(evsel, sample, "ret");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) return pid_end_io_sample(tchart, sample->tid, IOTYPE_TX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) sample->time, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) process_enter_rx(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) long fd = evsel__intval(evsel, sample, "fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return pid_begin_io_sample(tchart, sample->tid, IOTYPE_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) sample->time, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) process_exit_rx(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) long ret = evsel__intval(evsel, sample, "ret");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return pid_end_io_sample(tchart, sample->tid, IOTYPE_RX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) sample->time, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) process_enter_poll(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) long fd = evsel__intval(evsel, sample, "fd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return pid_begin_io_sample(tchart, sample->tid, IOTYPE_POLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) sample->time, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) process_exit_poll(struct timechart *tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct evsel *evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) long ret = evsel__intval(evsel, sample, "ret");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) return pid_end_io_sample(tchart, sample->tid, IOTYPE_POLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) sample->time, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * Sort the pid datastructure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) static void sort_pids(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct per_pid *new_list, *p, *cursor, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* sort by ppid first, then by pid, lowest to highest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) new_list = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) while (tchart->all_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) tchart->all_data = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) p->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (new_list == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) new_list = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) p->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) cursor = new_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) while (cursor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (cursor->ppid > p->ppid ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) (cursor->ppid == p->ppid && cursor->pid > p->pid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* must insert before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) if (prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) p->next = prev->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) prev->next = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) cursor = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) p->next = new_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) new_list = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) cursor = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) prev = cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) cursor = cursor->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (!cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) prev->next = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) tchart->all_data = new_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static void draw_c_p_states(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct power_event *pwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) pwr = tchart->power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * two pass drawing so that the P state bars are on top of the C state blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) while (pwr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (pwr->type == CSTATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) pwr = pwr->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) pwr = tchart->power_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) while (pwr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (pwr->type == PSTATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (!pwr->state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) pwr->state = tchart->min_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) pwr = pwr->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) static void draw_wakeups(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) struct wake_event *we;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) we = tchart->wake_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) while (we) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) int from = 0, to = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) char *task_from = NULL, *task_to = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /* locate the column of the waker and wakee */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (p->pid == we->waker || p->pid == we->wakee) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (p->pid == we->waker && !from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) from = c->Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) task_from = strdup(c->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (p->pid == we->wakee && !to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) to = c->Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) task_to = strdup(c->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (p->pid == we->waker && !from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) from = c->Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) task_from = strdup(c->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (p->pid == we->wakee && !to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) to = c->Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) task_to = strdup(c->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (!task_from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) task_from = malloc(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) sprintf(task_from, "[%i]", we->waker);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (!task_to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) task_to = malloc(40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) sprintf(task_to, "[%i]", we->wakee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (we->waker == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) svg_interrupt(we->time, to, we->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) else if (from && to && abs(from - to) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) svg_wakeline(we->time, from, to, we->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) svg_partial_wakeline(we->time, from, task_from, to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) task_to, we->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) we = we->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) free(task_from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) free(task_to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static void draw_cpu_usage(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct cpu_sample *sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) sample = c->samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) while (sample) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (sample->type == TYPE_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) svg_process(sample->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) p->pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) c->comm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) sample->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) sample = sample->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) static void draw_io_bars(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) const char *suf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) double bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) char comm[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct io_sample *sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) int Y = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (!c->display) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) c->Y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) svg_box(Y, c->start_time, c->end_time, "process3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) sample = c->io_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) for (sample = c->io_samples; sample; sample = sample->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) double h = (double)sample->bytes / c->max_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (tchart->skip_eagain &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) sample->err == -EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (sample->err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) h = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (sample->type == IOTYPE_SYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) svg_fbox(Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) sample->err ? "error" : "sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) sample->fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) sample->err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) sample->merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) else if (sample->type == IOTYPE_POLL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) svg_fbox(Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) sample->err ? "error" : "poll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) sample->fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) sample->err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) sample->merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) else if (sample->type == IOTYPE_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) svg_ubox(Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) sample->err ? "error" : "disk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) sample->fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) sample->err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) sample->merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) else if (sample->type == IOTYPE_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) svg_lbox(Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) sample->err ? "error" : "disk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) sample->fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) sample->err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) sample->merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) else if (sample->type == IOTYPE_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) svg_ubox(Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) sample->err ? "error" : "net",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) sample->fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) sample->err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) sample->merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) else if (sample->type == IOTYPE_TX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) svg_lbox(Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) sample->err ? "error" : "net",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) sample->fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) sample->err,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) sample->merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) suf = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) bytes = c->total_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (bytes > 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) bytes = bytes / 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) suf = "K";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (bytes > 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) bytes = bytes / 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) suf = "M";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (bytes > 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) bytes = bytes / 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) suf = "G";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) sprintf(comm, "%s:%i (%3.1f %sbytes)", c->comm ?: "", p->pid, bytes, suf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) svg_text(Y, c->start_time, comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) c->Y = Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) Y++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) static void draw_process_bars(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) struct cpu_sample *sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) int Y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) Y = 2 * tchart->numcpus + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (!c->display) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) c->Y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) svg_box(Y, c->start_time, c->end_time, "process");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) sample = c->samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) while (sample) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (sample->type == TYPE_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) svg_running(Y, sample->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) sample->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (sample->type == TYPE_BLOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) svg_blocked(Y, sample->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) sample->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (sample->type == TYPE_WAITING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) svg_waiting(Y, sample->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) sample->start_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) sample->end_time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) sample->backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) sample = sample->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (c->comm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) char comm[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (c->total_time > 5000000000) /* 5 seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / (double)NSEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / (double)NSEC_PER_MSEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) svg_text(Y, c->start_time, comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) c->Y = Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) Y++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) static void add_process_filter(const char *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) int pid = strtoull(string, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) struct process_filter *filt = malloc(sizeof(*filt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) if (!filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) filt->name = strdup(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) filt->pid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) filt->next = process_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) process_filter = filt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct process_filter *filt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) if (!process_filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) filt = process_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) while (filt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (filt->pid && p->pid == filt->pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) if (strcmp(filt->name, c->comm) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) filt = filt->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) static int determine_display_tasks_filtered(struct timechart *tchart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) p->display = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) if (p->start_time == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) p->start_time = tchart->first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) /* no exit marker, task kept running to the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (p->end_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) p->end_time = tchart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) c->display = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (c->start_time == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) c->start_time = tchart->first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (passes_filter(p, c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) c->display = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) p->display = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (c->end_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) c->end_time = tchart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) static int determine_display_tasks(struct timechart *tchart, u64 threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) p = tchart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) p->display = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (p->start_time == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) p->start_time = tchart->first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) /* no exit marker, task kept running to the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (p->end_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) p->end_time = tchart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (p->total_time >= threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) p->display = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) c->display = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (c->start_time == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) c->start_time = tchart->first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) if (c->total_time >= threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) c->display = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (c->end_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) c->end_time = tchart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) static int determine_display_io_tasks(struct timechart *timechart, u64 threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) struct per_pid *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) struct per_pidcomm *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) p = timechart->all_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) /* no exit marker, task kept running to the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) if (p->end_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) p->end_time = timechart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) c = p->all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) while (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) c->display = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (c->total_bytes >= threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) c->display = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (c->end_time == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) c->end_time = timechart->last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) c = c->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) p = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) #define BYTES_THRESH (1 * 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) #define TIME_THRESH 10000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) static void write_svg_file(struct timechart *tchart, const char *filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) u64 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) int thresh = tchart->io_events ? BYTES_THRESH : TIME_THRESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (tchart->power_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) tchart->proc_num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /* We'd like to show at least proc_num tasks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) * be less picky if we have fewer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (process_filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) count = determine_display_tasks_filtered(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) else if (tchart->io_events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) count = determine_display_io_tasks(tchart, thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) count = determine_display_tasks(tchart, thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) thresh /= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) } while (!process_filter && thresh && count < tchart->proc_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (!tchart->proc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) if (tchart->io_events) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) open_svg(filename, 0, count, tchart->first_time, tchart->last_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) svg_time_grid(0.5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) svg_io_legenda();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) draw_io_bars(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) open_svg(filename, tchart->numcpus, count, tchart->first_time, tchart->last_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) svg_time_grid(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) svg_legenda();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) for (i = 0; i < tchart->numcpus; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) svg_cpu_box(i, tchart->max_freq, tchart->turbo_frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) draw_cpu_usage(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (tchart->proc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) draw_process_bars(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (!tchart->tasks_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) draw_c_p_states(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (tchart->proc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) draw_wakeups(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) svg_close();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) static int process_header(struct perf_file_section *section __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) struct perf_header *ph,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) int feat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) int fd __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) struct timechart *tchart = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) switch (feat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) case HEADER_NRCPUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) tchart->numcpus = ph->env.nr_cpus_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) case HEADER_CPU_TOPOLOGY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (!tchart->topology)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) if (svg_build_topology_map(&ph->env))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) fprintf(stderr, "problem building topology\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) static int __cmd_timechart(struct timechart *tchart, const char *output_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) const struct evsel_str_handler power_tracepoints[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) { "power:cpu_idle", process_sample_cpu_idle },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) { "power:cpu_frequency", process_sample_cpu_frequency },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) { "sched:sched_wakeup", process_sample_sched_wakeup },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) { "sched:sched_switch", process_sample_sched_switch },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) #ifdef SUPPORT_OLD_POWER_EVENTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) { "power:power_start", process_sample_power_start },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) { "power:power_end", process_sample_power_end },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) { "power:power_frequency", process_sample_power_frequency },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) { "syscalls:sys_enter_read", process_enter_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) { "syscalls:sys_enter_pread64", process_enter_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) { "syscalls:sys_enter_readv", process_enter_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) { "syscalls:sys_enter_preadv", process_enter_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) { "syscalls:sys_enter_write", process_enter_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) { "syscalls:sys_enter_pwrite64", process_enter_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) { "syscalls:sys_enter_writev", process_enter_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) { "syscalls:sys_enter_pwritev", process_enter_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) { "syscalls:sys_enter_sync", process_enter_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) { "syscalls:sys_enter_sync_file_range", process_enter_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) { "syscalls:sys_enter_fsync", process_enter_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) { "syscalls:sys_enter_msync", process_enter_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) { "syscalls:sys_enter_recvfrom", process_enter_rx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) { "syscalls:sys_enter_recvmmsg", process_enter_rx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) { "syscalls:sys_enter_recvmsg", process_enter_rx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) { "syscalls:sys_enter_sendto", process_enter_tx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) { "syscalls:sys_enter_sendmsg", process_enter_tx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) { "syscalls:sys_enter_sendmmsg", process_enter_tx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) { "syscalls:sys_enter_epoll_pwait", process_enter_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) { "syscalls:sys_enter_epoll_wait", process_enter_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) { "syscalls:sys_enter_poll", process_enter_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) { "syscalls:sys_enter_ppoll", process_enter_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) { "syscalls:sys_enter_pselect6", process_enter_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) { "syscalls:sys_enter_select", process_enter_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) { "syscalls:sys_exit_read", process_exit_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) { "syscalls:sys_exit_pread64", process_exit_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) { "syscalls:sys_exit_readv", process_exit_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) { "syscalls:sys_exit_preadv", process_exit_read },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) { "syscalls:sys_exit_write", process_exit_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) { "syscalls:sys_exit_pwrite64", process_exit_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) { "syscalls:sys_exit_writev", process_exit_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) { "syscalls:sys_exit_pwritev", process_exit_write },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) { "syscalls:sys_exit_sync", process_exit_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) { "syscalls:sys_exit_sync_file_range", process_exit_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) { "syscalls:sys_exit_fsync", process_exit_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) { "syscalls:sys_exit_msync", process_exit_sync },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) { "syscalls:sys_exit_recvfrom", process_exit_rx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) { "syscalls:sys_exit_recvmmsg", process_exit_rx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) { "syscalls:sys_exit_recvmsg", process_exit_rx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) { "syscalls:sys_exit_sendto", process_exit_tx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) { "syscalls:sys_exit_sendmsg", process_exit_tx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) { "syscalls:sys_exit_sendmmsg", process_exit_tx },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) { "syscalls:sys_exit_epoll_pwait", process_exit_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) { "syscalls:sys_exit_epoll_wait", process_exit_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) { "syscalls:sys_exit_poll", process_exit_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) { "syscalls:sys_exit_ppoll", process_exit_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) { "syscalls:sys_exit_pselect6", process_exit_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) { "syscalls:sys_exit_select", process_exit_poll },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) struct perf_data data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) .path = input_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) .mode = PERF_DATA_MODE_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) .force = tchart->force,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) struct perf_session *session = perf_session__new(&data, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) &tchart->tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (IS_ERR(session))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return PTR_ERR(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) symbol__init(&session->header.env);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) (void)perf_header__process_sections(&session->header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) perf_data__fd(session->data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) tchart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) process_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) if (!perf_session__has_traces(session, "timechart record"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) goto out_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (perf_session__set_tracepoints_handlers(session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) power_tracepoints)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) pr_err("Initializing session tracepoint handlers failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) goto out_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) ret = perf_session__process_events(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) goto out_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) end_sample_processing(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) sort_pids(tchart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) write_svg_file(tchart, output_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) pr_info("Written %2.1f seconds of trace to %s.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) (tchart->last_time - tchart->first_time) / (double)NSEC_PER_SEC, output_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) out_delete:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) perf_session__delete(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) static int timechart__io_record(int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) unsigned int rec_argc, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) const char **rec_argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) const char **p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) char *filter = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) const char * const common_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) "record", "-a", "-R", "-c", "1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) unsigned int common_args_nr = ARRAY_SIZE(common_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) const char * const disk_events[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) "syscalls:sys_enter_read",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) "syscalls:sys_enter_pread64",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) "syscalls:sys_enter_readv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) "syscalls:sys_enter_preadv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) "syscalls:sys_enter_write",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) "syscalls:sys_enter_pwrite64",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) "syscalls:sys_enter_writev",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) "syscalls:sys_enter_pwritev",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) "syscalls:sys_enter_sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) "syscalls:sys_enter_sync_file_range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) "syscalls:sys_enter_fsync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) "syscalls:sys_enter_msync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) "syscalls:sys_exit_read",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) "syscalls:sys_exit_pread64",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) "syscalls:sys_exit_readv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) "syscalls:sys_exit_preadv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) "syscalls:sys_exit_write",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) "syscalls:sys_exit_pwrite64",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) "syscalls:sys_exit_writev",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) "syscalls:sys_exit_pwritev",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) "syscalls:sys_exit_sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) "syscalls:sys_exit_sync_file_range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) "syscalls:sys_exit_fsync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) "syscalls:sys_exit_msync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) unsigned int disk_events_nr = ARRAY_SIZE(disk_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) const char * const net_events[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) "syscalls:sys_enter_recvfrom",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) "syscalls:sys_enter_recvmmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) "syscalls:sys_enter_recvmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) "syscalls:sys_enter_sendto",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) "syscalls:sys_enter_sendmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) "syscalls:sys_enter_sendmmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) "syscalls:sys_exit_recvfrom",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) "syscalls:sys_exit_recvmmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) "syscalls:sys_exit_recvmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) "syscalls:sys_exit_sendto",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) "syscalls:sys_exit_sendmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) "syscalls:sys_exit_sendmmsg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) unsigned int net_events_nr = ARRAY_SIZE(net_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) const char * const poll_events[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) "syscalls:sys_enter_epoll_pwait",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) "syscalls:sys_enter_epoll_wait",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) "syscalls:sys_enter_poll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) "syscalls:sys_enter_ppoll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) "syscalls:sys_enter_pselect6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) "syscalls:sys_enter_select",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) "syscalls:sys_exit_epoll_pwait",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) "syscalls:sys_exit_epoll_wait",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) "syscalls:sys_exit_poll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) "syscalls:sys_exit_ppoll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) "syscalls:sys_exit_pselect6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) "syscalls:sys_exit_select",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) unsigned int poll_events_nr = ARRAY_SIZE(poll_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) rec_argc = common_args_nr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) disk_events_nr * 4 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) net_events_nr * 4 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) poll_events_nr * 4 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) rec_argv = calloc(rec_argc + 1, sizeof(char *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) if (rec_argv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) if (asprintf(&filter, "common_pid != %d", getpid()) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) free(rec_argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) p = rec_argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) for (i = 0; i < common_args_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) *p++ = strdup(common_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) for (i = 0; i < disk_events_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (!is_valid_tracepoint(disk_events[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) rec_argc -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) *p++ = "-e";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) *p++ = strdup(disk_events[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) *p++ = "--filter";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) *p++ = filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) for (i = 0; i < net_events_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) if (!is_valid_tracepoint(net_events[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) rec_argc -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) *p++ = "-e";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) *p++ = strdup(net_events[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) *p++ = "--filter";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) *p++ = filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) for (i = 0; i < poll_events_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) if (!is_valid_tracepoint(poll_events[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) rec_argc -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) *p++ = "-e";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) *p++ = strdup(poll_events[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) *p++ = "--filter";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) *p++ = filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) for (i = 0; i < (unsigned int)argc; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) *p++ = argv[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) return cmd_record(rec_argc, rec_argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) static int timechart__record(struct timechart *tchart, int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) unsigned int rec_argc, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) const char **rec_argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) const char **p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) unsigned int record_elems;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) const char * const common_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) "record", "-a", "-R", "-c", "1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) unsigned int common_args_nr = ARRAY_SIZE(common_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) const char * const backtrace_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) "-g",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) unsigned int backtrace_args_no = ARRAY_SIZE(backtrace_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) const char * const power_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) "-e", "power:cpu_frequency",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) "-e", "power:cpu_idle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) unsigned int power_args_nr = ARRAY_SIZE(power_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) const char * const old_power_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) #ifdef SUPPORT_OLD_POWER_EVENTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) "-e", "power:power_start",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) "-e", "power:power_end",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) "-e", "power:power_frequency",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) const char * const tasks_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) "-e", "sched:sched_wakeup",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) "-e", "sched:sched_switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) #ifdef SUPPORT_OLD_POWER_EVENTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (!is_valid_tracepoint("power:cpu_idle") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) is_valid_tracepoint("power:power_start")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) use_old_power_events = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) power_args_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) old_power_args_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (tchart->power_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) tasks_args_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (tchart->tasks_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) power_args_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) old_power_args_nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) if (!tchart->with_backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) backtrace_args_no = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) record_elems = common_args_nr + tasks_args_nr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) power_args_nr + old_power_args_nr + backtrace_args_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) rec_argc = record_elems + argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) rec_argv = calloc(rec_argc + 1, sizeof(char *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (rec_argv == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) p = rec_argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) for (i = 0; i < common_args_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) *p++ = strdup(common_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) for (i = 0; i < backtrace_args_no; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) *p++ = strdup(backtrace_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) for (i = 0; i < tasks_args_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) *p++ = strdup(tasks_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) for (i = 0; i < power_args_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) *p++ = strdup(power_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) for (i = 0; i < old_power_args_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) *p++ = strdup(old_power_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) for (j = 0; j < (unsigned int)argc; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) *p++ = argv[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) return cmd_record(rec_argc, rec_argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) parse_process(const struct option *opt __maybe_unused, const char *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) int __maybe_unused unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) if (arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) add_process_filter(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) parse_highlight(const struct option *opt __maybe_unused, const char *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) int __maybe_unused unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) unsigned long duration = strtoul(arg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) if (svg_highlight || svg_highlight_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if (duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) svg_highlight = duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) svg_highlight_name = strdup(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) char unit = 'n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) u64 *value = opt->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) switch (unit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) *value *= NSEC_PER_MSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) *value *= NSEC_PER_USEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) int cmd_timechart(int argc, const char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) struct timechart tchart = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) .tool = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) .comm = process_comm_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) .fork = process_fork_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) .exit = process_exit_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) .sample = process_sample_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) .ordered_events = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) .proc_num = 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) .min_time = NSEC_PER_MSEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) .merge_dist = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) const char *output_name = "output.svg";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) const struct option timechart_common_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, "output processes data only"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) OPT_END()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) const struct option timechart_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) OPT_STRING('i', "input", &input_name, "file", "input file name"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) OPT_STRING('o', "output", &output_name, "file", "output file name"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) OPT_INTEGER('w', "width", &svg_page_width, "page width"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) OPT_CALLBACK(0, "highlight", NULL, "duration or task name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) "highlight tasks. Pass duration in ns or process name.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) parse_highlight),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) OPT_CALLBACK('p', "process", NULL, "process",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) "process selector. Pass a pid or process name.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) parse_process),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) OPT_CALLBACK(0, "symfs", NULL, "directory",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) "Look for files with symbols relative to this directory",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) symbol__config_symfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) OPT_INTEGER('n', "proc-num", &tchart.proc_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) "min. number of tasks to print"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) OPT_BOOLEAN('t', "topology", &tchart.topology,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) "sort CPUs according to topology"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) OPT_BOOLEAN(0, "io-skip-eagain", &tchart.skip_eagain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) "skip EAGAIN errors"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) OPT_CALLBACK(0, "io-min-time", &tchart.min_time, "time",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) "all IO faster than min-time will visually appear longer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) parse_time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) "merge events that are merge-dist us apart",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) parse_time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) OPT_PARENT(timechart_common_options),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) const char * const timechart_subcommands[] = { "record", NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) const char *timechart_usage[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) "perf timechart [<options>] {record}",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) const struct option timechart_record_options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) OPT_BOOLEAN('I', "io-only", &tchart.io_only,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) "record only IO data"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) OPT_PARENT(timechart_common_options),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) const char * const timechart_record_usage[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) "perf timechart record [<options>]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (tchart.power_only && tchart.tasks_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) pr_err("-P and -T options cannot be used at the same time.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) if (argc && !strncmp(argv[0], "rec", 3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) argc = parse_options(argc, argv, timechart_record_options,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) timechart_record_usage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) PARSE_OPT_STOP_AT_NON_OPTION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) if (tchart.power_only && tchart.tasks_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) pr_err("-P and -T options cannot be used at the same time.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) if (tchart.io_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) return timechart__io_record(argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) return timechart__record(&tchart, argc, argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) } else if (argc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) usage_with_options(timechart_usage, timechart_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) setup_pager();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return __cmd_timechart(&tchart, output_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) }