~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/builtin-kwork.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/perf/builtin-kwork.c (Architecture ppc) and /tools/perf/builtin-kwork.c (Architecture m68k)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2 /*                                                  2 /*
  3  * builtin-kwork.c                                  3  * builtin-kwork.c
  4  *                                                  4  *
  5  * Copyright (c) 2022  Huawei Inc,  Yang Jihon      5  * Copyright (c) 2022  Huawei Inc,  Yang Jihong <yangjihong1@huawei.com>
  6  */                                                 6  */
  7                                                     7 
  8 #include "builtin.h"                                8 #include "builtin.h"
  9                                                     9 
 10 #include "util/data.h"                             10 #include "util/data.h"
 11 #include "util/evlist.h"                           11 #include "util/evlist.h"
 12 #include "util/evsel.h"                            12 #include "util/evsel.h"
 13 #include "util/header.h"                           13 #include "util/header.h"
 14 #include "util/kwork.h"                            14 #include "util/kwork.h"
 15 #include "util/debug.h"                            15 #include "util/debug.h"
 16 #include "util/session.h"                          16 #include "util/session.h"
 17 #include "util/symbol.h"                           17 #include "util/symbol.h"
 18 #include "util/thread.h"                           18 #include "util/thread.h"
 19 #include "util/string2.h"                          19 #include "util/string2.h"
 20 #include "util/callchain.h"                        20 #include "util/callchain.h"
 21 #include "util/evsel_fprintf.h"                    21 #include "util/evsel_fprintf.h"
 22 #include "util/util.h"                             22 #include "util/util.h"
 23                                                    23 
 24 #include <subcmd/pager.h>                          24 #include <subcmd/pager.h>
 25 #include <subcmd/parse-options.h>                  25 #include <subcmd/parse-options.h>
 26 #include <traceevent/event-parse.h>                26 #include <traceevent/event-parse.h>
 27                                                    27 
 28 #include <errno.h>                                 28 #include <errno.h>
 29 #include <inttypes.h>                              29 #include <inttypes.h>
 30 #include <signal.h>                                30 #include <signal.h>
 31 #include <linux/err.h>                             31 #include <linux/err.h>
 32 #include <linux/time64.h>                          32 #include <linux/time64.h>
 33 #include <linux/zalloc.h>                          33 #include <linux/zalloc.h>
 34                                                    34 
 35 /*                                                 35 /*
 36  * report header elements width                    36  * report header elements width
 37  */                                                37  */
 38 #define PRINT_CPU_WIDTH 4                          38 #define PRINT_CPU_WIDTH 4
 39 #define PRINT_COUNT_WIDTH 9                        39 #define PRINT_COUNT_WIDTH 9
 40 #define PRINT_RUNTIME_WIDTH 10                     40 #define PRINT_RUNTIME_WIDTH 10
 41 #define PRINT_LATENCY_WIDTH 10                     41 #define PRINT_LATENCY_WIDTH 10
 42 #define PRINT_TIMESTAMP_WIDTH 17                   42 #define PRINT_TIMESTAMP_WIDTH 17
 43 #define PRINT_KWORK_NAME_WIDTH 30                  43 #define PRINT_KWORK_NAME_WIDTH 30
 44 #define RPINT_DECIMAL_WIDTH 3                      44 #define RPINT_DECIMAL_WIDTH 3
 45 #define PRINT_BRACKETPAIR_WIDTH 2                  45 #define PRINT_BRACKETPAIR_WIDTH 2
 46 #define PRINT_TIME_UNIT_SEC_WIDTH 2                46 #define PRINT_TIME_UNIT_SEC_WIDTH 2
 47 #define PRINT_TIME_UNIT_MESC_WIDTH 3               47 #define PRINT_TIME_UNIT_MESC_WIDTH 3
 48 #define PRINT_PID_WIDTH 7                          48 #define PRINT_PID_WIDTH 7
 49 #define PRINT_TASK_NAME_WIDTH 16                   49 #define PRINT_TASK_NAME_WIDTH 16
 50 #define PRINT_CPU_USAGE_WIDTH 6                    50 #define PRINT_CPU_USAGE_WIDTH 6
 51 #define PRINT_CPU_USAGE_DECIMAL_WIDTH 2            51 #define PRINT_CPU_USAGE_DECIMAL_WIDTH 2
 52 #define PRINT_CPU_USAGE_HIST_WIDTH 30              52 #define PRINT_CPU_USAGE_HIST_WIDTH 30
 53 #define PRINT_RUNTIME_HEADER_WIDTH (PRINT_RUNT     53 #define PRINT_RUNTIME_HEADER_WIDTH (PRINT_RUNTIME_WIDTH + PRINT_TIME_UNIT_MESC_WIDTH)
 54 #define PRINT_LATENCY_HEADER_WIDTH (PRINT_LATE     54 #define PRINT_LATENCY_HEADER_WIDTH (PRINT_LATENCY_WIDTH + PRINT_TIME_UNIT_MESC_WIDTH)
 55 #define PRINT_TIMEHIST_CPU_WIDTH (PRINT_CPU_WI     55 #define PRINT_TIMEHIST_CPU_WIDTH (PRINT_CPU_WIDTH + PRINT_BRACKETPAIR_WIDTH)
 56 #define PRINT_TIMESTAMP_HEADER_WIDTH (PRINT_TI     56 #define PRINT_TIMESTAMP_HEADER_WIDTH (PRINT_TIMESTAMP_WIDTH + PRINT_TIME_UNIT_SEC_WIDTH)
 57                                                    57 
 58 struct sort_dimension {                            58 struct sort_dimension {
 59         const char      *name;                     59         const char      *name;
 60         int             (*cmp)(struct kwork_wo     60         int             (*cmp)(struct kwork_work *l, struct kwork_work *r);
 61         struct          list_head list;            61         struct          list_head list;
 62 };                                                 62 };
 63                                                    63 
 64 static int id_cmp(struct kwork_work *l, struct     64 static int id_cmp(struct kwork_work *l, struct kwork_work *r)
 65 {                                                  65 {
 66         if (l->cpu > r->cpu)                       66         if (l->cpu > r->cpu)
 67                 return 1;                          67                 return 1;
 68         if (l->cpu < r->cpu)                       68         if (l->cpu < r->cpu)
 69                 return -1;                         69                 return -1;
 70                                                    70 
 71         if (l->id > r->id)                         71         if (l->id > r->id)
 72                 return 1;                          72                 return 1;
 73         if (l->id < r->id)                         73         if (l->id < r->id)
 74                 return -1;                         74                 return -1;
 75                                                    75 
 76         return 0;                                  76         return 0;
 77 }                                                  77 }
 78                                                    78 
 79 static int count_cmp(struct kwork_work *l, str     79 static int count_cmp(struct kwork_work *l, struct kwork_work *r)
 80 {                                                  80 {
 81         if (l->nr_atoms > r->nr_atoms)             81         if (l->nr_atoms > r->nr_atoms)
 82                 return 1;                          82                 return 1;
 83         if (l->nr_atoms < r->nr_atoms)             83         if (l->nr_atoms < r->nr_atoms)
 84                 return -1;                         84                 return -1;
 85                                                    85 
 86         return 0;                                  86         return 0;
 87 }                                                  87 }
 88                                                    88 
 89 static int runtime_cmp(struct kwork_work *l, s     89 static int runtime_cmp(struct kwork_work *l, struct kwork_work *r)
 90 {                                                  90 {
 91         if (l->total_runtime > r->total_runtim     91         if (l->total_runtime > r->total_runtime)
 92                 return 1;                          92                 return 1;
 93         if (l->total_runtime < r->total_runtim     93         if (l->total_runtime < r->total_runtime)
 94                 return -1;                         94                 return -1;
 95                                                    95 
 96         return 0;                                  96         return 0;
 97 }                                                  97 }
 98                                                    98 
 99 static int max_runtime_cmp(struct kwork_work *     99 static int max_runtime_cmp(struct kwork_work *l, struct kwork_work *r)
100 {                                                 100 {
101         if (l->max_runtime > r->max_runtime)      101         if (l->max_runtime > r->max_runtime)
102                 return 1;                         102                 return 1;
103         if (l->max_runtime < r->max_runtime)      103         if (l->max_runtime < r->max_runtime)
104                 return -1;                        104                 return -1;
105                                                   105 
106         return 0;                                 106         return 0;
107 }                                                 107 }
108                                                   108 
109 static int avg_latency_cmp(struct kwork_work *    109 static int avg_latency_cmp(struct kwork_work *l, struct kwork_work *r)
110 {                                                 110 {
111         u64 avgl, avgr;                           111         u64 avgl, avgr;
112                                                   112 
113         if (!r->nr_atoms)                         113         if (!r->nr_atoms)
114                 return 1;                         114                 return 1;
115         if (!l->nr_atoms)                         115         if (!l->nr_atoms)
116                 return -1;                        116                 return -1;
117                                                   117 
118         avgl = l->total_latency / l->nr_atoms;    118         avgl = l->total_latency / l->nr_atoms;
119         avgr = r->total_latency / r->nr_atoms;    119         avgr = r->total_latency / r->nr_atoms;
120                                                   120 
121         if (avgl > avgr)                          121         if (avgl > avgr)
122                 return 1;                         122                 return 1;
123         if (avgl < avgr)                          123         if (avgl < avgr)
124                 return -1;                        124                 return -1;
125                                                   125 
126         return 0;                                 126         return 0;
127 }                                                 127 }
128                                                   128 
129 static int max_latency_cmp(struct kwork_work *    129 static int max_latency_cmp(struct kwork_work *l, struct kwork_work *r)
130 {                                                 130 {
131         if (l->max_latency > r->max_latency)      131         if (l->max_latency > r->max_latency)
132                 return 1;                         132                 return 1;
133         if (l->max_latency < r->max_latency)      133         if (l->max_latency < r->max_latency)
134                 return -1;                        134                 return -1;
135                                                   135 
136         return 0;                                 136         return 0;
137 }                                                 137 }
138                                                   138 
139 static int cpu_usage_cmp(struct kwork_work *l,    139 static int cpu_usage_cmp(struct kwork_work *l, struct kwork_work *r)
140 {                                                 140 {
141         if (l->cpu_usage > r->cpu_usage)          141         if (l->cpu_usage > r->cpu_usage)
142                 return 1;                         142                 return 1;
143         if (l->cpu_usage < r->cpu_usage)          143         if (l->cpu_usage < r->cpu_usage)
144                 return -1;                        144                 return -1;
145                                                   145 
146         return 0;                                 146         return 0;
147 }                                                 147 }
148                                                   148 
149 static int id_or_cpu_r_cmp(struct kwork_work *    149 static int id_or_cpu_r_cmp(struct kwork_work *l, struct kwork_work *r)
150 {                                                 150 {
151         if (l->id < r->id)                        151         if (l->id < r->id)
152                 return 1;                         152                 return 1;
153         if (l->id > r->id)                        153         if (l->id > r->id)
154                 return -1;                        154                 return -1;
155                                                   155 
156         if (l->id != 0)                           156         if (l->id != 0)
157                 return 0;                         157                 return 0;
158                                                   158 
159         if (l->cpu < r->cpu)                      159         if (l->cpu < r->cpu)
160                 return 1;                         160                 return 1;
161         if (l->cpu > r->cpu)                      161         if (l->cpu > r->cpu)
162                 return -1;                        162                 return -1;
163                                                   163 
164         return 0;                                 164         return 0;
165 }                                                 165 }
166                                                   166 
167 static int sort_dimension__add(struct perf_kwo    167 static int sort_dimension__add(struct perf_kwork *kwork __maybe_unused,
168                                const char *tok    168                                const char *tok, struct list_head *list)
169 {                                                 169 {
170         size_t i;                                 170         size_t i;
171         static struct sort_dimension max_sort_    171         static struct sort_dimension max_sort_dimension = {
172                 .name = "max",                    172                 .name = "max",
173                 .cmp  = max_runtime_cmp,          173                 .cmp  = max_runtime_cmp,
174         };                                        174         };
175         static struct sort_dimension id_sort_d    175         static struct sort_dimension id_sort_dimension = {
176                 .name = "id",                     176                 .name = "id",
177                 .cmp  = id_cmp,                   177                 .cmp  = id_cmp,
178         };                                        178         };
179         static struct sort_dimension runtime_s    179         static struct sort_dimension runtime_sort_dimension = {
180                 .name = "runtime",                180                 .name = "runtime",
181                 .cmp  = runtime_cmp,              181                 .cmp  = runtime_cmp,
182         };                                        182         };
183         static struct sort_dimension count_sor    183         static struct sort_dimension count_sort_dimension = {
184                 .name = "count",                  184                 .name = "count",
185                 .cmp  = count_cmp,                185                 .cmp  = count_cmp,
186         };                                        186         };
187         static struct sort_dimension avg_sort_    187         static struct sort_dimension avg_sort_dimension = {
188                 .name = "avg",                    188                 .name = "avg",
189                 .cmp  = avg_latency_cmp,          189                 .cmp  = avg_latency_cmp,
190         };                                        190         };
191         static struct sort_dimension rate_sort    191         static struct sort_dimension rate_sort_dimension = {
192                 .name = "rate",                   192                 .name = "rate",
193                 .cmp  = cpu_usage_cmp,            193                 .cmp  = cpu_usage_cmp,
194         };                                        194         };
195         static struct sort_dimension tid_sort_    195         static struct sort_dimension tid_sort_dimension = {
196                 .name = "tid",                    196                 .name = "tid",
197                 .cmp  = id_or_cpu_r_cmp,          197                 .cmp  = id_or_cpu_r_cmp,
198         };                                        198         };
199         struct sort_dimension *available_sorts    199         struct sort_dimension *available_sorts[] = {
200                 &id_sort_dimension,               200                 &id_sort_dimension,
201                 &max_sort_dimension,              201                 &max_sort_dimension,
202                 &count_sort_dimension,            202                 &count_sort_dimension,
203                 &runtime_sort_dimension,          203                 &runtime_sort_dimension,
204                 &avg_sort_dimension,              204                 &avg_sort_dimension,
205                 &rate_sort_dimension,             205                 &rate_sort_dimension,
206                 &tid_sort_dimension,              206                 &tid_sort_dimension,
207         };                                        207         };
208                                                   208 
209         if (kwork->report == KWORK_REPORT_LATE    209         if (kwork->report == KWORK_REPORT_LATENCY)
210                 max_sort_dimension.cmp = max_l    210                 max_sort_dimension.cmp = max_latency_cmp;
211                                                   211 
212         for (i = 0; i < ARRAY_SIZE(available_s    212         for (i = 0; i < ARRAY_SIZE(available_sorts); i++) {
213                 if (!strcmp(available_sorts[i]    213                 if (!strcmp(available_sorts[i]->name, tok)) {
214                         list_add_tail(&availab    214                         list_add_tail(&available_sorts[i]->list, list);
215                         return 0;                 215                         return 0;
216                 }                                 216                 }
217         }                                         217         }
218                                                   218 
219         return -1;                                219         return -1;
220 }                                                 220 }
221                                                   221 
222 static void setup_sorting(struct perf_kwork *k    222 static void setup_sorting(struct perf_kwork *kwork,
223                           const struct option     223                           const struct option *options,
224                           const char * const u    224                           const char * const usage_msg[])
225 {                                                 225 {
226         char *tmp, *tok, *str = strdup(kwork->    226         char *tmp, *tok, *str = strdup(kwork->sort_order);
227                                                   227 
228         for (tok = strtok_r(str, ", ", &tmp);     228         for (tok = strtok_r(str, ", ", &tmp);
229              tok; tok = strtok_r(NULL, ", ", &    229              tok; tok = strtok_r(NULL, ", ", &tmp)) {
230                 if (sort_dimension__add(kwork,    230                 if (sort_dimension__add(kwork, tok, &kwork->sort_list) < 0)
231                         usage_with_options_msg    231                         usage_with_options_msg(usage_msg, options,
232                                                   232                                                "Unknown --sort key: `%s'", tok);
233         }                                         233         }
234                                                   234 
235         pr_debug("Sort order: %s\n", kwork->so    235         pr_debug("Sort order: %s\n", kwork->sort_order);
236         free(str);                                236         free(str);
237 }                                                 237 }
238                                                   238 
239 static struct kwork_atom *atom_new(struct perf    239 static struct kwork_atom *atom_new(struct perf_kwork *kwork,
240                                    struct perf    240                                    struct perf_sample *sample)
241 {                                                 241 {
242         unsigned long i;                          242         unsigned long i;
243         struct kwork_atom_page *page;             243         struct kwork_atom_page *page;
244         struct kwork_atom *atom = NULL;           244         struct kwork_atom *atom = NULL;
245                                                   245 
246         list_for_each_entry(page, &kwork->atom    246         list_for_each_entry(page, &kwork->atom_page_list, list) {
247                 if (!bitmap_full(page->bitmap,    247                 if (!bitmap_full(page->bitmap, NR_ATOM_PER_PAGE)) {
248                         i = find_first_zero_bi    248                         i = find_first_zero_bit(page->bitmap, NR_ATOM_PER_PAGE);
249                         BUG_ON(i >= NR_ATOM_PE    249                         BUG_ON(i >= NR_ATOM_PER_PAGE);
250                         atom = &page->atoms[i]    250                         atom = &page->atoms[i];
251                         goto found_atom;          251                         goto found_atom;
252                 }                                 252                 }
253         }                                         253         }
254                                                   254 
255         /*                                        255         /*
256          * new page                               256          * new page
257          */                                       257          */
258         page = zalloc(sizeof(*page));             258         page = zalloc(sizeof(*page));
259         if (page == NULL) {                       259         if (page == NULL) {
260                 pr_err("Failed to zalloc kwork    260                 pr_err("Failed to zalloc kwork atom page\n");
261                 return NULL;                      261                 return NULL;
262         }                                         262         }
263                                                   263 
264         i = 0;                                    264         i = 0;
265         atom = &page->atoms[0];                   265         atom = &page->atoms[0];
266         list_add_tail(&page->list, &kwork->ato    266         list_add_tail(&page->list, &kwork->atom_page_list);
267                                                   267 
268 found_atom:                                       268 found_atom:
269         __set_bit(i, page->bitmap);               269         __set_bit(i, page->bitmap);
270         atom->time = sample->time;                270         atom->time = sample->time;
271         atom->prev = NULL;                        271         atom->prev = NULL;
272         atom->page_addr = page;                   272         atom->page_addr = page;
273         atom->bit_inpage = i;                     273         atom->bit_inpage = i;
274         return atom;                              274         return atom;
275 }                                                 275 }
276                                                   276 
277 static void atom_free(struct kwork_atom *atom)    277 static void atom_free(struct kwork_atom *atom)
278 {                                                 278 {
279         if (atom->prev != NULL)                   279         if (atom->prev != NULL)
280                 atom_free(atom->prev);            280                 atom_free(atom->prev);
281                                                   281 
282         __clear_bit(atom->bit_inpage,             282         __clear_bit(atom->bit_inpage,
283                     ((struct kwork_atom_page *    283                     ((struct kwork_atom_page *)atom->page_addr)->bitmap);
284 }                                                 284 }
285                                                   285 
286 static void atom_del(struct kwork_atom *atom)     286 static void atom_del(struct kwork_atom *atom)
287 {                                                 287 {
288         list_del(&atom->list);                    288         list_del(&atom->list);
289         atom_free(atom);                          289         atom_free(atom);
290 }                                                 290 }
291                                                   291 
292 static int work_cmp(struct list_head *list,       292 static int work_cmp(struct list_head *list,
293                     struct kwork_work *l, stru    293                     struct kwork_work *l, struct kwork_work *r)
294 {                                                 294 {
295         int ret = 0;                              295         int ret = 0;
296         struct sort_dimension *sort;              296         struct sort_dimension *sort;
297                                                   297 
298         BUG_ON(list_empty(list));                 298         BUG_ON(list_empty(list));
299                                                   299 
300         list_for_each_entry(sort, list, list)     300         list_for_each_entry(sort, list, list) {
301                 ret = sort->cmp(l, r);            301                 ret = sort->cmp(l, r);
302                 if (ret)                          302                 if (ret)
303                         return ret;               303                         return ret;
304         }                                         304         }
305                                                   305 
306         return ret;                               306         return ret;
307 }                                                 307 }
308                                                   308 
309 static struct kwork_work *work_search(struct r    309 static struct kwork_work *work_search(struct rb_root_cached *root,
310                                       struct k    310                                       struct kwork_work *key,
311                                       struct l    311                                       struct list_head *sort_list)
312 {                                                 312 {
313         int cmp;                                  313         int cmp;
314         struct kwork_work *work;                  314         struct kwork_work *work;
315         struct rb_node *node = root->rb_root.r    315         struct rb_node *node = root->rb_root.rb_node;
316                                                   316 
317         while (node) {                            317         while (node) {
318                 work = container_of(node, stru    318                 work = container_of(node, struct kwork_work, node);
319                 cmp = work_cmp(sort_list, key,    319                 cmp = work_cmp(sort_list, key, work);
320                 if (cmp > 0)                      320                 if (cmp > 0)
321                         node = node->rb_left;     321                         node = node->rb_left;
322                 else if (cmp < 0)                 322                 else if (cmp < 0)
323                         node = node->rb_right;    323                         node = node->rb_right;
324                 else {                            324                 else {
325                         if (work->name == NULL    325                         if (work->name == NULL)
326                                 work->name = k    326                                 work->name = key->name;
327                         return work;              327                         return work;
328                 }                                 328                 }
329         }                                         329         }
330         return NULL;                              330         return NULL;
331 }                                                 331 }
332                                                   332 
333 static void work_insert(struct rb_root_cached     333 static void work_insert(struct rb_root_cached *root,
334                         struct kwork_work *key    334                         struct kwork_work *key, struct list_head *sort_list)
335 {                                                 335 {
336         int cmp;                                  336         int cmp;
337         bool leftmost = true;                     337         bool leftmost = true;
338         struct kwork_work *cur;                   338         struct kwork_work *cur;
339         struct rb_node **new = &(root->rb_root    339         struct rb_node **new = &(root->rb_root.rb_node), *parent = NULL;
340                                                   340 
341         while (*new) {                            341         while (*new) {
342                 cur = container_of(*new, struc    342                 cur = container_of(*new, struct kwork_work, node);
343                 parent = *new;                    343                 parent = *new;
344                 cmp = work_cmp(sort_list, key,    344                 cmp = work_cmp(sort_list, key, cur);
345                                                   345 
346                 if (cmp > 0)                      346                 if (cmp > 0)
347                         new = &((*new)->rb_lef    347                         new = &((*new)->rb_left);
348                 else {                            348                 else {
349                         new = &((*new)->rb_rig    349                         new = &((*new)->rb_right);
350                         leftmost = false;         350                         leftmost = false;
351                 }                                 351                 }
352         }                                         352         }
353                                                   353 
354         rb_link_node(&key->node, parent, new);    354         rb_link_node(&key->node, parent, new);
355         rb_insert_color_cached(&key->node, roo    355         rb_insert_color_cached(&key->node, root, leftmost);
356 }                                                 356 }
357                                                   357 
358 static struct kwork_work *work_new(struct kwor    358 static struct kwork_work *work_new(struct kwork_work *key)
359 {                                                 359 {
360         int i;                                    360         int i;
361         struct kwork_work *work = zalloc(sizeo    361         struct kwork_work *work = zalloc(sizeof(*work));
362                                                   362 
363         if (work == NULL) {                       363         if (work == NULL) {
364                 pr_err("Failed to zalloc kwork    364                 pr_err("Failed to zalloc kwork work\n");
365                 return NULL;                      365                 return NULL;
366         }                                         366         }
367                                                   367 
368         for (i = 0; i < KWORK_TRACE_MAX; i++)     368         for (i = 0; i < KWORK_TRACE_MAX; i++)
369                 INIT_LIST_HEAD(&work->atom_lis    369                 INIT_LIST_HEAD(&work->atom_list[i]);
370                                                   370 
371         work->id = key->id;                       371         work->id = key->id;
372         work->cpu = key->cpu;                     372         work->cpu = key->cpu;
373         work->name = key->name;                   373         work->name = key->name;
374         work->class = key->class;                 374         work->class = key->class;
375         return work;                              375         return work;
376 }                                                 376 }
377                                                   377 
378 static struct kwork_work *work_findnew(struct     378 static struct kwork_work *work_findnew(struct rb_root_cached *root,
379                                        struct     379                                        struct kwork_work *key,
380                                        struct     380                                        struct list_head *sort_list)
381 {                                                 381 {
382         struct kwork_work *work = work_search(    382         struct kwork_work *work = work_search(root, key, sort_list);
383                                                   383 
384         if (work != NULL)                         384         if (work != NULL)
385                 return work;                      385                 return work;
386                                                   386 
387         work = work_new(key);                     387         work = work_new(key);
388         if (work)                                 388         if (work)
389                 work_insert(root, work, sort_l    389                 work_insert(root, work, sort_list);
390                                                   390 
391         return work;                              391         return work;
392 }                                                 392 }
393                                                   393 
394 static void profile_update_timespan(struct per    394 static void profile_update_timespan(struct perf_kwork *kwork,
395                                     struct per    395                                     struct perf_sample *sample)
396 {                                                 396 {
397         if (!kwork->summary)                      397         if (!kwork->summary)
398                 return;                           398                 return;
399                                                   399 
400         if ((kwork->timestart == 0) || (kwork-    400         if ((kwork->timestart == 0) || (kwork->timestart > sample->time))
401                 kwork->timestart = sample->tim    401                 kwork->timestart = sample->time;
402                                                   402 
403         if (kwork->timeend < sample->time)        403         if (kwork->timeend < sample->time)
404                 kwork->timeend = sample->time;    404                 kwork->timeend = sample->time;
405 }                                                 405 }
406                                                   406 
407 static bool profile_name_match(struct perf_kwo    407 static bool profile_name_match(struct perf_kwork *kwork,
408                                struct kwork_wo    408                                struct kwork_work *work)
409 {                                                 409 {
410         if (kwork->profile_name && work->name     410         if (kwork->profile_name && work->name &&
411             (strcmp(work->name, kwork->profile    411             (strcmp(work->name, kwork->profile_name) != 0)) {
412                 return false;                     412                 return false;
413         }                                         413         }
414                                                   414 
415         return true;                              415         return true;
416 }                                                 416 }
417                                                   417 
418 static bool profile_event_match(struct perf_kw    418 static bool profile_event_match(struct perf_kwork *kwork,
419                                 struct kwork_w    419                                 struct kwork_work *work,
420                                 struct perf_sa    420                                 struct perf_sample *sample)
421 {                                                 421 {
422         int cpu = work->cpu;                      422         int cpu = work->cpu;
423         u64 time = sample->time;                  423         u64 time = sample->time;
424         struct perf_time_interval *ptime = &kw    424         struct perf_time_interval *ptime = &kwork->ptime;
425                                                   425 
426         if ((kwork->cpu_list != NULL) && !test    426         if ((kwork->cpu_list != NULL) && !test_bit(cpu, kwork->cpu_bitmap))
427                 return false;                     427                 return false;
428                                                   428 
429         if (((ptime->start != 0) && (ptime->st    429         if (((ptime->start != 0) && (ptime->start > time)) ||
430             ((ptime->end != 0) && (ptime->end     430             ((ptime->end != 0) && (ptime->end < time)))
431                 return false;                     431                 return false;
432                                                   432 
433         /*                                        433         /*
434          * report top needs to collect the run    434          * report top needs to collect the runtime of all tasks to
435          * calculate the load of each core.       435          * calculate the load of each core.
436          */                                       436          */
437         if ((kwork->report != KWORK_REPORT_TOP    437         if ((kwork->report != KWORK_REPORT_TOP) &&
438             !profile_name_match(kwork, work))     438             !profile_name_match(kwork, work)) {
439                 return false;                     439                 return false;
440         }                                         440         }
441                                                   441 
442         profile_update_timespan(kwork, sample)    442         profile_update_timespan(kwork, sample);
443         return true;                              443         return true;
444 }                                                 444 }
445                                                   445 
446 static int work_push_atom(struct perf_kwork *k    446 static int work_push_atom(struct perf_kwork *kwork,
447                           struct kwork_class *    447                           struct kwork_class *class,
448                           enum kwork_trace_typ    448                           enum kwork_trace_type src_type,
449                           enum kwork_trace_typ    449                           enum kwork_trace_type dst_type,
450                           struct evsel *evsel,    450                           struct evsel *evsel,
451                           struct perf_sample *    451                           struct perf_sample *sample,
452                           struct machine *mach    452                           struct machine *machine,
453                           struct kwork_work **    453                           struct kwork_work **ret_work,
454                           bool overwrite)         454                           bool overwrite)
455 {                                                 455 {
456         struct kwork_atom *atom, *dst_atom, *l    456         struct kwork_atom *atom, *dst_atom, *last_atom;
457         struct kwork_work *work, key;             457         struct kwork_work *work, key;
458                                                   458 
459         BUG_ON(class->work_init == NULL);         459         BUG_ON(class->work_init == NULL);
460         class->work_init(kwork, class, &key, s    460         class->work_init(kwork, class, &key, src_type, evsel, sample, machine);
461                                                   461 
462         atom = atom_new(kwork, sample);           462         atom = atom_new(kwork, sample);
463         if (atom == NULL)                         463         if (atom == NULL)
464                 return -1;                        464                 return -1;
465                                                   465 
466         work = work_findnew(&class->work_root,    466         work = work_findnew(&class->work_root, &key, &kwork->cmp_id);
467         if (work == NULL) {                       467         if (work == NULL) {
468                 atom_free(atom);                  468                 atom_free(atom);
469                 return -1;                        469                 return -1;
470         }                                         470         }
471                                                   471 
472         if (!profile_event_match(kwork, work,     472         if (!profile_event_match(kwork, work, sample)) {
473                 atom_free(atom);                  473                 atom_free(atom);
474                 return 0;                         474                 return 0;
475         }                                         475         }
476                                                   476 
477         if (dst_type < KWORK_TRACE_MAX) {         477         if (dst_type < KWORK_TRACE_MAX) {
478                 dst_atom = list_last_entry_or_    478                 dst_atom = list_last_entry_or_null(&work->atom_list[dst_type],
479                                                   479                                                    struct kwork_atom, list);
480                 if (dst_atom != NULL) {           480                 if (dst_atom != NULL) {
481                         atom->prev = dst_atom;    481                         atom->prev = dst_atom;
482                         list_del(&dst_atom->li    482                         list_del(&dst_atom->list);
483                 }                                 483                 }
484         }                                         484         }
485                                                   485 
486         if (ret_work != NULL)                     486         if (ret_work != NULL)
487                 *ret_work = work;                 487                 *ret_work = work;
488                                                   488 
489         if (overwrite) {                          489         if (overwrite) {
490                 last_atom = list_last_entry_or    490                 last_atom = list_last_entry_or_null(&work->atom_list[src_type],
491                                                   491                                                     struct kwork_atom, list);
492                 if (last_atom) {                  492                 if (last_atom) {
493                         atom_del(last_atom);      493                         atom_del(last_atom);
494                                                   494 
495                         kwork->nr_skipped_even    495                         kwork->nr_skipped_events[src_type]++;
496                         kwork->nr_skipped_even    496                         kwork->nr_skipped_events[KWORK_TRACE_MAX]++;
497                 }                                 497                 }
498         }                                         498         }
499                                                   499 
500         list_add_tail(&atom->list, &work->atom    500         list_add_tail(&atom->list, &work->atom_list[src_type]);
501                                                   501 
502         return 0;                                 502         return 0;
503 }                                                 503 }
504                                                   504 
505 static struct kwork_atom *work_pop_atom(struct    505 static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork,
506                                         struct    506                                         struct kwork_class *class,
507                                         enum k    507                                         enum kwork_trace_type src_type,
508                                         enum k    508                                         enum kwork_trace_type dst_type,
509                                         struct    509                                         struct evsel *evsel,
510                                         struct    510                                         struct perf_sample *sample,
511                                         struct    511                                         struct machine *machine,
512                                         struct    512                                         struct kwork_work **ret_work)
513 {                                                 513 {
514         struct kwork_atom *atom, *src_atom;       514         struct kwork_atom *atom, *src_atom;
515         struct kwork_work *work, key;             515         struct kwork_work *work, key;
516                                                   516 
517         BUG_ON(class->work_init == NULL);         517         BUG_ON(class->work_init == NULL);
518         class->work_init(kwork, class, &key, s    518         class->work_init(kwork, class, &key, src_type, evsel, sample, machine);
519                                                   519 
520         work = work_findnew(&class->work_root,    520         work = work_findnew(&class->work_root, &key, &kwork->cmp_id);
521         if (ret_work != NULL)                     521         if (ret_work != NULL)
522                 *ret_work = work;                 522                 *ret_work = work;
523                                                   523 
524         if (work == NULL)                         524         if (work == NULL)
525                 return NULL;                      525                 return NULL;
526                                                   526 
527         if (!profile_event_match(kwork, work,     527         if (!profile_event_match(kwork, work, sample))
528                 return NULL;                      528                 return NULL;
529                                                   529 
530         atom = list_last_entry_or_null(&work->    530         atom = list_last_entry_or_null(&work->atom_list[dst_type],
531                                        struct     531                                        struct kwork_atom, list);
532         if (atom != NULL)                         532         if (atom != NULL)
533                 return atom;                      533                 return atom;
534                                                   534 
535         src_atom = atom_new(kwork, sample);       535         src_atom = atom_new(kwork, sample);
536         if (src_atom != NULL)                     536         if (src_atom != NULL)
537                 list_add_tail(&src_atom->list,    537                 list_add_tail(&src_atom->list, &work->atom_list[src_type]);
538         else {                                    538         else {
539                 if (ret_work != NULL)             539                 if (ret_work != NULL)
540                         *ret_work = NULL;         540                         *ret_work = NULL;
541         }                                         541         }
542                                                   542 
543         return NULL;                              543         return NULL;
544 }                                                 544 }
545                                                   545 
546 static struct kwork_work *find_work_by_id(stru    546 static struct kwork_work *find_work_by_id(struct rb_root_cached *root,
547                                           u64     547                                           u64 id, int cpu)
548 {                                                 548 {
549         struct rb_node *next;                     549         struct rb_node *next;
550         struct kwork_work *work;                  550         struct kwork_work *work;
551                                                   551 
552         next = rb_first_cached(root);             552         next = rb_first_cached(root);
553         while (next) {                            553         while (next) {
554                 work = rb_entry(next, struct k    554                 work = rb_entry(next, struct kwork_work, node);
555                 if ((cpu != -1 && work->id ==     555                 if ((cpu != -1 && work->id == id && work->cpu == cpu) ||
556                     (cpu == -1 && work->id ==     556                     (cpu == -1 && work->id == id))
557                         return work;              557                         return work;
558                                                   558 
559                 next = rb_next(next);             559                 next = rb_next(next);
560         }                                         560         }
561                                                   561 
562         return NULL;                              562         return NULL;
563 }                                                 563 }
564                                                   564 
565 static struct kwork_class *get_kwork_class(str    565 static struct kwork_class *get_kwork_class(struct perf_kwork *kwork,
566                                            enu    566                                            enum kwork_class_type type)
567 {                                                 567 {
568         struct kwork_class *class;                568         struct kwork_class *class;
569                                                   569 
570         list_for_each_entry(class, &kwork->cla    570         list_for_each_entry(class, &kwork->class_list, list) {
571                 if (class->type == type)          571                 if (class->type == type)
572                         return class;             572                         return class;
573         }                                         573         }
574                                                   574 
575         return NULL;                              575         return NULL;
576 }                                                 576 }
577                                                   577 
578 static void report_update_exit_event(struct kw    578 static void report_update_exit_event(struct kwork_work *work,
579                                      struct kw    579                                      struct kwork_atom *atom,
580                                      struct pe    580                                      struct perf_sample *sample)
581 {                                                 581 {
582         u64 delta;                                582         u64 delta;
583         u64 exit_time = sample->time;             583         u64 exit_time = sample->time;
584         u64 entry_time = atom->time;              584         u64 entry_time = atom->time;
585                                                   585 
586         if ((entry_time != 0) && (exit_time >=    586         if ((entry_time != 0) && (exit_time >= entry_time)) {
587                 delta = exit_time - entry_time    587                 delta = exit_time - entry_time;
588                 if ((delta > work->max_runtime    588                 if ((delta > work->max_runtime) ||
589                     (work->max_runtime == 0))     589                     (work->max_runtime == 0)) {
590                         work->max_runtime = de    590                         work->max_runtime = delta;
591                         work->max_runtime_star    591                         work->max_runtime_start = entry_time;
592                         work->max_runtime_end     592                         work->max_runtime_end = exit_time;
593                 }                                 593                 }
594                 work->total_runtime += delta;     594                 work->total_runtime += delta;
595                 work->nr_atoms++;                 595                 work->nr_atoms++;
596         }                                         596         }
597 }                                                 597 }
598                                                   598 
599 static int report_entry_event(struct perf_kwor    599 static int report_entry_event(struct perf_kwork *kwork,
600                               struct kwork_cla    600                               struct kwork_class *class,
601                               struct evsel *ev    601                               struct evsel *evsel,
602                               struct perf_samp    602                               struct perf_sample *sample,
603                               struct machine *    603                               struct machine *machine)
604 {                                                 604 {
605         return work_push_atom(kwork, class, KW    605         return work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
606                               KWORK_TRACE_MAX,    606                               KWORK_TRACE_MAX, evsel, sample,
607                               machine, NULL, t    607                               machine, NULL, true);
608 }                                                 608 }
609                                                   609 
610 static int report_exit_event(struct perf_kwork    610 static int report_exit_event(struct perf_kwork *kwork,
611                              struct kwork_clas    611                              struct kwork_class *class,
612                              struct evsel *evs    612                              struct evsel *evsel,
613                              struct perf_sampl    613                              struct perf_sample *sample,
614                              struct machine *m    614                              struct machine *machine)
615 {                                                 615 {
616         struct kwork_atom *atom = NULL;           616         struct kwork_atom *atom = NULL;
617         struct kwork_work *work = NULL;           617         struct kwork_work *work = NULL;
618                                                   618 
619         atom = work_pop_atom(kwork, class, KWO    619         atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
620                              KWORK_TRACE_ENTRY    620                              KWORK_TRACE_ENTRY, evsel, sample,
621                              machine, &work);     621                              machine, &work);
622         if (work == NULL)                         622         if (work == NULL)
623                 return -1;                        623                 return -1;
624                                                   624 
625         if (atom != NULL) {                       625         if (atom != NULL) {
626                 report_update_exit_event(work,    626                 report_update_exit_event(work, atom, sample);
627                 atom_del(atom);                   627                 atom_del(atom);
628         }                                         628         }
629                                                   629 
630         return 0;                                 630         return 0;
631 }                                                 631 }
632                                                   632 
633 static void latency_update_entry_event(struct     633 static void latency_update_entry_event(struct kwork_work *work,
634                                        struct     634                                        struct kwork_atom *atom,
635                                        struct     635                                        struct perf_sample *sample)
636 {                                                 636 {
637         u64 delta;                                637         u64 delta;
638         u64 entry_time = sample->time;            638         u64 entry_time = sample->time;
639         u64 raise_time = atom->time;              639         u64 raise_time = atom->time;
640                                                   640 
641         if ((raise_time != 0) && (entry_time >    641         if ((raise_time != 0) && (entry_time >= raise_time)) {
642                 delta = entry_time - raise_tim    642                 delta = entry_time - raise_time;
643                 if ((delta > work->max_latency    643                 if ((delta > work->max_latency) ||
644                     (work->max_latency == 0))     644                     (work->max_latency == 0)) {
645                         work->max_latency = de    645                         work->max_latency = delta;
646                         work->max_latency_star    646                         work->max_latency_start = raise_time;
647                         work->max_latency_end     647                         work->max_latency_end = entry_time;
648                 }                                 648                 }
649                 work->total_latency += delta;     649                 work->total_latency += delta;
650                 work->nr_atoms++;                 650                 work->nr_atoms++;
651         }                                         651         }
652 }                                                 652 }
653                                                   653 
654 static int latency_raise_event(struct perf_kwo    654 static int latency_raise_event(struct perf_kwork *kwork,
655                                struct kwork_cl    655                                struct kwork_class *class,
656                                struct evsel *e    656                                struct evsel *evsel,
657                                struct perf_sam    657                                struct perf_sample *sample,
658                                struct machine     658                                struct machine *machine)
659 {                                                 659 {
660         return work_push_atom(kwork, class, KW    660         return work_push_atom(kwork, class, KWORK_TRACE_RAISE,
661                               KWORK_TRACE_MAX,    661                               KWORK_TRACE_MAX, evsel, sample,
662                               machine, NULL, t    662                               machine, NULL, true);
663 }                                                 663 }
664                                                   664 
665 static int latency_entry_event(struct perf_kwo    665 static int latency_entry_event(struct perf_kwork *kwork,
666                                struct kwork_cl    666                                struct kwork_class *class,
667                                struct evsel *e    667                                struct evsel *evsel,
668                                struct perf_sam    668                                struct perf_sample *sample,
669                                struct machine     669                                struct machine *machine)
670 {                                                 670 {
671         struct kwork_atom *atom = NULL;           671         struct kwork_atom *atom = NULL;
672         struct kwork_work *work = NULL;           672         struct kwork_work *work = NULL;
673                                                   673 
674         atom = work_pop_atom(kwork, class, KWO    674         atom = work_pop_atom(kwork, class, KWORK_TRACE_ENTRY,
675                              KWORK_TRACE_RAISE    675                              KWORK_TRACE_RAISE, evsel, sample,
676                              machine, &work);     676                              machine, &work);
677         if (work == NULL)                         677         if (work == NULL)
678                 return -1;                        678                 return -1;
679                                                   679 
680         if (atom != NULL) {                       680         if (atom != NULL) {
681                 latency_update_entry_event(wor    681                 latency_update_entry_event(work, atom, sample);
682                 atom_del(atom);                   682                 atom_del(atom);
683         }                                         683         }
684                                                   684 
685         return 0;                                 685         return 0;
686 }                                                 686 }
687                                                   687 
688 static void timehist_save_callchain(struct per    688 static void timehist_save_callchain(struct perf_kwork *kwork,
689                                     struct per    689                                     struct perf_sample *sample,
690                                     struct evs    690                                     struct evsel *evsel,
691                                     struct mac    691                                     struct machine *machine)
692 {                                                 692 {
693         struct symbol *sym;                       693         struct symbol *sym;
694         struct thread *thread;                    694         struct thread *thread;
695         struct callchain_cursor_node *node;       695         struct callchain_cursor_node *node;
696         struct callchain_cursor *cursor;          696         struct callchain_cursor *cursor;
697                                                   697 
698         if (!kwork->show_callchain || sample->    698         if (!kwork->show_callchain || sample->callchain == NULL)
699                 return;                           699                 return;
700                                                   700 
701         /* want main thread for process - has     701         /* want main thread for process - has maps */
702         thread = machine__findnew_thread(machi    702         thread = machine__findnew_thread(machine, sample->pid, sample->pid);
703         if (thread == NULL) {                     703         if (thread == NULL) {
704                 pr_debug("Failed to get thread    704                 pr_debug("Failed to get thread for pid %d\n", sample->pid);
705                 return;                           705                 return;
706         }                                         706         }
707                                                   707 
708         cursor = get_tls_callchain_cursor();      708         cursor = get_tls_callchain_cursor();
709                                                   709 
710         if (thread__resolve_callchain(thread,     710         if (thread__resolve_callchain(thread, cursor, evsel, sample,
711                                       NULL, NU    711                                       NULL, NULL, kwork->max_stack + 2) != 0) {
712                 pr_debug("Failed to resolve ca    712                 pr_debug("Failed to resolve callchain, skipping\n");
713                 goto out_put;                     713                 goto out_put;
714         }                                         714         }
715                                                   715 
716         callchain_cursor_commit(cursor);          716         callchain_cursor_commit(cursor);
717                                                   717 
718         while (true) {                            718         while (true) {
719                 node = callchain_cursor_curren    719                 node = callchain_cursor_current(cursor);
720                 if (node == NULL)                 720                 if (node == NULL)
721                         break;                    721                         break;
722                                                   722 
723                 sym = node->ms.sym;               723                 sym = node->ms.sym;
724                 if (sym) {                        724                 if (sym) {
725                         if (!strcmp(sym->name,    725                         if (!strcmp(sym->name, "__softirqentry_text_start") ||
726                             !strcmp(sym->name,    726                             !strcmp(sym->name, "__do_softirq"))
727                                 sym->ignore =     727                                 sym->ignore = 1;
728                 }                                 728                 }
729                                                   729 
730                 callchain_cursor_advance(curso    730                 callchain_cursor_advance(cursor);
731         }                                         731         }
732                                                   732 
733 out_put:                                          733 out_put:
734         thread__put(thread);                      734         thread__put(thread);
735 }                                                 735 }
736                                                   736 
737 static void timehist_print_event(struct perf_k    737 static void timehist_print_event(struct perf_kwork *kwork,
738                                  struct kwork_    738                                  struct kwork_work *work,
739                                  struct kwork_    739                                  struct kwork_atom *atom,
740                                  struct perf_s    740                                  struct perf_sample *sample,
741                                  struct addr_l    741                                  struct addr_location *al)
742 {                                                 742 {
743         char entrytime[32], exittime[32];         743         char entrytime[32], exittime[32];
744         char kwork_name[PRINT_KWORK_NAME_WIDTH    744         char kwork_name[PRINT_KWORK_NAME_WIDTH];
745                                                   745 
746         /*                                        746         /*
747          * runtime start                          747          * runtime start
748          */                                       748          */
749         timestamp__scnprintf_usec(atom->time,     749         timestamp__scnprintf_usec(atom->time,
750                                   entrytime, s    750                                   entrytime, sizeof(entrytime));
751         printf(" %*s ", PRINT_TIMESTAMP_WIDTH,    751         printf(" %*s ", PRINT_TIMESTAMP_WIDTH, entrytime);
752                                                   752 
753         /*                                        753         /*
754          * runtime end                            754          * runtime end
755          */                                       755          */
756         timestamp__scnprintf_usec(sample->time    756         timestamp__scnprintf_usec(sample->time,
757                                   exittime, si    757                                   exittime, sizeof(exittime));
758         printf(" %*s ", PRINT_TIMESTAMP_WIDTH,    758         printf(" %*s ", PRINT_TIMESTAMP_WIDTH, exittime);
759                                                   759 
760         /*                                        760         /*
761          * cpu                                    761          * cpu
762          */                                       762          */
763         printf(" [%0*d] ", PRINT_CPU_WIDTH, wo    763         printf(" [%0*d] ", PRINT_CPU_WIDTH, work->cpu);
764                                                   764 
765         /*                                        765         /*
766          * kwork name                             766          * kwork name
767          */                                       767          */
768         if (work->class && work->class->work_n    768         if (work->class && work->class->work_name) {
769                 work->class->work_name(work, k    769                 work->class->work_name(work, kwork_name,
770                                        PRINT_K    770                                        PRINT_KWORK_NAME_WIDTH);
771                 printf(" %-*s ", PRINT_KWORK_N    771                 printf(" %-*s ", PRINT_KWORK_NAME_WIDTH, kwork_name);
772         } else                                    772         } else
773                 printf(" %-*s ", PRINT_KWORK_N    773                 printf(" %-*s ", PRINT_KWORK_NAME_WIDTH, "");
774                                                   774 
775         /*                                        775         /*
776          *runtime                                 776          *runtime
777          */                                       777          */
778         printf(" %*.*f ",                         778         printf(" %*.*f ",
779                PRINT_RUNTIME_WIDTH, RPINT_DECI    779                PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
780                (double)(sample->time - atom->t    780                (double)(sample->time - atom->time) / NSEC_PER_MSEC);
781                                                   781 
782         /*                                        782         /*
783          * delaytime                              783          * delaytime
784          */                                       784          */
785         if (atom->prev != NULL)                   785         if (atom->prev != NULL)
786                 printf(" %*.*f ", PRINT_LATENC    786                 printf(" %*.*f ", PRINT_LATENCY_WIDTH, RPINT_DECIMAL_WIDTH,
787                        (double)(atom->time - a    787                        (double)(atom->time - atom->prev->time) / NSEC_PER_MSEC);
788         else                                      788         else
789                 printf(" %*s ", PRINT_LATENCY_    789                 printf(" %*s ", PRINT_LATENCY_WIDTH, " ");
790                                                   790 
791         /*                                        791         /*
792          * callchain                              792          * callchain
793          */                                       793          */
794         if (kwork->show_callchain) {              794         if (kwork->show_callchain) {
795                 struct callchain_cursor *curso    795                 struct callchain_cursor *cursor = get_tls_callchain_cursor();
796                                                   796 
797                 if (cursor == NULL)               797                 if (cursor == NULL)
798                         return;                   798                         return;
799                                                   799 
800                 printf(" ");                      800                 printf(" ");
801                                                   801 
802                 sample__fprintf_sym(sample, al    802                 sample__fprintf_sym(sample, al, 0,
803                                     EVSEL__PRI    803                                     EVSEL__PRINT_SYM | EVSEL__PRINT_ONELINE |
804                                     EVSEL__PRI    804                                     EVSEL__PRINT_CALLCHAIN_ARROW |
805                                     EVSEL__PRI    805                                     EVSEL__PRINT_SKIP_IGNORED,
806                                     cursor, sy    806                                     cursor, symbol_conf.bt_stop_list,
807                                     stdout);      807                                     stdout);
808         }                                         808         }
809                                                   809 
810         printf("\n");                             810         printf("\n");
811 }                                                 811 }
812                                                   812 
813 static int timehist_raise_event(struct perf_kw    813 static int timehist_raise_event(struct perf_kwork *kwork,
814                                 struct kwork_c    814                                 struct kwork_class *class,
815                                 struct evsel *    815                                 struct evsel *evsel,
816                                 struct perf_sa    816                                 struct perf_sample *sample,
817                                 struct machine    817                                 struct machine *machine)
818 {                                                 818 {
819         return work_push_atom(kwork, class, KW    819         return work_push_atom(kwork, class, KWORK_TRACE_RAISE,
820                               KWORK_TRACE_MAX,    820                               KWORK_TRACE_MAX, evsel, sample,
821                               machine, NULL, t    821                               machine, NULL, true);
822 }                                                 822 }
823                                                   823 
824 static int timehist_entry_event(struct perf_kw    824 static int timehist_entry_event(struct perf_kwork *kwork,
825                                 struct kwork_c    825                                 struct kwork_class *class,
826                                 struct evsel *    826                                 struct evsel *evsel,
827                                 struct perf_sa    827                                 struct perf_sample *sample,
828                                 struct machine    828                                 struct machine *machine)
829 {                                                 829 {
830         int ret;                                  830         int ret;
831         struct kwork_work *work = NULL;           831         struct kwork_work *work = NULL;
832                                                   832 
833         ret = work_push_atom(kwork, class, KWO    833         ret = work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
834                              KWORK_TRACE_RAISE    834                              KWORK_TRACE_RAISE, evsel, sample,
835                              machine, &work, t    835                              machine, &work, true);
836         if (ret)                                  836         if (ret)
837                 return ret;                       837                 return ret;
838                                                   838 
839         if (work != NULL)                         839         if (work != NULL)
840                 timehist_save_callchain(kwork,    840                 timehist_save_callchain(kwork, sample, evsel, machine);
841                                                   841 
842         return 0;                                 842         return 0;
843 }                                                 843 }
844                                                   844 
845 static int timehist_exit_event(struct perf_kwo    845 static int timehist_exit_event(struct perf_kwork *kwork,
846                                struct kwork_cl    846                                struct kwork_class *class,
847                                struct evsel *e    847                                struct evsel *evsel,
848                                struct perf_sam    848                                struct perf_sample *sample,
849                                struct machine     849                                struct machine *machine)
850 {                                                 850 {
851         struct kwork_atom *atom = NULL;           851         struct kwork_atom *atom = NULL;
852         struct kwork_work *work = NULL;           852         struct kwork_work *work = NULL;
853         struct addr_location al;                  853         struct addr_location al;
854         int ret = 0;                              854         int ret = 0;
855                                                   855 
856         addr_location__init(&al);                 856         addr_location__init(&al);
857         if (machine__resolve(machine, &al, sam    857         if (machine__resolve(machine, &al, sample) < 0) {
858                 pr_debug("Problem processing e    858                 pr_debug("Problem processing event, skipping it\n");
859                 ret = -1;                         859                 ret = -1;
860                 goto out;                         860                 goto out;
861         }                                         861         }
862                                                   862 
863         atom = work_pop_atom(kwork, class, KWO    863         atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
864                              KWORK_TRACE_ENTRY    864                              KWORK_TRACE_ENTRY, evsel, sample,
865                              machine, &work);     865                              machine, &work);
866         if (work == NULL) {                       866         if (work == NULL) {
867                 ret = -1;                         867                 ret = -1;
868                 goto out;                         868                 goto out;
869         }                                         869         }
870                                                   870 
871         if (atom != NULL) {                       871         if (atom != NULL) {
872                 work->nr_atoms++;                 872                 work->nr_atoms++;
873                 timehist_print_event(kwork, wo    873                 timehist_print_event(kwork, work, atom, sample, &al);
874                 atom_del(atom);                   874                 atom_del(atom);
875         }                                         875         }
876                                                   876 
877 out:                                              877 out:
878         addr_location__exit(&al);                 878         addr_location__exit(&al);
879         return ret;                               879         return ret;
880 }                                                 880 }
881                                                   881 
882 static void top_update_runtime(struct kwork_wo    882 static void top_update_runtime(struct kwork_work *work,
883                                struct kwork_at    883                                struct kwork_atom *atom,
884                                struct perf_sam    884                                struct perf_sample *sample)
885 {                                                 885 {
886         u64 delta;                                886         u64 delta;
887         u64 exit_time = sample->time;             887         u64 exit_time = sample->time;
888         u64 entry_time = atom->time;              888         u64 entry_time = atom->time;
889                                                   889 
890         if ((entry_time != 0) && (exit_time >=    890         if ((entry_time != 0) && (exit_time >= entry_time)) {
891                 delta = exit_time - entry_time    891                 delta = exit_time - entry_time;
892                 work->total_runtime += delta;     892                 work->total_runtime += delta;
893         }                                         893         }
894 }                                                 894 }
895                                                   895 
896 static int top_entry_event(struct perf_kwork *    896 static int top_entry_event(struct perf_kwork *kwork,
897                            struct kwork_class     897                            struct kwork_class *class,
898                            struct evsel *evsel    898                            struct evsel *evsel,
899                            struct perf_sample     899                            struct perf_sample *sample,
900                            struct machine *mac    900                            struct machine *machine)
901 {                                                 901 {
902         return work_push_atom(kwork, class, KW    902         return work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
903                               KWORK_TRACE_MAX,    903                               KWORK_TRACE_MAX, evsel, sample,
904                               machine, NULL, t    904                               machine, NULL, true);
905 }                                                 905 }
906                                                   906 
907 static int top_exit_event(struct perf_kwork *k    907 static int top_exit_event(struct perf_kwork *kwork,
908                           struct kwork_class *    908                           struct kwork_class *class,
909                           struct evsel *evsel,    909                           struct evsel *evsel,
910                           struct perf_sample *    910                           struct perf_sample *sample,
911                           struct machine *mach    911                           struct machine *machine)
912 {                                                 912 {
913         struct kwork_work *work, *sched_work;     913         struct kwork_work *work, *sched_work;
914         struct kwork_class *sched_class;          914         struct kwork_class *sched_class;
915         struct kwork_atom *atom;                  915         struct kwork_atom *atom;
916                                                   916 
917         atom = work_pop_atom(kwork, class, KWO    917         atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
918                              KWORK_TRACE_ENTRY    918                              KWORK_TRACE_ENTRY, evsel, sample,
919                              machine, &work);     919                              machine, &work);
920         if (!work)                                920         if (!work)
921                 return -1;                        921                 return -1;
922                                                   922 
923         if (atom) {                               923         if (atom) {
924                 sched_class = get_kwork_class(    924                 sched_class = get_kwork_class(kwork, KWORK_CLASS_SCHED);
925                 if (sched_class) {                925                 if (sched_class) {
926                         sched_work = find_work    926                         sched_work = find_work_by_id(&sched_class->work_root,
927                                                   927                                                      work->id, work->cpu);
928                         if (sched_work)           928                         if (sched_work)
929                                 top_update_run    929                                 top_update_runtime(work, atom, sample);
930                 }                                 930                 }
931                 atom_del(atom);                   931                 atom_del(atom);
932         }                                         932         }
933                                                   933 
934         return 0;                                 934         return 0;
935 }                                                 935 }
936                                                   936 
937 static int top_sched_switch_event(struct perf_    937 static int top_sched_switch_event(struct perf_kwork *kwork,
938                                   struct kwork    938                                   struct kwork_class *class,
939                                   struct evsel    939                                   struct evsel *evsel,
940                                   struct perf_    940                                   struct perf_sample *sample,
941                                   struct machi    941                                   struct machine *machine)
942 {                                                 942 {
943         struct kwork_atom *atom;                  943         struct kwork_atom *atom;
944         struct kwork_work *work;                  944         struct kwork_work *work;
945                                                   945 
946         atom = work_pop_atom(kwork, class, KWO    946         atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
947                              KWORK_TRACE_ENTRY    947                              KWORK_TRACE_ENTRY, evsel, sample,
948                              machine, &work);     948                              machine, &work);
949         if (!work)                                949         if (!work)
950                 return -1;                        950                 return -1;
951                                                   951 
952         if (atom) {                               952         if (atom) {
953                 top_update_runtime(work, atom,    953                 top_update_runtime(work, atom, sample);
954                 atom_del(atom);                   954                 atom_del(atom);
955         }                                         955         }
956                                                   956 
957         return top_entry_event(kwork, class, e    957         return top_entry_event(kwork, class, evsel, sample, machine);
958 }                                                 958 }
959                                                   959 
960 static struct kwork_class kwork_irq;              960 static struct kwork_class kwork_irq;
961 static int process_irq_handler_entry_event(str    961 static int process_irq_handler_entry_event(struct perf_tool *tool,
962                                            str    962                                            struct evsel *evsel,
963                                            str    963                                            struct perf_sample *sample,
964                                            str    964                                            struct machine *machine)
965 {                                                 965 {
966         struct perf_kwork *kwork = container_o    966         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
967                                                   967 
968         if (kwork->tp_handler->entry_event)       968         if (kwork->tp_handler->entry_event)
969                 return kwork->tp_handler->entr    969                 return kwork->tp_handler->entry_event(kwork, &kwork_irq,
970                                                   970                                                       evsel, sample, machine);
971         return 0;                                 971         return 0;
972 }                                                 972 }
973                                                   973 
974 static int process_irq_handler_exit_event(stru    974 static int process_irq_handler_exit_event(struct perf_tool *tool,
975                                           stru    975                                           struct evsel *evsel,
976                                           stru    976                                           struct perf_sample *sample,
977                                           stru    977                                           struct machine *machine)
978 {                                                 978 {
979         struct perf_kwork *kwork = container_o    979         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
980                                                   980 
981         if (kwork->tp_handler->exit_event)        981         if (kwork->tp_handler->exit_event)
982                 return kwork->tp_handler->exit    982                 return kwork->tp_handler->exit_event(kwork, &kwork_irq,
983                                                   983                                                      evsel, sample, machine);
984         return 0;                                 984         return 0;
985 }                                                 985 }
986                                                   986 
987 const struct evsel_str_handler irq_tp_handlers    987 const struct evsel_str_handler irq_tp_handlers[] = {
988         { "irq:irq_handler_entry", process_irq    988         { "irq:irq_handler_entry", process_irq_handler_entry_event, },
989         { "irq:irq_handler_exit",  process_irq    989         { "irq:irq_handler_exit",  process_irq_handler_exit_event,  },
990 };                                                990 };
991                                                   991 
992 static int irq_class_init(struct kwork_class *    992 static int irq_class_init(struct kwork_class *class,
993                           struct perf_session     993                           struct perf_session *session)
994 {                                                 994 {
995         if (perf_session__set_tracepoints_hand    995         if (perf_session__set_tracepoints_handlers(session, irq_tp_handlers)) {
996                 pr_err("Failed to set irq trac    996                 pr_err("Failed to set irq tracepoints handlers\n");
997                 return -1;                        997                 return -1;
998         }                                         998         }
999                                                   999 
1000         class->work_root = RB_ROOT_CACHED;       1000         class->work_root = RB_ROOT_CACHED;
1001         return 0;                                1001         return 0;
1002 }                                                1002 }
1003                                                  1003 
1004 static void irq_work_init(struct perf_kwork *    1004 static void irq_work_init(struct perf_kwork *kwork,
1005                           struct kwork_class     1005                           struct kwork_class *class,
1006                           struct kwork_work *    1006                           struct kwork_work *work,
1007                           enum kwork_trace_ty    1007                           enum kwork_trace_type src_type __maybe_unused,
1008                           struct evsel *evsel    1008                           struct evsel *evsel,
1009                           struct perf_sample     1009                           struct perf_sample *sample,
1010                           struct machine *mac    1010                           struct machine *machine __maybe_unused)
1011 {                                                1011 {
1012         work->class = class;                     1012         work->class = class;
1013         work->cpu = sample->cpu;                 1013         work->cpu = sample->cpu;
1014                                                  1014 
1015         if (kwork->report == KWORK_REPORT_TOP    1015         if (kwork->report == KWORK_REPORT_TOP) {
1016                 work->id = evsel__intval_comm    1016                 work->id = evsel__intval_common(evsel, sample, "common_pid");
1017                 work->name = NULL;               1017                 work->name = NULL;
1018         } else {                                 1018         } else {
1019                 work->id = evsel__intval(evse    1019                 work->id = evsel__intval(evsel, sample, "irq");
1020                 work->name = evsel__strval(ev    1020                 work->name = evsel__strval(evsel, sample, "name");
1021         }                                        1021         }
1022 }                                                1022 }
1023                                                  1023 
1024 static void irq_work_name(struct kwork_work *    1024 static void irq_work_name(struct kwork_work *work, char *buf, int len)
1025 {                                                1025 {
1026         snprintf(buf, len, "%s:%" PRIu64 "",     1026         snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id);
1027 }                                                1027 }
1028                                                  1028 
1029 static struct kwork_class kwork_irq = {          1029 static struct kwork_class kwork_irq = {
1030         .name           = "irq",                 1030         .name           = "irq",
1031         .type           = KWORK_CLASS_IRQ,       1031         .type           = KWORK_CLASS_IRQ,
1032         .nr_tracepoints = 2,                     1032         .nr_tracepoints = 2,
1033         .tp_handlers    = irq_tp_handlers,       1033         .tp_handlers    = irq_tp_handlers,
1034         .class_init     = irq_class_init,        1034         .class_init     = irq_class_init,
1035         .work_init      = irq_work_init,         1035         .work_init      = irq_work_init,
1036         .work_name      = irq_work_name,         1036         .work_name      = irq_work_name,
1037 };                                               1037 };
1038                                                  1038 
1039 static struct kwork_class kwork_softirq;         1039 static struct kwork_class kwork_softirq;
1040 static int process_softirq_raise_event(struct    1040 static int process_softirq_raise_event(struct perf_tool *tool,
1041                                        struct    1041                                        struct evsel *evsel,
1042                                        struct    1042                                        struct perf_sample *sample,
1043                                        struct    1043                                        struct machine *machine)
1044 {                                                1044 {
1045         struct perf_kwork *kwork = container_    1045         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1046                                                  1046 
1047         if (kwork->tp_handler->raise_event)      1047         if (kwork->tp_handler->raise_event)
1048                 return kwork->tp_handler->rai    1048                 return kwork->tp_handler->raise_event(kwork, &kwork_softirq,
1049                                                  1049                                                       evsel, sample, machine);
1050                                                  1050 
1051         return 0;                                1051         return 0;
1052 }                                                1052 }
1053                                                  1053 
1054 static int process_softirq_entry_event(struct    1054 static int process_softirq_entry_event(struct perf_tool *tool,
1055                                        struct    1055                                        struct evsel *evsel,
1056                                        struct    1056                                        struct perf_sample *sample,
1057                                        struct    1057                                        struct machine *machine)
1058 {                                                1058 {
1059         struct perf_kwork *kwork = container_    1059         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1060                                                  1060 
1061         if (kwork->tp_handler->entry_event)      1061         if (kwork->tp_handler->entry_event)
1062                 return kwork->tp_handler->ent    1062                 return kwork->tp_handler->entry_event(kwork, &kwork_softirq,
1063                                                  1063                                                       evsel, sample, machine);
1064                                                  1064 
1065         return 0;                                1065         return 0;
1066 }                                                1066 }
1067                                                  1067 
1068 static int process_softirq_exit_event(struct     1068 static int process_softirq_exit_event(struct perf_tool *tool,
1069                                       struct     1069                                       struct evsel *evsel,
1070                                       struct     1070                                       struct perf_sample *sample,
1071                                       struct     1071                                       struct machine *machine)
1072 {                                                1072 {
1073         struct perf_kwork *kwork = container_    1073         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1074                                                  1074 
1075         if (kwork->tp_handler->exit_event)       1075         if (kwork->tp_handler->exit_event)
1076                 return kwork->tp_handler->exi    1076                 return kwork->tp_handler->exit_event(kwork, &kwork_softirq,
1077                                                  1077                                                      evsel, sample, machine);
1078                                                  1078 
1079         return 0;                                1079         return 0;
1080 }                                                1080 }
1081                                                  1081 
1082 const struct evsel_str_handler softirq_tp_han    1082 const struct evsel_str_handler softirq_tp_handlers[] = {
1083         { "irq:softirq_raise", process_softir    1083         { "irq:softirq_raise", process_softirq_raise_event, },
1084         { "irq:softirq_entry", process_softir    1084         { "irq:softirq_entry", process_softirq_entry_event, },
1085         { "irq:softirq_exit",  process_softir    1085         { "irq:softirq_exit",  process_softirq_exit_event,  },
1086 };                                               1086 };
1087                                                  1087 
1088 static int softirq_class_init(struct kwork_cl    1088 static int softirq_class_init(struct kwork_class *class,
1089                               struct perf_ses    1089                               struct perf_session *session)
1090 {                                                1090 {
1091         if (perf_session__set_tracepoints_han    1091         if (perf_session__set_tracepoints_handlers(session,
1092                                                  1092                                                    softirq_tp_handlers)) {
1093                 pr_err("Failed to set softirq    1093                 pr_err("Failed to set softirq tracepoints handlers\n");
1094                 return -1;                       1094                 return -1;
1095         }                                        1095         }
1096                                                  1096 
1097         class->work_root = RB_ROOT_CACHED;       1097         class->work_root = RB_ROOT_CACHED;
1098         return 0;                                1098         return 0;
1099 }                                                1099 }
1100                                                  1100 
1101 static char *evsel__softirq_name(struct evsel    1101 static char *evsel__softirq_name(struct evsel *evsel, u64 num)
1102 {                                                1102 {
1103         char *name = NULL;                       1103         char *name = NULL;
1104         bool found = false;                      1104         bool found = false;
1105         struct tep_print_flag_sym *sym = NULL    1105         struct tep_print_flag_sym *sym = NULL;
1106         struct tep_print_arg *args = evsel->t    1106         struct tep_print_arg *args = evsel->tp_format->print_fmt.args;
1107                                                  1107 
1108         if ((args == NULL) || (args->next ==     1108         if ((args == NULL) || (args->next == NULL))
1109                 return NULL;                     1109                 return NULL;
1110                                                  1110 
1111         /* skip softirq field: "REC->vec" */     1111         /* skip softirq field: "REC->vec" */
1112         for (sym = args->next->symbol.symbols    1112         for (sym = args->next->symbol.symbols; sym != NULL; sym = sym->next) {
1113                 if ((eval_flag(sym->value) ==    1113                 if ((eval_flag(sym->value) == (unsigned long long)num) &&
1114                     (strlen(sym->str) != 0))     1114                     (strlen(sym->str) != 0)) {
1115                         found = true;            1115                         found = true;
1116                         break;                   1116                         break;
1117                 }                                1117                 }
1118         }                                        1118         }
1119                                                  1119 
1120         if (!found)                              1120         if (!found)
1121                 return NULL;                     1121                 return NULL;
1122                                                  1122 
1123         name = strdup(sym->str);                 1123         name = strdup(sym->str);
1124         if (name == NULL) {                      1124         if (name == NULL) {
1125                 pr_err("Failed to copy symbol    1125                 pr_err("Failed to copy symbol name\n");
1126                 return NULL;                     1126                 return NULL;
1127         }                                        1127         }
1128         return name;                             1128         return name;
1129 }                                                1129 }
1130                                                  1130 
1131 static void softirq_work_init(struct perf_kwo    1131 static void softirq_work_init(struct perf_kwork *kwork,
1132                               struct kwork_cl    1132                               struct kwork_class *class,
1133                               struct kwork_wo    1133                               struct kwork_work *work,
1134                               enum kwork_trac    1134                               enum kwork_trace_type src_type __maybe_unused,
1135                               struct evsel *e    1135                               struct evsel *evsel,
1136                               struct perf_sam    1136                               struct perf_sample *sample,
1137                               struct machine     1137                               struct machine *machine __maybe_unused)
1138 {                                                1138 {
1139         u64 num;                                 1139         u64 num;
1140                                                  1140 
1141         work->class = class;                     1141         work->class = class;
1142         work->cpu = sample->cpu;                 1142         work->cpu = sample->cpu;
1143                                                  1143 
1144         if (kwork->report == KWORK_REPORT_TOP    1144         if (kwork->report == KWORK_REPORT_TOP) {
1145                 work->id = evsel__intval_comm    1145                 work->id = evsel__intval_common(evsel, sample, "common_pid");
1146                 work->name = NULL;               1146                 work->name = NULL;
1147         } else {                                 1147         } else {
1148                 num = evsel__intval(evsel, sa    1148                 num = evsel__intval(evsel, sample, "vec");
1149                 work->id = num;                  1149                 work->id = num;
1150                 work->name = evsel__softirq_n    1150                 work->name = evsel__softirq_name(evsel, num);
1151         }                                        1151         }
1152 }                                                1152 }
1153                                                  1153 
1154 static void softirq_work_name(struct kwork_wo    1154 static void softirq_work_name(struct kwork_work *work, char *buf, int len)
1155 {                                                1155 {
1156         snprintf(buf, len, "(s)%s:%" PRIu64 "    1156         snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id);
1157 }                                                1157 }
1158                                                  1158 
1159 static struct kwork_class kwork_softirq = {      1159 static struct kwork_class kwork_softirq = {
1160         .name           = "softirq",             1160         .name           = "softirq",
1161         .type           = KWORK_CLASS_SOFTIRQ    1161         .type           = KWORK_CLASS_SOFTIRQ,
1162         .nr_tracepoints = 3,                     1162         .nr_tracepoints = 3,
1163         .tp_handlers    = softirq_tp_handlers    1163         .tp_handlers    = softirq_tp_handlers,
1164         .class_init     = softirq_class_init,    1164         .class_init     = softirq_class_init,
1165         .work_init      = softirq_work_init,     1165         .work_init      = softirq_work_init,
1166         .work_name      = softirq_work_name,     1166         .work_name      = softirq_work_name,
1167 };                                               1167 };
1168                                                  1168 
1169 static struct kwork_class kwork_workqueue;       1169 static struct kwork_class kwork_workqueue;
1170 static int process_workqueue_activate_work_ev    1170 static int process_workqueue_activate_work_event(struct perf_tool *tool,
1171                                                  1171                                                  struct evsel *evsel,
1172                                                  1172                                                  struct perf_sample *sample,
1173                                                  1173                                                  struct machine *machine)
1174 {                                                1174 {
1175         struct perf_kwork *kwork = container_    1175         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1176                                                  1176 
1177         if (kwork->tp_handler->raise_event)      1177         if (kwork->tp_handler->raise_event)
1178                 return kwork->tp_handler->rai    1178                 return kwork->tp_handler->raise_event(kwork, &kwork_workqueue,
1179                                                  1179                                                     evsel, sample, machine);
1180                                                  1180 
1181         return 0;                                1181         return 0;
1182 }                                                1182 }
1183                                                  1183 
1184 static int process_workqueue_execute_start_ev    1184 static int process_workqueue_execute_start_event(struct perf_tool *tool,
1185                                                  1185                                                  struct evsel *evsel,
1186                                                  1186                                                  struct perf_sample *sample,
1187                                                  1187                                                  struct machine *machine)
1188 {                                                1188 {
1189         struct perf_kwork *kwork = container_    1189         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1190                                                  1190 
1191         if (kwork->tp_handler->entry_event)      1191         if (kwork->tp_handler->entry_event)
1192                 return kwork->tp_handler->ent    1192                 return kwork->tp_handler->entry_event(kwork, &kwork_workqueue,
1193                                                  1193                                                     evsel, sample, machine);
1194                                                  1194 
1195         return 0;                                1195         return 0;
1196 }                                                1196 }
1197                                                  1197 
1198 static int process_workqueue_execute_end_even    1198 static int process_workqueue_execute_end_event(struct perf_tool *tool,
1199                                                  1199                                                struct evsel *evsel,
1200                                                  1200                                                struct perf_sample *sample,
1201                                                  1201                                                struct machine *machine)
1202 {                                                1202 {
1203         struct perf_kwork *kwork = container_    1203         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1204                                                  1204 
1205         if (kwork->tp_handler->exit_event)       1205         if (kwork->tp_handler->exit_event)
1206                 return kwork->tp_handler->exi    1206                 return kwork->tp_handler->exit_event(kwork, &kwork_workqueue,
1207                                                  1207                                                    evsel, sample, machine);
1208                                                  1208 
1209         return 0;                                1209         return 0;
1210 }                                                1210 }
1211                                                  1211 
1212 const struct evsel_str_handler workqueue_tp_h    1212 const struct evsel_str_handler workqueue_tp_handlers[] = {
1213         { "workqueue:workqueue_activate_work"    1213         { "workqueue:workqueue_activate_work", process_workqueue_activate_work_event, },
1214         { "workqueue:workqueue_execute_start"    1214         { "workqueue:workqueue_execute_start", process_workqueue_execute_start_event, },
1215         { "workqueue:workqueue_execute_end",     1215         { "workqueue:workqueue_execute_end",   process_workqueue_execute_end_event,   },
1216 };                                               1216 };
1217                                                  1217 
1218 static int workqueue_class_init(struct kwork_    1218 static int workqueue_class_init(struct kwork_class *class,
1219                                 struct perf_s    1219                                 struct perf_session *session)
1220 {                                                1220 {
1221         if (perf_session__set_tracepoints_han    1221         if (perf_session__set_tracepoints_handlers(session,
1222                                                  1222                                                    workqueue_tp_handlers)) {
1223                 pr_err("Failed to set workque    1223                 pr_err("Failed to set workqueue tracepoints handlers\n");
1224                 return -1;                       1224                 return -1;
1225         }                                        1225         }
1226                                                  1226 
1227         class->work_root = RB_ROOT_CACHED;       1227         class->work_root = RB_ROOT_CACHED;
1228         return 0;                                1228         return 0;
1229 }                                                1229 }
1230                                                  1230 
1231 static void workqueue_work_init(struct perf_k    1231 static void workqueue_work_init(struct perf_kwork *kwork __maybe_unused,
1232                                 struct kwork_    1232                                 struct kwork_class *class,
1233                                 struct kwork_    1233                                 struct kwork_work *work,
1234                                 enum kwork_tr    1234                                 enum kwork_trace_type src_type __maybe_unused,
1235                                 struct evsel     1235                                 struct evsel *evsel,
1236                                 struct perf_s    1236                                 struct perf_sample *sample,
1237                                 struct machin    1237                                 struct machine *machine)
1238 {                                                1238 {
1239         char *modp = NULL;                       1239         char *modp = NULL;
1240         unsigned long long function_addr = ev    1240         unsigned long long function_addr = evsel__intval(evsel,
1241                                                  1241                                                          sample, "function");
1242                                                  1242 
1243         work->class = class;                     1243         work->class = class;
1244         work->cpu = sample->cpu;                 1244         work->cpu = sample->cpu;
1245         work->id = evsel__intval(evsel, sampl    1245         work->id = evsel__intval(evsel, sample, "work");
1246         work->name = function_addr == 0 ? NUL    1246         work->name = function_addr == 0 ? NULL :
1247                 machine__resolve_kernel_addr(    1247                 machine__resolve_kernel_addr(machine, &function_addr, &modp);
1248 }                                                1248 }
1249                                                  1249 
1250 static void workqueue_work_name(struct kwork_    1250 static void workqueue_work_name(struct kwork_work *work, char *buf, int len)
1251 {                                                1251 {
1252         if (work->name != NULL)                  1252         if (work->name != NULL)
1253                 snprintf(buf, len, "(w)%s", w    1253                 snprintf(buf, len, "(w)%s", work->name);
1254         else                                     1254         else
1255                 snprintf(buf, len, "(w)0x%" P    1255                 snprintf(buf, len, "(w)0x%" PRIx64, work->id);
1256 }                                                1256 }
1257                                                  1257 
1258 static struct kwork_class kwork_workqueue = {    1258 static struct kwork_class kwork_workqueue = {
1259         .name           = "workqueue",           1259         .name           = "workqueue",
1260         .type           = KWORK_CLASS_WORKQUE    1260         .type           = KWORK_CLASS_WORKQUEUE,
1261         .nr_tracepoints = 3,                     1261         .nr_tracepoints = 3,
1262         .tp_handlers    = workqueue_tp_handle    1262         .tp_handlers    = workqueue_tp_handlers,
1263         .class_init     = workqueue_class_ini    1263         .class_init     = workqueue_class_init,
1264         .work_init      = workqueue_work_init    1264         .work_init      = workqueue_work_init,
1265         .work_name      = workqueue_work_name    1265         .work_name      = workqueue_work_name,
1266 };                                               1266 };
1267                                                  1267 
1268 static struct kwork_class kwork_sched;           1268 static struct kwork_class kwork_sched;
1269 static int process_sched_switch_event(struct     1269 static int process_sched_switch_event(struct perf_tool *tool,
1270                                       struct     1270                                       struct evsel *evsel,
1271                                       struct     1271                                       struct perf_sample *sample,
1272                                       struct     1272                                       struct machine *machine)
1273 {                                                1273 {
1274         struct perf_kwork *kwork = container_    1274         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
1275                                                  1275 
1276         if (kwork->tp_handler->sched_switch_e    1276         if (kwork->tp_handler->sched_switch_event)
1277                 return kwork->tp_handler->sch    1277                 return kwork->tp_handler->sched_switch_event(kwork, &kwork_sched,
1278                                                  1278                                                              evsel, sample, machine);
1279         return 0;                                1279         return 0;
1280 }                                                1280 }
1281                                                  1281 
1282 const struct evsel_str_handler sched_tp_handl    1282 const struct evsel_str_handler sched_tp_handlers[] = {
1283         { "sched:sched_switch",  process_sche    1283         { "sched:sched_switch",  process_sched_switch_event, },
1284 };                                               1284 };
1285                                                  1285 
1286 static int sched_class_init(struct kwork_clas    1286 static int sched_class_init(struct kwork_class *class,
1287                             struct perf_sessi    1287                             struct perf_session *session)
1288 {                                                1288 {
1289         if (perf_session__set_tracepoints_han    1289         if (perf_session__set_tracepoints_handlers(session,
1290                                                  1290                                                    sched_tp_handlers)) {
1291                 pr_err("Failed to set sched t    1291                 pr_err("Failed to set sched tracepoints handlers\n");
1292                 return -1;                       1292                 return -1;
1293         }                                        1293         }
1294                                                  1294 
1295         class->work_root = RB_ROOT_CACHED;       1295         class->work_root = RB_ROOT_CACHED;
1296         return 0;                                1296         return 0;
1297 }                                                1297 }
1298                                                  1298 
1299 static void sched_work_init(struct perf_kwork    1299 static void sched_work_init(struct perf_kwork *kwork __maybe_unused,
1300                             struct kwork_clas    1300                             struct kwork_class *class,
1301                             struct kwork_work    1301                             struct kwork_work *work,
1302                             enum kwork_trace_    1302                             enum kwork_trace_type src_type,
1303                             struct evsel *evs    1303                             struct evsel *evsel,
1304                             struct perf_sampl    1304                             struct perf_sample *sample,
1305                             struct machine *m    1305                             struct machine *machine __maybe_unused)
1306 {                                                1306 {
1307         work->class = class;                     1307         work->class = class;
1308         work->cpu = sample->cpu;                 1308         work->cpu = sample->cpu;
1309                                                  1309 
1310         if (src_type == KWORK_TRACE_EXIT) {      1310         if (src_type == KWORK_TRACE_EXIT) {
1311                 work->id = evsel__intval(evse    1311                 work->id = evsel__intval(evsel, sample, "prev_pid");
1312                 work->name = strdup(evsel__st    1312                 work->name = strdup(evsel__strval(evsel, sample, "prev_comm"));
1313         } else if (src_type == KWORK_TRACE_EN    1313         } else if (src_type == KWORK_TRACE_ENTRY) {
1314                 work->id = evsel__intval(evse    1314                 work->id = evsel__intval(evsel, sample, "next_pid");
1315                 work->name = strdup(evsel__st    1315                 work->name = strdup(evsel__strval(evsel, sample, "next_comm"));
1316         }                                        1316         }
1317 }                                                1317 }
1318                                                  1318 
1319 static void sched_work_name(struct kwork_work    1319 static void sched_work_name(struct kwork_work *work, char *buf, int len)
1320 {                                                1320 {
1321         snprintf(buf, len, "%s", work->name);    1321         snprintf(buf, len, "%s", work->name);
1322 }                                                1322 }
1323                                                  1323 
1324 static struct kwork_class kwork_sched = {        1324 static struct kwork_class kwork_sched = {
1325         .name           = "sched",               1325         .name           = "sched",
1326         .type           = KWORK_CLASS_SCHED,     1326         .type           = KWORK_CLASS_SCHED,
1327         .nr_tracepoints = ARRAY_SIZE(sched_tp    1327         .nr_tracepoints = ARRAY_SIZE(sched_tp_handlers),
1328         .tp_handlers    = sched_tp_handlers,     1328         .tp_handlers    = sched_tp_handlers,
1329         .class_init     = sched_class_init,      1329         .class_init     = sched_class_init,
1330         .work_init      = sched_work_init,       1330         .work_init      = sched_work_init,
1331         .work_name      = sched_work_name,       1331         .work_name      = sched_work_name,
1332 };                                               1332 };
1333                                                  1333 
1334 static struct kwork_class *kwork_class_suppor    1334 static struct kwork_class *kwork_class_supported_list[KWORK_CLASS_MAX] = {
1335         [KWORK_CLASS_IRQ]       = &kwork_irq,    1335         [KWORK_CLASS_IRQ]       = &kwork_irq,
1336         [KWORK_CLASS_SOFTIRQ]   = &kwork_soft    1336         [KWORK_CLASS_SOFTIRQ]   = &kwork_softirq,
1337         [KWORK_CLASS_WORKQUEUE] = &kwork_work    1337         [KWORK_CLASS_WORKQUEUE] = &kwork_workqueue,
1338         [KWORK_CLASS_SCHED]     = &kwork_sche    1338         [KWORK_CLASS_SCHED]     = &kwork_sched,
1339 };                                               1339 };
1340                                                  1340 
1341 static void print_separator(int len)             1341 static void print_separator(int len)
1342 {                                                1342 {
1343         printf(" %.*s\n", len, graph_dotted_l    1343         printf(" %.*s\n", len, graph_dotted_line);
1344 }                                                1344 }
1345                                                  1345 
1346 static int report_print_work(struct perf_kwor    1346 static int report_print_work(struct perf_kwork *kwork, struct kwork_work *work)
1347 {                                                1347 {
1348         int ret = 0;                             1348         int ret = 0;
1349         char kwork_name[PRINT_KWORK_NAME_WIDT    1349         char kwork_name[PRINT_KWORK_NAME_WIDTH];
1350         char max_runtime_start[32], max_runti    1350         char max_runtime_start[32], max_runtime_end[32];
1351         char max_latency_start[32], max_laten    1351         char max_latency_start[32], max_latency_end[32];
1352                                                  1352 
1353         printf(" ");                             1353         printf(" ");
1354                                                  1354 
1355         /*                                       1355         /*
1356          * kwork name                            1356          * kwork name
1357          */                                      1357          */
1358         if (work->class && work->class->work_    1358         if (work->class && work->class->work_name) {
1359                 work->class->work_name(work,     1359                 work->class->work_name(work, kwork_name,
1360                                        PRINT_    1360                                        PRINT_KWORK_NAME_WIDTH);
1361                 ret += printf(" %-*s |", PRIN    1361                 ret += printf(" %-*s |", PRINT_KWORK_NAME_WIDTH, kwork_name);
1362         } else {                                 1362         } else {
1363                 ret += printf(" %-*s |", PRIN    1363                 ret += printf(" %-*s |", PRINT_KWORK_NAME_WIDTH, "");
1364         }                                        1364         }
1365                                                  1365 
1366         /*                                       1366         /*
1367          * cpu                                   1367          * cpu
1368          */                                      1368          */
1369         ret += printf(" %0*d |", PRINT_CPU_WI    1369         ret += printf(" %0*d |", PRINT_CPU_WIDTH, work->cpu);
1370                                                  1370 
1371         /*                                       1371         /*
1372          * total runtime                         1372          * total runtime
1373          */                                      1373          */
1374         if (kwork->report == KWORK_REPORT_RUN    1374         if (kwork->report == KWORK_REPORT_RUNTIME) {
1375                 ret += printf(" %*.*f ms |",     1375                 ret += printf(" %*.*f ms |",
1376                               PRINT_RUNTIME_W    1376                               PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
1377                               (double)work->t    1377                               (double)work->total_runtime / NSEC_PER_MSEC);
1378         } else if (kwork->report == KWORK_REP    1378         } else if (kwork->report == KWORK_REPORT_LATENCY) { // avg delay
1379                 ret += printf(" %*.*f ms |",     1379                 ret += printf(" %*.*f ms |",
1380                               PRINT_LATENCY_W    1380                               PRINT_LATENCY_WIDTH, RPINT_DECIMAL_WIDTH,
1381                               (double)work->t    1381                               (double)work->total_latency /
1382                               work->nr_atoms     1382                               work->nr_atoms / NSEC_PER_MSEC);
1383         }                                        1383         }
1384                                                  1384 
1385         /*                                       1385         /*
1386          * count                                 1386          * count
1387          */                                      1387          */
1388         ret += printf(" %*" PRIu64 " |", PRIN    1388         ret += printf(" %*" PRIu64 " |", PRINT_COUNT_WIDTH, work->nr_atoms);
1389                                                  1389 
1390         /*                                       1390         /*
1391          * max runtime, max runtime start, ma    1391          * max runtime, max runtime start, max runtime end
1392          */                                      1392          */
1393         if (kwork->report == KWORK_REPORT_RUN    1393         if (kwork->report == KWORK_REPORT_RUNTIME) {
1394                 timestamp__scnprintf_usec(wor    1394                 timestamp__scnprintf_usec(work->max_runtime_start,
1395                                           max    1395                                           max_runtime_start,
1396                                           siz    1396                                           sizeof(max_runtime_start));
1397                 timestamp__scnprintf_usec(wor    1397                 timestamp__scnprintf_usec(work->max_runtime_end,
1398                                           max    1398                                           max_runtime_end,
1399                                           siz    1399                                           sizeof(max_runtime_end));
1400                 ret += printf(" %*.*f ms | %*    1400                 ret += printf(" %*.*f ms | %*s s | %*s s |",
1401                               PRINT_RUNTIME_W    1401                               PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
1402                               (double)work->m    1402                               (double)work->max_runtime / NSEC_PER_MSEC,
1403                               PRINT_TIMESTAMP    1403                               PRINT_TIMESTAMP_WIDTH, max_runtime_start,
1404                               PRINT_TIMESTAMP    1404                               PRINT_TIMESTAMP_WIDTH, max_runtime_end);
1405         }                                        1405         }
1406         /*                                       1406         /*
1407          * max delay, max delay start, max de    1407          * max delay, max delay start, max delay end
1408          */                                      1408          */
1409         else if (kwork->report == KWORK_REPOR    1409         else if (kwork->report == KWORK_REPORT_LATENCY) {
1410                 timestamp__scnprintf_usec(wor    1410                 timestamp__scnprintf_usec(work->max_latency_start,
1411                                           max    1411                                           max_latency_start,
1412                                           siz    1412                                           sizeof(max_latency_start));
1413                 timestamp__scnprintf_usec(wor    1413                 timestamp__scnprintf_usec(work->max_latency_end,
1414                                           max    1414                                           max_latency_end,
1415                                           siz    1415                                           sizeof(max_latency_end));
1416                 ret += printf(" %*.*f ms | %*    1416                 ret += printf(" %*.*f ms | %*s s | %*s s |",
1417                               PRINT_LATENCY_W    1417                               PRINT_LATENCY_WIDTH, RPINT_DECIMAL_WIDTH,
1418                               (double)work->m    1418                               (double)work->max_latency / NSEC_PER_MSEC,
1419                               PRINT_TIMESTAMP    1419                               PRINT_TIMESTAMP_WIDTH, max_latency_start,
1420                               PRINT_TIMESTAMP    1420                               PRINT_TIMESTAMP_WIDTH, max_latency_end);
1421         }                                        1421         }
1422                                                  1422 
1423         printf("\n");                            1423         printf("\n");
1424         return ret;                              1424         return ret;
1425 }                                                1425 }
1426                                                  1426 
1427 static int report_print_header(struct perf_kw    1427 static int report_print_header(struct perf_kwork *kwork)
1428 {                                                1428 {
1429         int ret;                                 1429         int ret;
1430                                                  1430 
1431         printf("\n ");                           1431         printf("\n ");
1432         ret = printf(" %-*s | %-*s |",           1432         ret = printf(" %-*s | %-*s |",
1433                      PRINT_KWORK_NAME_WIDTH,     1433                      PRINT_KWORK_NAME_WIDTH, "Kwork Name",
1434                      PRINT_CPU_WIDTH, "Cpu");    1434                      PRINT_CPU_WIDTH, "Cpu");
1435                                                  1435 
1436         if (kwork->report == KWORK_REPORT_RUN    1436         if (kwork->report == KWORK_REPORT_RUNTIME) {
1437                 ret += printf(" %-*s |",         1437                 ret += printf(" %-*s |",
1438                               PRINT_RUNTIME_H    1438                               PRINT_RUNTIME_HEADER_WIDTH, "Total Runtime");
1439         } else if (kwork->report == KWORK_REP    1439         } else if (kwork->report == KWORK_REPORT_LATENCY) {
1440                 ret += printf(" %-*s |",         1440                 ret += printf(" %-*s |",
1441                               PRINT_LATENCY_H    1441                               PRINT_LATENCY_HEADER_WIDTH, "Avg delay");
1442         }                                        1442         }
1443                                                  1443 
1444         ret += printf(" %-*s |", PRINT_COUNT_    1444         ret += printf(" %-*s |", PRINT_COUNT_WIDTH, "Count");
1445                                                  1445 
1446         if (kwork->report == KWORK_REPORT_RUN    1446         if (kwork->report == KWORK_REPORT_RUNTIME) {
1447                 ret += printf(" %-*s | %-*s |    1447                 ret += printf(" %-*s | %-*s | %-*s |",
1448                               PRINT_RUNTIME_H    1448                               PRINT_RUNTIME_HEADER_WIDTH, "Max runtime",
1449                               PRINT_TIMESTAMP    1449                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max runtime start",
1450                               PRINT_TIMESTAMP    1450                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max runtime end");
1451         } else if (kwork->report == KWORK_REP    1451         } else if (kwork->report == KWORK_REPORT_LATENCY) {
1452                 ret += printf(" %-*s | %-*s |    1452                 ret += printf(" %-*s | %-*s | %-*s |",
1453                               PRINT_LATENCY_H    1453                               PRINT_LATENCY_HEADER_WIDTH, "Max delay",
1454                               PRINT_TIMESTAMP    1454                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max delay start",
1455                               PRINT_TIMESTAMP    1455                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max delay end");
1456         }                                        1456         }
1457                                                  1457 
1458         printf("\n");                            1458         printf("\n");
1459         print_separator(ret);                    1459         print_separator(ret);
1460         return ret;                              1460         return ret;
1461 }                                                1461 }
1462                                                  1462 
1463 static void timehist_print_header(void)          1463 static void timehist_print_header(void)
1464 {                                                1464 {
1465         /*                                       1465         /*
1466          * header row                            1466          * header row
1467          */                                      1467          */
1468         printf(" %-*s  %-*s  %-*s  %-*s  %-*s    1468         printf(" %-*s  %-*s  %-*s  %-*s  %-*s  %-*s\n",
1469                PRINT_TIMESTAMP_WIDTH, "Runtim    1469                PRINT_TIMESTAMP_WIDTH, "Runtime start",
1470                PRINT_TIMESTAMP_WIDTH, "Runtim    1470                PRINT_TIMESTAMP_WIDTH, "Runtime end",
1471                PRINT_TIMEHIST_CPU_WIDTH, "Cpu    1471                PRINT_TIMEHIST_CPU_WIDTH, "Cpu",
1472                PRINT_KWORK_NAME_WIDTH, "Kwork    1472                PRINT_KWORK_NAME_WIDTH, "Kwork name",
1473                PRINT_RUNTIME_WIDTH, "Runtime"    1473                PRINT_RUNTIME_WIDTH, "Runtime",
1474                PRINT_RUNTIME_WIDTH, "Delaytim    1474                PRINT_RUNTIME_WIDTH, "Delaytime");
1475                                                  1475 
1476         /*                                       1476         /*
1477          * units row                             1477          * units row
1478          */                                      1478          */
1479         printf(" %-*s  %-*s  %-*s  %-*s  %-*s    1479         printf(" %-*s  %-*s  %-*s  %-*s  %-*s  %-*s\n",
1480                PRINT_TIMESTAMP_WIDTH, "",        1480                PRINT_TIMESTAMP_WIDTH, "",
1481                PRINT_TIMESTAMP_WIDTH, "",        1481                PRINT_TIMESTAMP_WIDTH, "",
1482                PRINT_TIMEHIST_CPU_WIDTH, "",     1482                PRINT_TIMEHIST_CPU_WIDTH, "",
1483                PRINT_KWORK_NAME_WIDTH, "(TYPE    1483                PRINT_KWORK_NAME_WIDTH, "(TYPE)NAME:NUM",
1484                PRINT_RUNTIME_WIDTH, "(msec)",    1484                PRINT_RUNTIME_WIDTH, "(msec)",
1485                PRINT_RUNTIME_WIDTH, "(msec)")    1485                PRINT_RUNTIME_WIDTH, "(msec)");
1486                                                  1486 
1487         /*                                       1487         /*
1488          * separator                             1488          * separator
1489          */                                      1489          */
1490         printf(" %.*s  %.*s  %.*s  %.*s  %.*s    1490         printf(" %.*s  %.*s  %.*s  %.*s  %.*s  %.*s\n",
1491                PRINT_TIMESTAMP_WIDTH, graph_d    1491                PRINT_TIMESTAMP_WIDTH, graph_dotted_line,
1492                PRINT_TIMESTAMP_WIDTH, graph_d    1492                PRINT_TIMESTAMP_WIDTH, graph_dotted_line,
1493                PRINT_TIMEHIST_CPU_WIDTH, grap    1493                PRINT_TIMEHIST_CPU_WIDTH, graph_dotted_line,
1494                PRINT_KWORK_NAME_WIDTH, graph_    1494                PRINT_KWORK_NAME_WIDTH, graph_dotted_line,
1495                PRINT_RUNTIME_WIDTH, graph_dot    1495                PRINT_RUNTIME_WIDTH, graph_dotted_line,
1496                PRINT_RUNTIME_WIDTH, graph_dot    1496                PRINT_RUNTIME_WIDTH, graph_dotted_line);
1497 }                                                1497 }
1498                                                  1498 
1499 static void print_summary(struct perf_kwork *    1499 static void print_summary(struct perf_kwork *kwork)
1500 {                                                1500 {
1501         u64 time = kwork->timeend - kwork->ti    1501         u64 time = kwork->timeend - kwork->timestart;
1502                                                  1502 
1503         printf("  Total count            : %9    1503         printf("  Total count            : %9" PRIu64 "\n", kwork->all_count);
1504         printf("  Total runtime   (msec) : %9    1504         printf("  Total runtime   (msec) : %9.3f (%.3f%% load average)\n",
1505                (double)kwork->all_runtime / N    1505                (double)kwork->all_runtime / NSEC_PER_MSEC,
1506                time == 0 ? 0 : (double)kwork-    1506                time == 0 ? 0 : (double)kwork->all_runtime / time);
1507         printf("  Total time span (msec) : %9    1507         printf("  Total time span (msec) : %9.3f\n",
1508                (double)time / NSEC_PER_MSEC);    1508                (double)time / NSEC_PER_MSEC);
1509 }                                                1509 }
1510                                                  1510 
1511 static unsigned long long nr_list_entry(struc    1511 static unsigned long long nr_list_entry(struct list_head *head)
1512 {                                                1512 {
1513         struct list_head *pos;                   1513         struct list_head *pos;
1514         unsigned long long n = 0;                1514         unsigned long long n = 0;
1515                                                  1515 
1516         list_for_each(pos, head)                 1516         list_for_each(pos, head)
1517                 n++;                             1517                 n++;
1518                                                  1518 
1519         return n;                                1519         return n;
1520 }                                                1520 }
1521                                                  1521 
1522 static void print_skipped_events(struct perf_    1522 static void print_skipped_events(struct perf_kwork *kwork)
1523 {                                                1523 {
1524         int i;                                   1524         int i;
1525         const char *const kwork_event_str[] =    1525         const char *const kwork_event_str[] = {
1526                 [KWORK_TRACE_RAISE] = "raise"    1526                 [KWORK_TRACE_RAISE] = "raise",
1527                 [KWORK_TRACE_ENTRY] = "entry"    1527                 [KWORK_TRACE_ENTRY] = "entry",
1528                 [KWORK_TRACE_EXIT]  = "exit",    1528                 [KWORK_TRACE_EXIT]  = "exit",
1529         };                                       1529         };
1530                                                  1530 
1531         if ((kwork->nr_skipped_events[KWORK_T    1531         if ((kwork->nr_skipped_events[KWORK_TRACE_MAX] != 0) &&
1532             (kwork->nr_events != 0)) {           1532             (kwork->nr_events != 0)) {
1533                 printf("  INFO: %.3f%% skippe    1533                 printf("  INFO: %.3f%% skipped events (%" PRIu64 " including ",
1534                        (double)kwork->nr_skip    1534                        (double)kwork->nr_skipped_events[KWORK_TRACE_MAX] /
1535                        (double)kwork->nr_even    1535                        (double)kwork->nr_events * 100.0,
1536                        kwork->nr_skipped_even    1536                        kwork->nr_skipped_events[KWORK_TRACE_MAX]);
1537                                                  1537 
1538                 for (i = 0; i < KWORK_TRACE_M    1538                 for (i = 0; i < KWORK_TRACE_MAX; i++) {
1539                         printf("%" PRIu64 " %    1539                         printf("%" PRIu64 " %s%s",
1540                                kwork->nr_skip    1540                                kwork->nr_skipped_events[i],
1541                                kwork_event_st    1541                                kwork_event_str[i],
1542                                (i == KWORK_TR    1542                                (i == KWORK_TRACE_MAX - 1) ? ")\n" : ", ");
1543                 }                                1543                 }
1544         }                                        1544         }
1545                                                  1545 
1546         if (verbose > 0)                         1546         if (verbose > 0)
1547                 printf("  INFO: use %lld atom    1547                 printf("  INFO: use %lld atom pages\n",
1548                        nr_list_entry(&kwork->    1548                        nr_list_entry(&kwork->atom_page_list));
1549 }                                                1549 }
1550                                                  1550 
1551 static void print_bad_events(struct perf_kwor    1551 static void print_bad_events(struct perf_kwork *kwork)
1552 {                                                1552 {
1553         if ((kwork->nr_lost_events != 0) && (    1553         if ((kwork->nr_lost_events != 0) && (kwork->nr_events != 0)) {
1554                 printf("  INFO: %.3f%% lost e    1554                 printf("  INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n",
1555                        (double)kwork->nr_lost    1555                        (double)kwork->nr_lost_events /
1556                        (double)kwork->nr_even    1556                        (double)kwork->nr_events * 100.0,
1557                        kwork->nr_lost_events,    1557                        kwork->nr_lost_events, kwork->nr_events,
1558                        kwork->nr_lost_chunks)    1558                        kwork->nr_lost_chunks);
1559         }                                        1559         }
1560 }                                                1560 }
1561                                                  1561 
1562 const char *graph_load = "|||||||||||||||||||    1562 const char *graph_load = "||||||||||||||||||||||||||||||||||||||||||||||||";
1563 const char *graph_idle = "                       1563 const char *graph_idle = "                                                ";
1564 static void top_print_per_cpu_load(struct per    1564 static void top_print_per_cpu_load(struct perf_kwork *kwork)
1565 {                                                1565 {
1566         int i, load_width;                       1566         int i, load_width;
1567         u64 total, load, load_ratio;             1567         u64 total, load, load_ratio;
1568         struct kwork_top_stat *stat = &kwork-    1568         struct kwork_top_stat *stat = &kwork->top_stat;
1569                                                  1569 
1570         for (i = 0; i < MAX_NR_CPUS; i++) {      1570         for (i = 0; i < MAX_NR_CPUS; i++) {
1571                 total = stat->cpus_runtime[i]    1571                 total = stat->cpus_runtime[i].total;
1572                 load = stat->cpus_runtime[i].    1572                 load = stat->cpus_runtime[i].load;
1573                 if (test_bit(i, stat->all_cpu    1573                 if (test_bit(i, stat->all_cpus_bitmap) && total) {
1574                         load_ratio = load * 1    1574                         load_ratio = load * 10000 / total;
1575                         load_width = PRINT_CP    1575                         load_width = PRINT_CPU_USAGE_HIST_WIDTH *
1576                                 load_ratio /     1576                                 load_ratio / 10000;
1577                                                  1577 
1578                         printf("%%Cpu%-*d[%.*    1578                         printf("%%Cpu%-*d[%.*s%.*s %*.*f%%]\n",
1579                                PRINT_CPU_WIDT    1579                                PRINT_CPU_WIDTH, i,
1580                                load_width, gr    1580                                load_width, graph_load,
1581                                PRINT_CPU_USAG    1581                                PRINT_CPU_USAGE_HIST_WIDTH - load_width,
1582                                graph_idle,       1582                                graph_idle,
1583                                PRINT_CPU_USAG    1583                                PRINT_CPU_USAGE_WIDTH,
1584                                PRINT_CPU_USAG    1584                                PRINT_CPU_USAGE_DECIMAL_WIDTH,
1585                                (double)load_r    1585                                (double)load_ratio / 100);
1586                 }                                1586                 }
1587         }                                        1587         }
1588 }                                                1588 }
1589                                                  1589 
1590 static void top_print_cpu_usage(struct perf_k    1590 static void top_print_cpu_usage(struct perf_kwork *kwork)
1591 {                                                1591 {
1592         struct kwork_top_stat *stat = &kwork-    1592         struct kwork_top_stat *stat = &kwork->top_stat;
1593         u64 idle_time = stat->cpus_runtime[MA    1593         u64 idle_time = stat->cpus_runtime[MAX_NR_CPUS].idle;
1594         u64 hardirq_time = stat->cpus_runtime    1594         u64 hardirq_time = stat->cpus_runtime[MAX_NR_CPUS].irq;
1595         u64 softirq_time = stat->cpus_runtime    1595         u64 softirq_time = stat->cpus_runtime[MAX_NR_CPUS].softirq;
1596         int cpus_nr = bitmap_weight(stat->all    1596         int cpus_nr = bitmap_weight(stat->all_cpus_bitmap, MAX_NR_CPUS);
1597         u64 cpus_total_time = stat->cpus_runt    1597         u64 cpus_total_time = stat->cpus_runtime[MAX_NR_CPUS].total;
1598                                                  1598 
1599         printf("Total  : %*.*f ms, %d cpus\n"    1599         printf("Total  : %*.*f ms, %d cpus\n",
1600                PRINT_RUNTIME_WIDTH, RPINT_DEC    1600                PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
1601                (double)cpus_total_time / NSEC    1601                (double)cpus_total_time / NSEC_PER_MSEC,
1602                cpus_nr);                         1602                cpus_nr);
1603                                                  1603 
1604         printf("%%Cpu(s): %*.*f%% id, %*.*f%%    1604         printf("%%Cpu(s): %*.*f%% id, %*.*f%% hi, %*.*f%% si\n",
1605                PRINT_CPU_USAGE_WIDTH, PRINT_C    1605                PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH,
1606                cpus_total_time ? (double)idle    1606                cpus_total_time ? (double)idle_time * 100 / cpus_total_time : 0,
1607                                                  1607 
1608                PRINT_CPU_USAGE_WIDTH, PRINT_C    1608                PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH,
1609                cpus_total_time ? (double)hard    1609                cpus_total_time ? (double)hardirq_time * 100 / cpus_total_time : 0,
1610                                                  1610 
1611                PRINT_CPU_USAGE_WIDTH, PRINT_C    1611                PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH,
1612                cpus_total_time ? (double)soft    1612                cpus_total_time ? (double)softirq_time * 100 / cpus_total_time : 0);
1613                                                  1613 
1614         top_print_per_cpu_load(kwork);           1614         top_print_per_cpu_load(kwork);
1615 }                                                1615 }
1616                                                  1616 
1617 static void top_print_header(struct perf_kwor    1617 static void top_print_header(struct perf_kwork *kwork __maybe_unused)
1618 {                                                1618 {
1619         int ret;                                 1619         int ret;
1620                                                  1620 
1621         printf("\n ");                           1621         printf("\n ");
1622         ret = printf(" %*s %s%*s%s %*s  %*s      1622         ret = printf(" %*s %s%*s%s %*s  %*s  %-*s",
1623                      PRINT_PID_WIDTH, "PID",     1623                      PRINT_PID_WIDTH, "PID",
1624                                                  1624 
1625                      kwork->use_bpf ? " " : "    1625                      kwork->use_bpf ? " " : "",
1626                      kwork->use_bpf ? PRINT_P    1626                      kwork->use_bpf ? PRINT_PID_WIDTH : 0,
1627                      kwork->use_bpf ? "SPID"     1627                      kwork->use_bpf ? "SPID" : "",
1628                      kwork->use_bpf ? " " : "    1628                      kwork->use_bpf ? " " : "",
1629                                                  1629 
1630                      PRINT_CPU_USAGE_WIDTH, "    1630                      PRINT_CPU_USAGE_WIDTH, "%CPU",
1631                      PRINT_RUNTIME_HEADER_WID    1631                      PRINT_RUNTIME_HEADER_WIDTH + RPINT_DECIMAL_WIDTH, "RUNTIME",
1632                      PRINT_TASK_NAME_WIDTH, "    1632                      PRINT_TASK_NAME_WIDTH, "COMMAND");
1633         printf("\n ");                           1633         printf("\n ");
1634         print_separator(ret);                    1634         print_separator(ret);
1635 }                                                1635 }
1636                                                  1636 
1637 static int top_print_work(struct perf_kwork *    1637 static int top_print_work(struct perf_kwork *kwork __maybe_unused, struct kwork_work *work)
1638 {                                                1638 {
1639         int ret = 0;                             1639         int ret = 0;
1640                                                  1640 
1641         printf(" ");                             1641         printf(" ");
1642                                                  1642 
1643         /*                                       1643         /*
1644          * pid                                   1644          * pid
1645          */                                      1645          */
1646         ret += printf(" %*" PRIu64 " ", PRINT    1646         ret += printf(" %*" PRIu64 " ", PRINT_PID_WIDTH, work->id);
1647                                                  1647 
1648         /*                                       1648         /*
1649          * tgid                                  1649          * tgid
1650          */                                      1650          */
1651         if (kwork->use_bpf)                      1651         if (kwork->use_bpf)
1652                 ret += printf(" %*d ", PRINT_    1652                 ret += printf(" %*d ", PRINT_PID_WIDTH, work->tgid);
1653                                                  1653 
1654         /*                                       1654         /*
1655          * cpu usage                             1655          * cpu usage
1656          */                                      1656          */
1657         ret += printf(" %*.*f ",                 1657         ret += printf(" %*.*f ",
1658                       PRINT_CPU_USAGE_WIDTH,     1658                       PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH,
1659                       (double)work->cpu_usage    1659                       (double)work->cpu_usage / 100);
1660                                                  1660 
1661         /*                                       1661         /*
1662          * total runtime                         1662          * total runtime
1663          */                                      1663          */
1664         ret += printf(" %*.*f ms ",              1664         ret += printf(" %*.*f ms ",
1665                       PRINT_RUNTIME_WIDTH + R    1665                       PRINT_RUNTIME_WIDTH + RPINT_DECIMAL_WIDTH, RPINT_DECIMAL_WIDTH,
1666                       (double)work->total_run    1666                       (double)work->total_runtime / NSEC_PER_MSEC);
1667                                                  1667 
1668         /*                                       1668         /*
1669          * command                               1669          * command
1670          */                                      1670          */
1671         if (kwork->use_bpf)                      1671         if (kwork->use_bpf)
1672                 ret += printf(" %s%s%s",         1672                 ret += printf(" %s%s%s",
1673                               work->is_kthrea    1673                               work->is_kthread ? "[" : "",
1674                               work->name,        1674                               work->name,
1675                               work->is_kthrea    1675                               work->is_kthread ? "]" : "");
1676         else                                     1676         else
1677                 ret += printf(" %-*s", PRINT_    1677                 ret += printf(" %-*s", PRINT_TASK_NAME_WIDTH, work->name);
1678                                                  1678 
1679         printf("\n");                            1679         printf("\n");
1680         return ret;                              1680         return ret;
1681 }                                                1681 }
1682                                                  1682 
1683 static void work_sort(struct perf_kwork *kwor    1683 static void work_sort(struct perf_kwork *kwork,
1684                       struct kwork_class *cla    1684                       struct kwork_class *class, struct rb_root_cached *root)
1685 {                                                1685 {
1686         struct rb_node *node;                    1686         struct rb_node *node;
1687         struct kwork_work *data;                 1687         struct kwork_work *data;
1688                                                  1688 
1689         pr_debug("Sorting %s ...\n", class->n    1689         pr_debug("Sorting %s ...\n", class->name);
1690         for (;;) {                               1690         for (;;) {
1691                 node = rb_first_cached(root);    1691                 node = rb_first_cached(root);
1692                 if (!node)                       1692                 if (!node)
1693                         break;                   1693                         break;
1694                                                  1694 
1695                 rb_erase_cached(node, root);     1695                 rb_erase_cached(node, root);
1696                 data = rb_entry(node, struct     1696                 data = rb_entry(node, struct kwork_work, node);
1697                 work_insert(&kwork->sorted_wo    1697                 work_insert(&kwork->sorted_work_root,
1698                                data, &kwork->    1698                                data, &kwork->sort_list);
1699         }                                        1699         }
1700 }                                                1700 }
1701                                                  1701 
1702 static void perf_kwork__sort(struct perf_kwor    1702 static void perf_kwork__sort(struct perf_kwork *kwork)
1703 {                                                1703 {
1704         struct kwork_class *class;               1704         struct kwork_class *class;
1705                                                  1705 
1706         list_for_each_entry(class, &kwork->cl    1706         list_for_each_entry(class, &kwork->class_list, list)
1707                 work_sort(kwork, class, &clas    1707                 work_sort(kwork, class, &class->work_root);
1708 }                                                1708 }
1709                                                  1709 
1710 static int perf_kwork__check_config(struct pe    1710 static int perf_kwork__check_config(struct perf_kwork *kwork,
1711                                     struct pe    1711                                     struct perf_session *session)
1712 {                                                1712 {
1713         int ret;                                 1713         int ret;
1714         struct evsel *evsel;                     1714         struct evsel *evsel;
1715         struct kwork_class *class;               1715         struct kwork_class *class;
1716                                                  1716 
1717         static struct trace_kwork_handler rep    1717         static struct trace_kwork_handler report_ops = {
1718                 .entry_event = report_entry_e    1718                 .entry_event = report_entry_event,
1719                 .exit_event  = report_exit_ev    1719                 .exit_event  = report_exit_event,
1720         };                                       1720         };
1721         static struct trace_kwork_handler lat    1721         static struct trace_kwork_handler latency_ops = {
1722                 .raise_event = latency_raise_    1722                 .raise_event = latency_raise_event,
1723                 .entry_event = latency_entry_    1723                 .entry_event = latency_entry_event,
1724         };                                       1724         };
1725         static struct trace_kwork_handler tim    1725         static struct trace_kwork_handler timehist_ops = {
1726                 .raise_event = timehist_raise    1726                 .raise_event = timehist_raise_event,
1727                 .entry_event = timehist_entry    1727                 .entry_event = timehist_entry_event,
1728                 .exit_event  = timehist_exit_    1728                 .exit_event  = timehist_exit_event,
1729         };                                       1729         };
1730         static struct trace_kwork_handler top    1730         static struct trace_kwork_handler top_ops = {
1731                 .entry_event        = timehis    1731                 .entry_event        = timehist_entry_event,
1732                 .exit_event         = top_exi    1732                 .exit_event         = top_exit_event,
1733                 .sched_switch_event = top_sch    1733                 .sched_switch_event = top_sched_switch_event,
1734         };                                       1734         };
1735                                                  1735 
1736         switch (kwork->report) {                 1736         switch (kwork->report) {
1737         case KWORK_REPORT_RUNTIME:               1737         case KWORK_REPORT_RUNTIME:
1738                 kwork->tp_handler = &report_o    1738                 kwork->tp_handler = &report_ops;
1739                 break;                           1739                 break;
1740         case KWORK_REPORT_LATENCY:               1740         case KWORK_REPORT_LATENCY:
1741                 kwork->tp_handler = &latency_    1741                 kwork->tp_handler = &latency_ops;
1742                 break;                           1742                 break;
1743         case KWORK_REPORT_TIMEHIST:              1743         case KWORK_REPORT_TIMEHIST:
1744                 kwork->tp_handler = &timehist    1744                 kwork->tp_handler = &timehist_ops;
1745                 break;                           1745                 break;
1746         case KWORK_REPORT_TOP:                   1746         case KWORK_REPORT_TOP:
1747                 kwork->tp_handler = &top_ops;    1747                 kwork->tp_handler = &top_ops;
1748                 break;                           1748                 break;
1749         default:                                 1749         default:
1750                 pr_debug("Invalid report type    1750                 pr_debug("Invalid report type %d\n", kwork->report);
1751                 return -1;                       1751                 return -1;
1752         }                                        1752         }
1753                                                  1753 
1754         list_for_each_entry(class, &kwork->cl    1754         list_for_each_entry(class, &kwork->class_list, list)
1755                 if ((class->class_init != NUL    1755                 if ((class->class_init != NULL) &&
1756                     (class->class_init(class,    1756                     (class->class_init(class, session) != 0))
1757                         return -1;               1757                         return -1;
1758                                                  1758 
1759         if (kwork->cpu_list != NULL) {           1759         if (kwork->cpu_list != NULL) {
1760                 ret = perf_session__cpu_bitma    1760                 ret = perf_session__cpu_bitmap(session,
1761                                                  1761                                                kwork->cpu_list,
1762                                                  1762                                                kwork->cpu_bitmap);
1763                 if (ret < 0) {                   1763                 if (ret < 0) {
1764                         pr_err("Invalid cpu b    1764                         pr_err("Invalid cpu bitmap\n");
1765                         return -1;               1765                         return -1;
1766                 }                                1766                 }
1767         }                                        1767         }
1768                                                  1768 
1769         if (kwork->time_str != NULL) {           1769         if (kwork->time_str != NULL) {
1770                 ret = perf_time__parse_str(&k    1770                 ret = perf_time__parse_str(&kwork->ptime, kwork->time_str);
1771                 if (ret != 0) {                  1771                 if (ret != 0) {
1772                         pr_err("Invalid time     1772                         pr_err("Invalid time span\n");
1773                         return -1;               1773                         return -1;
1774                 }                                1774                 }
1775         }                                        1775         }
1776                                                  1776 
1777         list_for_each_entry(evsel, &session->    1777         list_for_each_entry(evsel, &session->evlist->core.entries, core.node) {
1778                 if (kwork->show_callchain &&     1778                 if (kwork->show_callchain && !evsel__has_callchain(evsel)) {
1779                         pr_debug("Samples do     1779                         pr_debug("Samples do not have callchains\n");
1780                         kwork->show_callchain    1780                         kwork->show_callchain = 0;
1781                         symbol_conf.use_callc    1781                         symbol_conf.use_callchain = 0;
1782                 }                                1782                 }
1783         }                                        1783         }
1784                                                  1784 
1785         return 0;                                1785         return 0;
1786 }                                                1786 }
1787                                                  1787 
1788 static int perf_kwork__read_events(struct per    1788 static int perf_kwork__read_events(struct perf_kwork *kwork)
1789 {                                                1789 {
1790         int ret = -1;                            1790         int ret = -1;
1791         struct perf_session *session = NULL;     1791         struct perf_session *session = NULL;
1792                                                  1792 
1793         struct perf_data data = {                1793         struct perf_data data = {
1794                 .path  = input_name,             1794                 .path  = input_name,
1795                 .mode  = PERF_DATA_MODE_READ,    1795                 .mode  = PERF_DATA_MODE_READ,
1796                 .force = kwork->force,           1796                 .force = kwork->force,
1797         };                                       1797         };
1798                                                  1798 
1799         session = perf_session__new(&data, &k    1799         session = perf_session__new(&data, &kwork->tool);
1800         if (IS_ERR(session)) {                   1800         if (IS_ERR(session)) {
1801                 pr_debug("Error creating perf    1801                 pr_debug("Error creating perf session\n");
1802                 return PTR_ERR(session);         1802                 return PTR_ERR(session);
1803         }                                        1803         }
1804                                                  1804 
1805         symbol__init(&session->header.env);      1805         symbol__init(&session->header.env);
1806                                                  1806 
1807         if (perf_kwork__check_config(kwork, s    1807         if (perf_kwork__check_config(kwork, session) != 0)
1808                 goto out_delete;                 1808                 goto out_delete;
1809                                                  1809 
1810         if (session->tevent.pevent &&            1810         if (session->tevent.pevent &&
1811             tep_set_function_resolver(session    1811             tep_set_function_resolver(session->tevent.pevent,
1812                                       machine    1812                                       machine__resolve_kernel_addr,
1813                                       &sessio    1813                                       &session->machines.host) < 0) {
1814                 pr_err("Failed to set libtrac    1814                 pr_err("Failed to set libtraceevent function resolver\n");
1815                 goto out_delete;                 1815                 goto out_delete;
1816         }                                        1816         }
1817                                                  1817 
1818         if (kwork->report == KWORK_REPORT_TIM    1818         if (kwork->report == KWORK_REPORT_TIMEHIST)
1819                 timehist_print_header();         1819                 timehist_print_header();
1820                                                  1820 
1821         ret = perf_session__process_events(se    1821         ret = perf_session__process_events(session);
1822         if (ret) {                               1822         if (ret) {
1823                 pr_debug("Failed to process e    1823                 pr_debug("Failed to process events, error %d\n", ret);
1824                 goto out_delete;                 1824                 goto out_delete;
1825         }                                        1825         }
1826                                                  1826 
1827         kwork->nr_events      = session->evli    1827         kwork->nr_events      = session->evlist->stats.nr_events[0];
1828         kwork->nr_lost_events = session->evli    1828         kwork->nr_lost_events = session->evlist->stats.total_lost;
1829         kwork->nr_lost_chunks = session->evli    1829         kwork->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1830                                                  1830 
1831 out_delete:                                      1831 out_delete:
1832         perf_session__delete(session);           1832         perf_session__delete(session);
1833         return ret;                              1833         return ret;
1834 }                                                1834 }
1835                                                  1835 
1836 static void process_skipped_events(struct per    1836 static void process_skipped_events(struct perf_kwork *kwork,
1837                                    struct kwo    1837                                    struct kwork_work *work)
1838 {                                                1838 {
1839         int i;                                   1839         int i;
1840         unsigned long long count;                1840         unsigned long long count;
1841                                                  1841 
1842         for (i = 0; i < KWORK_TRACE_MAX; i++)    1842         for (i = 0; i < KWORK_TRACE_MAX; i++) {
1843                 count = nr_list_entry(&work->    1843                 count = nr_list_entry(&work->atom_list[i]);
1844                 kwork->nr_skipped_events[i] +    1844                 kwork->nr_skipped_events[i] += count;
1845                 kwork->nr_skipped_events[KWOR    1845                 kwork->nr_skipped_events[KWORK_TRACE_MAX] += count;
1846         }                                        1846         }
1847 }                                                1847 }
1848                                                  1848 
1849 struct kwork_work *perf_kwork_add_work(struct    1849 struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork,
1850                                        struct    1850                                        struct kwork_class *class,
1851                                        struct    1851                                        struct kwork_work *key)
1852 {                                                1852 {
1853         struct kwork_work *work = NULL;          1853         struct kwork_work *work = NULL;
1854                                                  1854 
1855         work = work_new(key);                    1855         work = work_new(key);
1856         if (work == NULL)                        1856         if (work == NULL)
1857                 return NULL;                     1857                 return NULL;
1858                                                  1858 
1859         work_insert(&class->work_root, work,     1859         work_insert(&class->work_root, work, &kwork->cmp_id);
1860         return work;                             1860         return work;
1861 }                                                1861 }
1862                                                  1862 
1863 static void sig_handler(int sig)                 1863 static void sig_handler(int sig)
1864 {                                                1864 {
1865         /*                                       1865         /*
1866          * Simply capture termination signal     1866          * Simply capture termination signal so that
1867          * the program can continue after pau    1867          * the program can continue after pause returns
1868          */                                      1868          */
1869         pr_debug("Capture signal %d\n", sig);    1869         pr_debug("Capture signal %d\n", sig);
1870 }                                                1870 }
1871                                                  1871 
1872 static int perf_kwork__report_bpf(struct perf    1872 static int perf_kwork__report_bpf(struct perf_kwork *kwork)
1873 {                                                1873 {
1874         int ret;                                 1874         int ret;
1875                                                  1875 
1876         signal(SIGINT, sig_handler);             1876         signal(SIGINT, sig_handler);
1877         signal(SIGTERM, sig_handler);            1877         signal(SIGTERM, sig_handler);
1878                                                  1878 
1879         ret = perf_kwork__trace_prepare_bpf(k    1879         ret = perf_kwork__trace_prepare_bpf(kwork);
1880         if (ret)                                 1880         if (ret)
1881                 return -1;                       1881                 return -1;
1882                                                  1882 
1883         printf("Starting trace, Hit <Ctrl+C>     1883         printf("Starting trace, Hit <Ctrl+C> to stop and report\n");
1884                                                  1884 
1885         perf_kwork__trace_start();               1885         perf_kwork__trace_start();
1886                                                  1886 
1887         /*                                       1887         /*
1888          * a simple pause, wait here for stop    1888          * a simple pause, wait here for stop signal
1889          */                                      1889          */
1890         pause();                                 1890         pause();
1891                                                  1891 
1892         perf_kwork__trace_finish();              1892         perf_kwork__trace_finish();
1893                                                  1893 
1894         perf_kwork__report_read_bpf(kwork);      1894         perf_kwork__report_read_bpf(kwork);
1895                                                  1895 
1896         perf_kwork__report_cleanup_bpf();        1896         perf_kwork__report_cleanup_bpf();
1897                                                  1897 
1898         return 0;                                1898         return 0;
1899 }                                                1899 }
1900                                                  1900 
1901 static int perf_kwork__report(struct perf_kwo    1901 static int perf_kwork__report(struct perf_kwork *kwork)
1902 {                                                1902 {
1903         int ret;                                 1903         int ret;
1904         struct rb_node *next;                    1904         struct rb_node *next;
1905         struct kwork_work *work;                 1905         struct kwork_work *work;
1906                                                  1906 
1907         if (kwork->use_bpf)                      1907         if (kwork->use_bpf)
1908                 ret = perf_kwork__report_bpf(    1908                 ret = perf_kwork__report_bpf(kwork);
1909         else                                     1909         else
1910                 ret = perf_kwork__read_events    1910                 ret = perf_kwork__read_events(kwork);
1911                                                  1911 
1912         if (ret != 0)                            1912         if (ret != 0)
1913                 return -1;                       1913                 return -1;
1914                                                  1914 
1915         perf_kwork__sort(kwork);                 1915         perf_kwork__sort(kwork);
1916                                                  1916 
1917         setup_pager();                           1917         setup_pager();
1918                                                  1918 
1919         ret = report_print_header(kwork);        1919         ret = report_print_header(kwork);
1920         next = rb_first_cached(&kwork->sorted    1920         next = rb_first_cached(&kwork->sorted_work_root);
1921         while (next) {                           1921         while (next) {
1922                 work = rb_entry(next, struct     1922                 work = rb_entry(next, struct kwork_work, node);
1923                 process_skipped_events(kwork,    1923                 process_skipped_events(kwork, work);
1924                                                  1924 
1925                 if (work->nr_atoms != 0) {       1925                 if (work->nr_atoms != 0) {
1926                         report_print_work(kwo    1926                         report_print_work(kwork, work);
1927                         if (kwork->summary) {    1927                         if (kwork->summary) {
1928                                 kwork->all_ru    1928                                 kwork->all_runtime += work->total_runtime;
1929                                 kwork->all_co    1929                                 kwork->all_count += work->nr_atoms;
1930                         }                        1930                         }
1931                 }                                1931                 }
1932                 next = rb_next(next);            1932                 next = rb_next(next);
1933         }                                        1933         }
1934         print_separator(ret);                    1934         print_separator(ret);
1935                                                  1935 
1936         if (kwork->summary) {                    1936         if (kwork->summary) {
1937                 print_summary(kwork);            1937                 print_summary(kwork);
1938                 print_separator(ret);            1938                 print_separator(ret);
1939         }                                        1939         }
1940                                                  1940 
1941         print_bad_events(kwork);                 1941         print_bad_events(kwork);
1942         print_skipped_events(kwork);             1942         print_skipped_events(kwork);
1943         printf("\n");                            1943         printf("\n");
1944                                                  1944 
1945         return 0;                                1945         return 0;
1946 }                                                1946 }
1947                                                  1947 
1948 typedef int (*tracepoint_handler)(struct perf    1948 typedef int (*tracepoint_handler)(struct perf_tool *tool,
1949                                   struct evse    1949                                   struct evsel *evsel,
1950                                   struct perf    1950                                   struct perf_sample *sample,
1951                                   struct mach    1951                                   struct machine *machine);
1952                                                  1952 
1953 static int perf_kwork__process_tracepoint_sam    1953 static int perf_kwork__process_tracepoint_sample(struct perf_tool *tool,
1954                                                  1954                                                  union perf_event *event __maybe_unused,
1955                                                  1955                                                  struct perf_sample *sample,
1956                                                  1956                                                  struct evsel *evsel,
1957                                                  1957                                                  struct machine *machine)
1958 {                                                1958 {
1959         int err = 0;                             1959         int err = 0;
1960                                                  1960 
1961         if (evsel->handler != NULL) {            1961         if (evsel->handler != NULL) {
1962                 tracepoint_handler f = evsel-    1962                 tracepoint_handler f = evsel->handler;
1963                                                  1963 
1964                 err = f(tool, evsel, sample,     1964                 err = f(tool, evsel, sample, machine);
1965         }                                        1965         }
1966                                                  1966 
1967         return err;                              1967         return err;
1968 }                                                1968 }
1969                                                  1969 
1970 static int perf_kwork__timehist(struct perf_k    1970 static int perf_kwork__timehist(struct perf_kwork *kwork)
1971 {                                                1971 {
1972         /*                                       1972         /*
1973          * event handlers for timehist option    1973          * event handlers for timehist option
1974          */                                      1974          */
1975         kwork->tool.comm         = perf_event    1975         kwork->tool.comm         = perf_event__process_comm;
1976         kwork->tool.exit         = perf_event    1976         kwork->tool.exit         = perf_event__process_exit;
1977         kwork->tool.fork         = perf_event    1977         kwork->tool.fork         = perf_event__process_fork;
1978         kwork->tool.attr         = perf_event    1978         kwork->tool.attr         = perf_event__process_attr;
1979         kwork->tool.tracing_data = perf_event    1979         kwork->tool.tracing_data = perf_event__process_tracing_data;
1980         kwork->tool.build_id     = perf_event    1980         kwork->tool.build_id     = perf_event__process_build_id;
1981         kwork->tool.ordered_events = true;       1981         kwork->tool.ordered_events = true;
1982         kwork->tool.ordering_requires_timesta    1982         kwork->tool.ordering_requires_timestamps = true;
1983         symbol_conf.use_callchain = kwork->sh    1983         symbol_conf.use_callchain = kwork->show_callchain;
1984                                                  1984 
1985         if (symbol__validate_sym_arguments())    1985         if (symbol__validate_sym_arguments()) {
1986                 pr_err("Failed to validate sy    1986                 pr_err("Failed to validate sym arguments\n");
1987                 return -1;                       1987                 return -1;
1988         }                                        1988         }
1989                                                  1989 
1990         setup_pager();                           1990         setup_pager();
1991                                                  1991 
1992         return perf_kwork__read_events(kwork)    1992         return perf_kwork__read_events(kwork);
1993 }                                                1993 }
1994                                                  1994 
1995 static void top_calc_total_runtime(struct per    1995 static void top_calc_total_runtime(struct perf_kwork *kwork)
1996 {                                                1996 {
1997         struct kwork_class *class;               1997         struct kwork_class *class;
1998         struct kwork_work *work;                 1998         struct kwork_work *work;
1999         struct rb_node *next;                    1999         struct rb_node *next;
2000         struct kwork_top_stat *stat = &kwork-    2000         struct kwork_top_stat *stat = &kwork->top_stat;
2001                                                  2001 
2002         class = get_kwork_class(kwork, KWORK_    2002         class = get_kwork_class(kwork, KWORK_CLASS_SCHED);
2003         if (!class)                              2003         if (!class)
2004                 return;                          2004                 return;
2005                                                  2005 
2006         next = rb_first_cached(&class->work_r    2006         next = rb_first_cached(&class->work_root);
2007         while (next) {                           2007         while (next) {
2008                 work = rb_entry(next, struct     2008                 work = rb_entry(next, struct kwork_work, node);
2009                 BUG_ON(work->cpu >= MAX_NR_CP    2009                 BUG_ON(work->cpu >= MAX_NR_CPUS);
2010                 stat->cpus_runtime[work->cpu]    2010                 stat->cpus_runtime[work->cpu].total += work->total_runtime;
2011                 stat->cpus_runtime[MAX_NR_CPU    2011                 stat->cpus_runtime[MAX_NR_CPUS].total += work->total_runtime;
2012                 next = rb_next(next);            2012                 next = rb_next(next);
2013         }                                        2013         }
2014 }                                                2014 }
2015                                                  2015 
2016 static void top_calc_idle_time(struct perf_kw    2016 static void top_calc_idle_time(struct perf_kwork *kwork,
2017                                 struct kwork_    2017                                 struct kwork_work *work)
2018 {                                                2018 {
2019         struct kwork_top_stat *stat = &kwork-    2019         struct kwork_top_stat *stat = &kwork->top_stat;
2020                                                  2020 
2021         if (work->id == 0) {                     2021         if (work->id == 0) {
2022                 stat->cpus_runtime[work->cpu]    2022                 stat->cpus_runtime[work->cpu].idle += work->total_runtime;
2023                 stat->cpus_runtime[MAX_NR_CPU    2023                 stat->cpus_runtime[MAX_NR_CPUS].idle += work->total_runtime;
2024         }                                        2024         }
2025 }                                                2025 }
2026                                                  2026 
2027 static void top_calc_irq_runtime(struct perf_    2027 static void top_calc_irq_runtime(struct perf_kwork *kwork,
2028                                  enum kwork_c    2028                                  enum kwork_class_type type,
2029                                  struct kwork    2029                                  struct kwork_work *work)
2030 {                                                2030 {
2031         struct kwork_top_stat *stat = &kwork-    2031         struct kwork_top_stat *stat = &kwork->top_stat;
2032                                                  2032 
2033         if (type == KWORK_CLASS_IRQ) {           2033         if (type == KWORK_CLASS_IRQ) {
2034                 stat->cpus_runtime[work->cpu]    2034                 stat->cpus_runtime[work->cpu].irq += work->total_runtime;
2035                 stat->cpus_runtime[MAX_NR_CPU    2035                 stat->cpus_runtime[MAX_NR_CPUS].irq += work->total_runtime;
2036         } else if (type == KWORK_CLASS_SOFTIR    2036         } else if (type == KWORK_CLASS_SOFTIRQ) {
2037                 stat->cpus_runtime[work->cpu]    2037                 stat->cpus_runtime[work->cpu].softirq += work->total_runtime;
2038                 stat->cpus_runtime[MAX_NR_CPU    2038                 stat->cpus_runtime[MAX_NR_CPUS].softirq += work->total_runtime;
2039         }                                        2039         }
2040 }                                                2040 }
2041                                                  2041 
2042 static void top_subtract_irq_runtime(struct p    2042 static void top_subtract_irq_runtime(struct perf_kwork *kwork,
2043                                      struct k    2043                                      struct kwork_work *work)
2044 {                                                2044 {
2045         struct kwork_class *class;               2045         struct kwork_class *class;
2046         struct kwork_work *data;                 2046         struct kwork_work *data;
2047         unsigned int i;                          2047         unsigned int i;
2048         int irq_class_list[] = {KWORK_CLASS_I    2048         int irq_class_list[] = {KWORK_CLASS_IRQ, KWORK_CLASS_SOFTIRQ};
2049                                                  2049 
2050         for (i = 0; i < ARRAY_SIZE(irq_class_    2050         for (i = 0; i < ARRAY_SIZE(irq_class_list); i++) {
2051                 class = get_kwork_class(kwork    2051                 class = get_kwork_class(kwork, irq_class_list[i]);
2052                 if (!class)                      2052                 if (!class)
2053                         continue;                2053                         continue;
2054                                                  2054 
2055                 data = find_work_by_id(&class    2055                 data = find_work_by_id(&class->work_root,
2056                                        work->    2056                                        work->id, work->cpu);
2057                 if (!data)                       2057                 if (!data)
2058                         continue;                2058                         continue;
2059                                                  2059 
2060                 if (work->total_runtime > dat    2060                 if (work->total_runtime > data->total_runtime) {
2061                         work->total_runtime -    2061                         work->total_runtime -= data->total_runtime;
2062                         top_calc_irq_runtime(    2062                         top_calc_irq_runtime(kwork, irq_class_list[i], data);
2063                 }                                2063                 }
2064         }                                        2064         }
2065 }                                                2065 }
2066                                                  2066 
2067 static void top_calc_cpu_usage(struct perf_kw    2067 static void top_calc_cpu_usage(struct perf_kwork *kwork)
2068 {                                                2068 {
2069         struct kwork_class *class;               2069         struct kwork_class *class;
2070         struct kwork_work *work;                 2070         struct kwork_work *work;
2071         struct rb_node *next;                    2071         struct rb_node *next;
2072         struct kwork_top_stat *stat = &kwork-    2072         struct kwork_top_stat *stat = &kwork->top_stat;
2073                                                  2073 
2074         class = get_kwork_class(kwork, KWORK_    2074         class = get_kwork_class(kwork, KWORK_CLASS_SCHED);
2075         if (!class)                              2075         if (!class)
2076                 return;                          2076                 return;
2077                                                  2077 
2078         next = rb_first_cached(&class->work_r    2078         next = rb_first_cached(&class->work_root);
2079         while (next) {                           2079         while (next) {
2080                 work = rb_entry(next, struct     2080                 work = rb_entry(next, struct kwork_work, node);
2081                                                  2081 
2082                 if (work->total_runtime == 0)    2082                 if (work->total_runtime == 0)
2083                         goto next;               2083                         goto next;
2084                                                  2084 
2085                 __set_bit(work->cpu, stat->al    2085                 __set_bit(work->cpu, stat->all_cpus_bitmap);
2086                                                  2086 
2087                 top_subtract_irq_runtime(kwor    2087                 top_subtract_irq_runtime(kwork, work);
2088                                                  2088 
2089                 work->cpu_usage = work->total    2089                 work->cpu_usage = work->total_runtime * 10000 /
2090                         stat->cpus_runtime[wo    2090                         stat->cpus_runtime[work->cpu].total;
2091                                                  2091 
2092                 top_calc_idle_time(kwork, wor    2092                 top_calc_idle_time(kwork, work);
2093 next:                                            2093 next:
2094                 next = rb_next(next);            2094                 next = rb_next(next);
2095         }                                        2095         }
2096 }                                                2096 }
2097                                                  2097 
2098 static void top_calc_load_runtime(struct perf    2098 static void top_calc_load_runtime(struct perf_kwork *kwork,
2099                                   struct kwor    2099                                   struct kwork_work *work)
2100 {                                                2100 {
2101         struct kwork_top_stat *stat = &kwork-    2101         struct kwork_top_stat *stat = &kwork->top_stat;
2102                                                  2102 
2103         if (work->id != 0) {                     2103         if (work->id != 0) {
2104                 stat->cpus_runtime[work->cpu]    2104                 stat->cpus_runtime[work->cpu].load += work->total_runtime;
2105                 stat->cpus_runtime[MAX_NR_CPU    2105                 stat->cpus_runtime[MAX_NR_CPUS].load += work->total_runtime;
2106         }                                        2106         }
2107 }                                                2107 }
2108                                                  2108 
2109 static void top_merge_tasks(struct perf_kwork    2109 static void top_merge_tasks(struct perf_kwork *kwork)
2110 {                                                2110 {
2111         struct kwork_work *merged_work, *data    2111         struct kwork_work *merged_work, *data;
2112         struct kwork_class *class;               2112         struct kwork_class *class;
2113         struct rb_node *node;                    2113         struct rb_node *node;
2114         int cpu;                                 2114         int cpu;
2115         struct rb_root_cached merged_root = R    2115         struct rb_root_cached merged_root = RB_ROOT_CACHED;
2116                                                  2116 
2117         class = get_kwork_class(kwork, KWORK_    2117         class = get_kwork_class(kwork, KWORK_CLASS_SCHED);
2118         if (!class)                              2118         if (!class)
2119                 return;                          2119                 return;
2120                                                  2120 
2121         for (;;) {                               2121         for (;;) {
2122                 node = rb_first_cached(&class    2122                 node = rb_first_cached(&class->work_root);
2123                 if (!node)                       2123                 if (!node)
2124                         break;                   2124                         break;
2125                                                  2125 
2126                 rb_erase_cached(node, &class-    2126                 rb_erase_cached(node, &class->work_root);
2127                 data = rb_entry(node, struct     2127                 data = rb_entry(node, struct kwork_work, node);
2128                                                  2128 
2129                 if (!profile_name_match(kwork    2129                 if (!profile_name_match(kwork, data))
2130                         continue;                2130                         continue;
2131                                                  2131 
2132                 cpu = data->cpu;                 2132                 cpu = data->cpu;
2133                 merged_work = find_work_by_id    2133                 merged_work = find_work_by_id(&merged_root, data->id,
2134                                                  2134                                               data->id == 0 ? cpu : -1);
2135                 if (!merged_work) {              2135                 if (!merged_work) {
2136                         work_insert(&merged_r    2136                         work_insert(&merged_root, data, &kwork->cmp_id);
2137                 } else {                         2137                 } else {
2138                         merged_work->total_ru    2138                         merged_work->total_runtime += data->total_runtime;
2139                         merged_work->cpu_usag    2139                         merged_work->cpu_usage += data->cpu_usage;
2140                 }                                2140                 }
2141                                                  2141 
2142                 top_calc_load_runtime(kwork,     2142                 top_calc_load_runtime(kwork, data);
2143         }                                        2143         }
2144                                                  2144 
2145         work_sort(kwork, class, &merged_root)    2145         work_sort(kwork, class, &merged_root);
2146 }                                                2146 }
2147                                                  2147 
2148 static void perf_kwork__top_report(struct per    2148 static void perf_kwork__top_report(struct perf_kwork *kwork)
2149 {                                                2149 {
2150         struct kwork_work *work;                 2150         struct kwork_work *work;
2151         struct rb_node *next;                    2151         struct rb_node *next;
2152                                                  2152 
2153         printf("\n");                            2153         printf("\n");
2154                                                  2154 
2155         top_print_cpu_usage(kwork);              2155         top_print_cpu_usage(kwork);
2156         top_print_header(kwork);                 2156         top_print_header(kwork);
2157         next = rb_first_cached(&kwork->sorted    2157         next = rb_first_cached(&kwork->sorted_work_root);
2158         while (next) {                           2158         while (next) {
2159                 work = rb_entry(next, struct     2159                 work = rb_entry(next, struct kwork_work, node);
2160                 process_skipped_events(kwork,    2160                 process_skipped_events(kwork, work);
2161                                                  2161 
2162                 if (work->total_runtime == 0)    2162                 if (work->total_runtime == 0)
2163                         goto next;               2163                         goto next;
2164                                                  2164 
2165                 top_print_work(kwork, work);     2165                 top_print_work(kwork, work);
2166                                                  2166 
2167 next:                                            2167 next:
2168                 next = rb_next(next);            2168                 next = rb_next(next);
2169         }                                        2169         }
2170                                                  2170 
2171         printf("\n");                            2171         printf("\n");
2172 }                                                2172 }
2173                                                  2173 
2174 static int perf_kwork__top_bpf(struct perf_kw    2174 static int perf_kwork__top_bpf(struct perf_kwork *kwork)
2175 {                                                2175 {
2176         int ret;                                 2176         int ret;
2177                                                  2177 
2178         signal(SIGINT, sig_handler);             2178         signal(SIGINT, sig_handler);
2179         signal(SIGTERM, sig_handler);            2179         signal(SIGTERM, sig_handler);
2180                                                  2180 
2181         ret = perf_kwork__top_prepare_bpf(kwo    2181         ret = perf_kwork__top_prepare_bpf(kwork);
2182         if (ret)                                 2182         if (ret)
2183                 return -1;                       2183                 return -1;
2184                                                  2184 
2185         printf("Starting trace, Hit <Ctrl+C>     2185         printf("Starting trace, Hit <Ctrl+C> to stop and report\n");
2186                                                  2186 
2187         perf_kwork__top_start();                 2187         perf_kwork__top_start();
2188                                                  2188 
2189         /*                                       2189         /*
2190          * a simple pause, wait here for stop    2190          * a simple pause, wait here for stop signal
2191          */                                      2191          */
2192         pause();                                 2192         pause();
2193                                                  2193 
2194         perf_kwork__top_finish();                2194         perf_kwork__top_finish();
2195                                                  2195 
2196         perf_kwork__top_read_bpf(kwork);         2196         perf_kwork__top_read_bpf(kwork);
2197                                                  2197 
2198         perf_kwork__top_cleanup_bpf();           2198         perf_kwork__top_cleanup_bpf();
2199                                                  2199 
2200         return 0;                                2200         return 0;
2201                                                  2201 
2202 }                                                2202 }
2203                                                  2203 
2204 static int perf_kwork__top(struct perf_kwork     2204 static int perf_kwork__top(struct perf_kwork *kwork)
2205 {                                                2205 {
2206         struct __top_cpus_runtime *cpus_runti    2206         struct __top_cpus_runtime *cpus_runtime;
2207         int ret = 0;                             2207         int ret = 0;
2208                                                  2208 
2209         cpus_runtime = zalloc(sizeof(struct _    2209         cpus_runtime = zalloc(sizeof(struct __top_cpus_runtime) * (MAX_NR_CPUS + 1));
2210         if (!cpus_runtime)                       2210         if (!cpus_runtime)
2211                 return -1;                       2211                 return -1;
2212                                                  2212 
2213         kwork->top_stat.cpus_runtime = cpus_r    2213         kwork->top_stat.cpus_runtime = cpus_runtime;
2214         bitmap_zero(kwork->top_stat.all_cpus_    2214         bitmap_zero(kwork->top_stat.all_cpus_bitmap, MAX_NR_CPUS);
2215                                                  2215 
2216         if (kwork->use_bpf)                      2216         if (kwork->use_bpf)
2217                 ret = perf_kwork__top_bpf(kwo    2217                 ret = perf_kwork__top_bpf(kwork);
2218         else                                     2218         else
2219                 ret = perf_kwork__read_events    2219                 ret = perf_kwork__read_events(kwork);
2220                                                  2220 
2221         if (ret)                                 2221         if (ret)
2222                 goto out;                        2222                 goto out;
2223                                                  2223 
2224         top_calc_total_runtime(kwork);           2224         top_calc_total_runtime(kwork);
2225         top_calc_cpu_usage(kwork);               2225         top_calc_cpu_usage(kwork);
2226         top_merge_tasks(kwork);                  2226         top_merge_tasks(kwork);
2227                                                  2227 
2228         setup_pager();                           2228         setup_pager();
2229                                                  2229 
2230         perf_kwork__top_report(kwork);           2230         perf_kwork__top_report(kwork);
2231                                                  2231 
2232 out:                                             2232 out:
2233         zfree(&kwork->top_stat.cpus_runtime);    2233         zfree(&kwork->top_stat.cpus_runtime);
2234         return ret;                              2234         return ret;
2235 }                                                2235 }
2236                                                  2236 
2237 static void setup_event_list(struct perf_kwor    2237 static void setup_event_list(struct perf_kwork *kwork,
2238                              const struct opt    2238                              const struct option *options,
2239                              const char * con    2239                              const char * const usage_msg[])
2240 {                                                2240 {
2241         int i;                                   2241         int i;
2242         struct kwork_class *class;               2242         struct kwork_class *class;
2243         char *tmp, *tok, *str;                   2243         char *tmp, *tok, *str;
2244                                                  2244 
2245         /*                                       2245         /*
2246          * set default events list if not spe    2246          * set default events list if not specified
2247          */                                      2247          */
2248         if (kwork->event_list_str == NULL)       2248         if (kwork->event_list_str == NULL)
2249                 kwork->event_list_str = "irq,    2249                 kwork->event_list_str = "irq, softirq, workqueue";
2250                                                  2250 
2251         str = strdup(kwork->event_list_str);     2251         str = strdup(kwork->event_list_str);
2252         for (tok = strtok_r(str, ", ", &tmp);    2252         for (tok = strtok_r(str, ", ", &tmp);
2253              tok; tok = strtok_r(NULL, ", ",     2253              tok; tok = strtok_r(NULL, ", ", &tmp)) {
2254                 for (i = 0; i < KWORK_CLASS_M    2254                 for (i = 0; i < KWORK_CLASS_MAX; i++) {
2255                         class = kwork_class_s    2255                         class = kwork_class_supported_list[i];
2256                         if (strcmp(tok, class    2256                         if (strcmp(tok, class->name) == 0) {
2257                                 list_add_tail    2257                                 list_add_tail(&class->list, &kwork->class_list);
2258                                 break;           2258                                 break;
2259                         }                        2259                         }
2260                 }                                2260                 }
2261                 if (i == KWORK_CLASS_MAX) {      2261                 if (i == KWORK_CLASS_MAX) {
2262                         usage_with_options_ms    2262                         usage_with_options_msg(usage_msg, options,
2263                                                  2263                                                "Unknown --event key: `%s'", tok);
2264                 }                                2264                 }
2265         }                                        2265         }
2266         free(str);                               2266         free(str);
2267                                                  2267 
2268         pr_debug("Config event list:");          2268         pr_debug("Config event list:");
2269         list_for_each_entry(class, &kwork->cl    2269         list_for_each_entry(class, &kwork->class_list, list)
2270                 pr_debug(" %s", class->name);    2270                 pr_debug(" %s", class->name);
2271         pr_debug("\n");                          2271         pr_debug("\n");
2272 }                                                2272 }
2273                                                  2273 
2274 static int perf_kwork__record(struct perf_kwo    2274 static int perf_kwork__record(struct perf_kwork *kwork,
2275                               int argc, const    2275                               int argc, const char **argv)
2276 {                                                2276 {
2277         const char **rec_argv;                   2277         const char **rec_argv;
2278         unsigned int rec_argc, i, j;             2278         unsigned int rec_argc, i, j;
2279         struct kwork_class *class;               2279         struct kwork_class *class;
2280                                                  2280 
2281         const char *const record_args[] = {      2281         const char *const record_args[] = {
2282                 "record",                        2282                 "record",
2283                 "-a",                            2283                 "-a",
2284                 "-R",                            2284                 "-R",
2285                 "-m", "1024",                    2285                 "-m", "1024",
2286                 "-c", "1",                       2286                 "-c", "1",
2287         };                                       2287         };
2288                                                  2288 
2289         rec_argc = ARRAY_SIZE(record_args) +     2289         rec_argc = ARRAY_SIZE(record_args) + argc - 1;
2290                                                  2290 
2291         list_for_each_entry(class, &kwork->cl    2291         list_for_each_entry(class, &kwork->class_list, list)
2292                 rec_argc += 2 * class->nr_tra    2292                 rec_argc += 2 * class->nr_tracepoints;
2293                                                  2293 
2294         rec_argv = calloc(rec_argc + 1, sizeo    2294         rec_argv = calloc(rec_argc + 1, sizeof(char *));
2295         if (rec_argv == NULL)                    2295         if (rec_argv == NULL)
2296                 return -ENOMEM;                  2296                 return -ENOMEM;
2297                                                  2297 
2298         for (i = 0; i < ARRAY_SIZE(record_arg    2298         for (i = 0; i < ARRAY_SIZE(record_args); i++)
2299                 rec_argv[i] = strdup(record_a    2299                 rec_argv[i] = strdup(record_args[i]);
2300                                                  2300 
2301         list_for_each_entry(class, &kwork->cl    2301         list_for_each_entry(class, &kwork->class_list, list) {
2302                 for (j = 0; j < class->nr_tra    2302                 for (j = 0; j < class->nr_tracepoints; j++) {
2303                         rec_argv[i++] = strdu    2303                         rec_argv[i++] = strdup("-e");
2304                         rec_argv[i++] = strdu    2304                         rec_argv[i++] = strdup(class->tp_handlers[j].name);
2305                 }                                2305                 }
2306         }                                        2306         }
2307                                                  2307 
2308         for (j = 1; j < (unsigned int)argc; j    2308         for (j = 1; j < (unsigned int)argc; j++, i++)
2309                 rec_argv[i] = argv[j];           2309                 rec_argv[i] = argv[j];
2310                                                  2310 
2311         BUG_ON(i != rec_argc);                   2311         BUG_ON(i != rec_argc);
2312                                                  2312 
2313         pr_debug("record comm: ");               2313         pr_debug("record comm: ");
2314         for (j = 0; j < rec_argc; j++)           2314         for (j = 0; j < rec_argc; j++)
2315                 pr_debug("%s ", rec_argv[j]);    2315                 pr_debug("%s ", rec_argv[j]);
2316         pr_debug("\n");                          2316         pr_debug("\n");
2317                                                  2317 
2318         return cmd_record(i, rec_argv);          2318         return cmd_record(i, rec_argv);
2319 }                                                2319 }
2320                                                  2320 
2321 int cmd_kwork(int argc, const char **argv)       2321 int cmd_kwork(int argc, const char **argv)
2322 {                                                2322 {
2323         static struct perf_kwork kwork = {       2323         static struct perf_kwork kwork = {
2324                 .class_list          = LIST_H    2324                 .class_list          = LIST_HEAD_INIT(kwork.class_list),
2325                 .tool = {                        2325                 .tool = {
2326                         .mmap           = per    2326                         .mmap           = perf_event__process_mmap,
2327                         .mmap2          = per    2327                         .mmap2          = perf_event__process_mmap2,
2328                         .sample         = per    2328                         .sample         = perf_kwork__process_tracepoint_sample,
2329                         .ordered_events = tru    2329                         .ordered_events = true,
2330                 },                               2330                 },
2331                 .atom_page_list      = LIST_H    2331                 .atom_page_list      = LIST_HEAD_INIT(kwork.atom_page_list),
2332                 .sort_list           = LIST_H    2332                 .sort_list           = LIST_HEAD_INIT(kwork.sort_list),
2333                 .cmp_id              = LIST_H    2333                 .cmp_id              = LIST_HEAD_INIT(kwork.cmp_id),
2334                 .sorted_work_root    = RB_ROO    2334                 .sorted_work_root    = RB_ROOT_CACHED,
2335                 .tp_handler          = NULL,     2335                 .tp_handler          = NULL,
2336                 .profile_name        = NULL,     2336                 .profile_name        = NULL,
2337                 .cpu_list            = NULL,     2337                 .cpu_list            = NULL,
2338                 .time_str            = NULL,     2338                 .time_str            = NULL,
2339                 .force               = false,    2339                 .force               = false,
2340                 .event_list_str      = NULL,     2340                 .event_list_str      = NULL,
2341                 .summary             = false,    2341                 .summary             = false,
2342                 .sort_order          = NULL,     2342                 .sort_order          = NULL,
2343                 .show_callchain      = false,    2343                 .show_callchain      = false,
2344                 .max_stack           = 5,        2344                 .max_stack           = 5,
2345                 .timestart           = 0,        2345                 .timestart           = 0,
2346                 .timeend             = 0,        2346                 .timeend             = 0,
2347                 .nr_events           = 0,        2347                 .nr_events           = 0,
2348                 .nr_lost_chunks      = 0,        2348                 .nr_lost_chunks      = 0,
2349                 .nr_lost_events      = 0,        2349                 .nr_lost_events      = 0,
2350                 .all_runtime         = 0,        2350                 .all_runtime         = 0,
2351                 .all_count           = 0,        2351                 .all_count           = 0,
2352                 .nr_skipped_events   = { 0 },    2352                 .nr_skipped_events   = { 0 },
2353         };                                       2353         };
2354         static const char default_report_sort    2354         static const char default_report_sort_order[] = "runtime, max, count";
2355         static const char default_latency_sor    2355         static const char default_latency_sort_order[] = "avg, max, count";
2356         static const char default_top_sort_or    2356         static const char default_top_sort_order[] = "rate, runtime";
2357         const struct option kwork_options[] =    2357         const struct option kwork_options[] = {
2358         OPT_INCR('v', "verbose", &verbose,       2358         OPT_INCR('v', "verbose", &verbose,
2359                  "be more verbose (show symbo    2359                  "be more verbose (show symbol address, etc)"),
2360         OPT_BOOLEAN('D', "dump-raw-trace", &d    2360         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
2361                     "dump raw trace in ASCII"    2361                     "dump raw trace in ASCII"),
2362         OPT_STRING('k', "kwork", &kwork.event    2362         OPT_STRING('k', "kwork", &kwork.event_list_str, "kwork",
2363                    "list of kwork to profile     2363                    "list of kwork to profile (irq, softirq, workqueue, sched, etc)"),
2364         OPT_BOOLEAN('f', "force", &kwork.forc    2364         OPT_BOOLEAN('f', "force", &kwork.force, "don't complain, do it"),
2365         OPT_END()                                2365         OPT_END()
2366         };                                       2366         };
2367         const struct option report_options[]     2367         const struct option report_options[] = {
2368         OPT_STRING('s', "sort", &kwork.sort_o    2368         OPT_STRING('s', "sort", &kwork.sort_order, "key[,key2...]",
2369                    "sort by key(s): runtime,     2369                    "sort by key(s): runtime, max, count"),
2370         OPT_STRING('C', "cpu", &kwork.cpu_lis    2370         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
2371                    "list of cpus to profile")    2371                    "list of cpus to profile"),
2372         OPT_STRING('n', "name", &kwork.profil    2372         OPT_STRING('n', "name", &kwork.profile_name, "name",
2373                    "event name to profile"),     2373                    "event name to profile"),
2374         OPT_STRING(0, "time", &kwork.time_str    2374         OPT_STRING(0, "time", &kwork.time_str, "str",
2375                    "Time span for analysis (s    2375                    "Time span for analysis (start,stop)"),
2376         OPT_STRING('i', "input", &input_name,    2376         OPT_STRING('i', "input", &input_name, "file",
2377                    "input file name"),           2377                    "input file name"),
2378         OPT_BOOLEAN('S', "with-summary", &kwo    2378         OPT_BOOLEAN('S', "with-summary", &kwork.summary,
2379                     "Show summary with statis    2379                     "Show summary with statistics"),
2380 #ifdef HAVE_BPF_SKEL                             2380 #ifdef HAVE_BPF_SKEL
2381         OPT_BOOLEAN('b', "use-bpf", &kwork.us    2381         OPT_BOOLEAN('b', "use-bpf", &kwork.use_bpf,
2382                     "Use BPF to measure kwork    2382                     "Use BPF to measure kwork runtime"),
2383 #endif                                           2383 #endif
2384         OPT_PARENT(kwork_options)                2384         OPT_PARENT(kwork_options)
2385         };                                       2385         };
2386         const struct option latency_options[]    2386         const struct option latency_options[] = {
2387         OPT_STRING('s', "sort", &kwork.sort_o    2387         OPT_STRING('s', "sort", &kwork.sort_order, "key[,key2...]",
2388                    "sort by key(s): avg, max,    2388                    "sort by key(s): avg, max, count"),
2389         OPT_STRING('C', "cpu", &kwork.cpu_lis    2389         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
2390                    "list of cpus to profile")    2390                    "list of cpus to profile"),
2391         OPT_STRING('n', "name", &kwork.profil    2391         OPT_STRING('n', "name", &kwork.profile_name, "name",
2392                    "event name to profile"),     2392                    "event name to profile"),
2393         OPT_STRING(0, "time", &kwork.time_str    2393         OPT_STRING(0, "time", &kwork.time_str, "str",
2394                    "Time span for analysis (s    2394                    "Time span for analysis (start,stop)"),
2395         OPT_STRING('i', "input", &input_name,    2395         OPT_STRING('i', "input", &input_name, "file",
2396                    "input file name"),           2396                    "input file name"),
2397 #ifdef HAVE_BPF_SKEL                             2397 #ifdef HAVE_BPF_SKEL
2398         OPT_BOOLEAN('b', "use-bpf", &kwork.us    2398         OPT_BOOLEAN('b', "use-bpf", &kwork.use_bpf,
2399                     "Use BPF to measure kwork    2399                     "Use BPF to measure kwork latency"),
2400 #endif                                           2400 #endif
2401         OPT_PARENT(kwork_options)                2401         OPT_PARENT(kwork_options)
2402         };                                       2402         };
2403         const struct option timehist_options[    2403         const struct option timehist_options[] = {
2404         OPT_STRING('k', "vmlinux", &symbol_co    2404         OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
2405                    "file", "vmlinux pathname"    2405                    "file", "vmlinux pathname"),
2406         OPT_STRING(0, "kallsyms", &symbol_con    2406         OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
2407                    "file", "kallsyms pathname    2407                    "file", "kallsyms pathname"),
2408         OPT_BOOLEAN('g', "call-graph", &kwork    2408         OPT_BOOLEAN('g', "call-graph", &kwork.show_callchain,
2409                     "Display call chains if p    2409                     "Display call chains if present"),
2410         OPT_UINTEGER(0, "max-stack", &kwork.m    2410         OPT_UINTEGER(0, "max-stack", &kwork.max_stack,
2411                    "Maximum number of functio    2411                    "Maximum number of functions to display backtrace."),
2412         OPT_STRING(0, "symfs", &symbol_conf.s    2412         OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
2413                     "Look for files with symb    2413                     "Look for files with symbols relative to this directory"),
2414         OPT_STRING(0, "time", &kwork.time_str    2414         OPT_STRING(0, "time", &kwork.time_str, "str",
2415                    "Time span for analysis (s    2415                    "Time span for analysis (start,stop)"),
2416         OPT_STRING('C', "cpu", &kwork.cpu_lis    2416         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
2417                    "list of cpus to profile")    2417                    "list of cpus to profile"),
2418         OPT_STRING('n', "name", &kwork.profil    2418         OPT_STRING('n', "name", &kwork.profile_name, "name",
2419                    "event name to profile"),     2419                    "event name to profile"),
2420         OPT_STRING('i', "input", &input_name,    2420         OPT_STRING('i', "input", &input_name, "file",
2421                    "input file name"),           2421                    "input file name"),
2422         OPT_PARENT(kwork_options)                2422         OPT_PARENT(kwork_options)
2423         };                                       2423         };
2424         const struct option top_options[] = {    2424         const struct option top_options[] = {
2425         OPT_STRING('s', "sort", &kwork.sort_o    2425         OPT_STRING('s', "sort", &kwork.sort_order, "key[,key2...]",
2426                    "sort by key(s): rate, run    2426                    "sort by key(s): rate, runtime, tid"),
2427         OPT_STRING('C', "cpu", &kwork.cpu_lis    2427         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
2428                    "list of cpus to profile")    2428                    "list of cpus to profile"),
2429         OPT_STRING('n', "name", &kwork.profil    2429         OPT_STRING('n', "name", &kwork.profile_name, "name",
2430                    "event name to profile"),     2430                    "event name to profile"),
2431         OPT_STRING(0, "time", &kwork.time_str    2431         OPT_STRING(0, "time", &kwork.time_str, "str",
2432                    "Time span for analysis (s    2432                    "Time span for analysis (start,stop)"),
2433         OPT_STRING('i', "input", &input_name,    2433         OPT_STRING('i', "input", &input_name, "file",
2434                    "input file name"),           2434                    "input file name"),
2435 #ifdef HAVE_BPF_SKEL                             2435 #ifdef HAVE_BPF_SKEL
2436         OPT_BOOLEAN('b', "use-bpf", &kwork.us    2436         OPT_BOOLEAN('b', "use-bpf", &kwork.use_bpf,
2437                     "Use BPF to measure task     2437                     "Use BPF to measure task cpu usage"),
2438 #endif                                           2438 #endif
2439         OPT_PARENT(kwork_options)                2439         OPT_PARENT(kwork_options)
2440         };                                       2440         };
2441         const char *kwork_usage[] = {            2441         const char *kwork_usage[] = {
2442                 NULL,                            2442                 NULL,
2443                 NULL                             2443                 NULL
2444         };                                       2444         };
2445         const char * const report_usage[] = {    2445         const char * const report_usage[] = {
2446                 "perf kwork report [<options>    2446                 "perf kwork report [<options>]",
2447                 NULL                             2447                 NULL
2448         };                                       2448         };
2449         const char * const latency_usage[] =     2449         const char * const latency_usage[] = {
2450                 "perf kwork latency [<options    2450                 "perf kwork latency [<options>]",
2451                 NULL                             2451                 NULL
2452         };                                       2452         };
2453         const char * const timehist_usage[] =    2453         const char * const timehist_usage[] = {
2454                 "perf kwork timehist [<option    2454                 "perf kwork timehist [<options>]",
2455                 NULL                             2455                 NULL
2456         };                                       2456         };
2457         const char * const top_usage[] = {       2457         const char * const top_usage[] = {
2458                 "perf kwork top [<options>]",    2458                 "perf kwork top [<options>]",
2459                 NULL                             2459                 NULL
2460         };                                       2460         };
2461         const char *const kwork_subcommands[]    2461         const char *const kwork_subcommands[] = {
2462                 "record", "report", "latency"    2462                 "record", "report", "latency", "timehist", "top", NULL
2463         };                                       2463         };
2464                                                  2464 
2465         argc = parse_options_subcommand(argc,    2465         argc = parse_options_subcommand(argc, argv, kwork_options,
2466                                         kwork    2466                                         kwork_subcommands, kwork_usage,
2467                                         PARSE    2467                                         PARSE_OPT_STOP_AT_NON_OPTION);
2468         if (!argc)                               2468         if (!argc)
2469                 usage_with_options(kwork_usag    2469                 usage_with_options(kwork_usage, kwork_options);
2470                                                  2470 
2471         sort_dimension__add(&kwork, "id", &kw    2471         sort_dimension__add(&kwork, "id", &kwork.cmp_id);
2472                                                  2472 
2473         if (strlen(argv[0]) > 2 && strstarts(    2473         if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
2474                 setup_event_list(&kwork, kwor    2474                 setup_event_list(&kwork, kwork_options, kwork_usage);
2475                 return perf_kwork__record(&kw    2475                 return perf_kwork__record(&kwork, argc, argv);
2476         } else if (strlen(argv[0]) > 2 && str    2476         } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
2477                 kwork.sort_order = default_re    2477                 kwork.sort_order = default_report_sort_order;
2478                 if (argc > 1) {                  2478                 if (argc > 1) {
2479                         argc = parse_options(    2479                         argc = parse_options(argc, argv, report_options, report_usage, 0);
2480                         if (argc)                2480                         if (argc)
2481                                 usage_with_op    2481                                 usage_with_options(report_usage, report_options);
2482                 }                                2482                 }
2483                 kwork.report = KWORK_REPORT_R    2483                 kwork.report = KWORK_REPORT_RUNTIME;
2484                 setup_sorting(&kwork, report_    2484                 setup_sorting(&kwork, report_options, report_usage);
2485                 setup_event_list(&kwork, kwor    2485                 setup_event_list(&kwork, kwork_options, kwork_usage);
2486                 return perf_kwork__report(&kw    2486                 return perf_kwork__report(&kwork);
2487         } else if (strlen(argv[0]) > 2 && str    2487         } else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) {
2488                 kwork.sort_order = default_la    2488                 kwork.sort_order = default_latency_sort_order;
2489                 if (argc > 1) {                  2489                 if (argc > 1) {
2490                         argc = parse_options(    2490                         argc = parse_options(argc, argv, latency_options, latency_usage, 0);
2491                         if (argc)                2491                         if (argc)
2492                                 usage_with_op    2492                                 usage_with_options(latency_usage, latency_options);
2493                 }                                2493                 }
2494                 kwork.report = KWORK_REPORT_L    2494                 kwork.report = KWORK_REPORT_LATENCY;
2495                 setup_sorting(&kwork, latency    2495                 setup_sorting(&kwork, latency_options, latency_usage);
2496                 setup_event_list(&kwork, kwor    2496                 setup_event_list(&kwork, kwork_options, kwork_usage);
2497                 return perf_kwork__report(&kw    2497                 return perf_kwork__report(&kwork);
2498         } else if (strlen(argv[0]) > 2 && str    2498         } else if (strlen(argv[0]) > 2 && strstarts("timehist", argv[0])) {
2499                 if (argc > 1) {                  2499                 if (argc > 1) {
2500                         argc = parse_options(    2500                         argc = parse_options(argc, argv, timehist_options, timehist_usage, 0);
2501                         if (argc)                2501                         if (argc)
2502                                 usage_with_op    2502                                 usage_with_options(timehist_usage, timehist_options);
2503                 }                                2503                 }
2504                 kwork.report = KWORK_REPORT_T    2504                 kwork.report = KWORK_REPORT_TIMEHIST;
2505                 setup_event_list(&kwork, kwor    2505                 setup_event_list(&kwork, kwork_options, kwork_usage);
2506                 return perf_kwork__timehist(&    2506                 return perf_kwork__timehist(&kwork);
2507         } else if (strlen(argv[0]) > 2 && str    2507         } else if (strlen(argv[0]) > 2 && strstarts("top", argv[0])) {
2508                 kwork.sort_order = default_to    2508                 kwork.sort_order = default_top_sort_order;
2509                 if (argc > 1) {                  2509                 if (argc > 1) {
2510                         argc = parse_options(    2510                         argc = parse_options(argc, argv, top_options, top_usage, 0);
2511                         if (argc)                2511                         if (argc)
2512                                 usage_with_op    2512                                 usage_with_options(top_usage, top_options);
2513                 }                                2513                 }
2514                 kwork.report = KWORK_REPORT_T    2514                 kwork.report = KWORK_REPORT_TOP;
2515                 if (!kwork.event_list_str)       2515                 if (!kwork.event_list_str)
2516                         kwork.event_list_str     2516                         kwork.event_list_str = "sched, irq, softirq";
2517                 setup_event_list(&kwork, kwor    2517                 setup_event_list(&kwork, kwork_options, kwork_usage);
2518                 setup_sorting(&kwork, top_opt    2518                 setup_sorting(&kwork, top_options, top_usage);
2519                 return perf_kwork__top(&kwork    2519                 return perf_kwork__top(&kwork);
2520         } else                                   2520         } else
2521                 usage_with_options(kwork_usag    2521                 usage_with_options(kwork_usage, kwork_options);
2522                                                  2522 
2523         return 0;                                2523         return 0;
2524 }                                                2524 }
2525                                                  2525 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php