perf stat: Fix handling of --for-each-cgroup with --bpf-counters to match non BPF...
[platform/kernel/linux-starfive.git] / tools / perf / builtin-kwork.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * builtin-kwork.c
4  *
5  * Copyright (c) 2022  Huawei Inc,  Yang Jihong <yangjihong1@huawei.com>
6  */
7
8 #include "builtin.h"
9
10 #include "util/data.h"
11 #include "util/kwork.h"
12 #include "util/debug.h"
13 #include "util/symbol.h"
14 #include "util/thread.h"
15 #include "util/string2.h"
16 #include "util/callchain.h"
17 #include "util/evsel_fprintf.h"
18
19 #include <subcmd/pager.h>
20 #include <subcmd/parse-options.h>
21
22 #include <errno.h>
23 #include <inttypes.h>
24 #include <linux/err.h>
25 #include <linux/time64.h>
26 #include <linux/zalloc.h>
27
28 /*
29  * report header elements width
30  */
31 #define PRINT_CPU_WIDTH 4
32 #define PRINT_COUNT_WIDTH 9
33 #define PRINT_RUNTIME_WIDTH 10
34 #define PRINT_LATENCY_WIDTH 10
35 #define PRINT_TIMESTAMP_WIDTH 17
36 #define PRINT_KWORK_NAME_WIDTH 30
37 #define RPINT_DECIMAL_WIDTH 3
38 #define PRINT_BRACKETPAIR_WIDTH 2
39 #define PRINT_TIME_UNIT_SEC_WIDTH 2
40 #define PRINT_TIME_UNIT_MESC_WIDTH 3
41 #define PRINT_RUNTIME_HEADER_WIDTH (PRINT_RUNTIME_WIDTH + PRINT_TIME_UNIT_MESC_WIDTH)
42 #define PRINT_LATENCY_HEADER_WIDTH (PRINT_LATENCY_WIDTH + PRINT_TIME_UNIT_MESC_WIDTH)
43 #define PRINT_TIMEHIST_CPU_WIDTH (PRINT_CPU_WIDTH + PRINT_BRACKETPAIR_WIDTH)
44 #define PRINT_TIMESTAMP_HEADER_WIDTH (PRINT_TIMESTAMP_WIDTH + PRINT_TIME_UNIT_SEC_WIDTH)
45
46 struct sort_dimension {
47         const char      *name;
48         int             (*cmp)(struct kwork_work *l, struct kwork_work *r);
49         struct          list_head list;
50 };
51
52 static int id_cmp(struct kwork_work *l, struct kwork_work *r)
53 {
54         if (l->cpu > r->cpu)
55                 return 1;
56         if (l->cpu < r->cpu)
57                 return -1;
58
59         if (l->id > r->id)
60                 return 1;
61         if (l->id < r->id)
62                 return -1;
63
64         return 0;
65 }
66
67 static int count_cmp(struct kwork_work *l, struct kwork_work *r)
68 {
69         if (l->nr_atoms > r->nr_atoms)
70                 return 1;
71         if (l->nr_atoms < r->nr_atoms)
72                 return -1;
73
74         return 0;
75 }
76
77 static int runtime_cmp(struct kwork_work *l, struct kwork_work *r)
78 {
79         if (l->total_runtime > r->total_runtime)
80                 return 1;
81         if (l->total_runtime < r->total_runtime)
82                 return -1;
83
84         return 0;
85 }
86
87 static int max_runtime_cmp(struct kwork_work *l, struct kwork_work *r)
88 {
89         if (l->max_runtime > r->max_runtime)
90                 return 1;
91         if (l->max_runtime < r->max_runtime)
92                 return -1;
93
94         return 0;
95 }
96
97 static int avg_latency_cmp(struct kwork_work *l, struct kwork_work *r)
98 {
99         u64 avgl, avgr;
100
101         if (!r->nr_atoms)
102                 return 1;
103         if (!l->nr_atoms)
104                 return -1;
105
106         avgl = l->total_latency / l->nr_atoms;
107         avgr = r->total_latency / r->nr_atoms;
108
109         if (avgl > avgr)
110                 return 1;
111         if (avgl < avgr)
112                 return -1;
113
114         return 0;
115 }
116
117 static int max_latency_cmp(struct kwork_work *l, struct kwork_work *r)
118 {
119         if (l->max_latency > r->max_latency)
120                 return 1;
121         if (l->max_latency < r->max_latency)
122                 return -1;
123
124         return 0;
125 }
126
127 static int sort_dimension__add(struct perf_kwork *kwork __maybe_unused,
128                                const char *tok, struct list_head *list)
129 {
130         size_t i;
131         static struct sort_dimension max_sort_dimension = {
132                 .name = "max",
133                 .cmp  = max_runtime_cmp,
134         };
135         static struct sort_dimension id_sort_dimension = {
136                 .name = "id",
137                 .cmp  = id_cmp,
138         };
139         static struct sort_dimension runtime_sort_dimension = {
140                 .name = "runtime",
141                 .cmp  = runtime_cmp,
142         };
143         static struct sort_dimension count_sort_dimension = {
144                 .name = "count",
145                 .cmp  = count_cmp,
146         };
147         static struct sort_dimension avg_sort_dimension = {
148                 .name = "avg",
149                 .cmp  = avg_latency_cmp,
150         };
151         struct sort_dimension *available_sorts[] = {
152                 &id_sort_dimension,
153                 &max_sort_dimension,
154                 &count_sort_dimension,
155                 &runtime_sort_dimension,
156                 &avg_sort_dimension,
157         };
158
159         if (kwork->report == KWORK_REPORT_LATENCY)
160                 max_sort_dimension.cmp = max_latency_cmp;
161
162         for (i = 0; i < ARRAY_SIZE(available_sorts); i++) {
163                 if (!strcmp(available_sorts[i]->name, tok)) {
164                         list_add_tail(&available_sorts[i]->list, list);
165                         return 0;
166                 }
167         }
168
169         return -1;
170 }
171
172 static void setup_sorting(struct perf_kwork *kwork,
173                           const struct option *options,
174                           const char * const usage_msg[])
175 {
176         char *tmp, *tok, *str = strdup(kwork->sort_order);
177
178         for (tok = strtok_r(str, ", ", &tmp);
179              tok; tok = strtok_r(NULL, ", ", &tmp)) {
180                 if (sort_dimension__add(kwork, tok, &kwork->sort_list) < 0)
181                         usage_with_options_msg(usage_msg, options,
182                                                "Unknown --sort key: `%s'", tok);
183         }
184
185         pr_debug("Sort order: %s\n", kwork->sort_order);
186         free(str);
187 }
188
189 static struct kwork_atom *atom_new(struct perf_kwork *kwork,
190                                    struct perf_sample *sample)
191 {
192         unsigned long i;
193         struct kwork_atom_page *page;
194         struct kwork_atom *atom = NULL;
195
196         list_for_each_entry(page, &kwork->atom_page_list, list) {
197                 if (!bitmap_full(page->bitmap, NR_ATOM_PER_PAGE)) {
198                         i = find_first_zero_bit(page->bitmap, NR_ATOM_PER_PAGE);
199                         BUG_ON(i >= NR_ATOM_PER_PAGE);
200                         atom = &page->atoms[i];
201                         goto found_atom;
202                 }
203         }
204
205         /*
206          * new page
207          */
208         page = zalloc(sizeof(*page));
209         if (page == NULL) {
210                 pr_err("Failed to zalloc kwork atom page\n");
211                 return NULL;
212         }
213
214         i = 0;
215         atom = &page->atoms[0];
216         list_add_tail(&page->list, &kwork->atom_page_list);
217
218 found_atom:
219         set_bit(i, page->bitmap);
220         atom->time = sample->time;
221         atom->prev = NULL;
222         atom->page_addr = page;
223         atom->bit_inpage = i;
224         return atom;
225 }
226
227 static void atom_free(struct kwork_atom *atom)
228 {
229         if (atom->prev != NULL)
230                 atom_free(atom->prev);
231
232         clear_bit(atom->bit_inpage,
233                   ((struct kwork_atom_page *)atom->page_addr)->bitmap);
234 }
235
236 static void atom_del(struct kwork_atom *atom)
237 {
238         list_del(&atom->list);
239         atom_free(atom);
240 }
241
242 static int work_cmp(struct list_head *list,
243                     struct kwork_work *l, struct kwork_work *r)
244 {
245         int ret = 0;
246         struct sort_dimension *sort;
247
248         BUG_ON(list_empty(list));
249
250         list_for_each_entry(sort, list, list) {
251                 ret = sort->cmp(l, r);
252                 if (ret)
253                         return ret;
254         }
255
256         return ret;
257 }
258
259 static struct kwork_work *work_search(struct rb_root_cached *root,
260                                       struct kwork_work *key,
261                                       struct list_head *sort_list)
262 {
263         int cmp;
264         struct kwork_work *work;
265         struct rb_node *node = root->rb_root.rb_node;
266
267         while (node) {
268                 work = container_of(node, struct kwork_work, node);
269                 cmp = work_cmp(sort_list, key, work);
270                 if (cmp > 0)
271                         node = node->rb_left;
272                 else if (cmp < 0)
273                         node = node->rb_right;
274                 else {
275                         if (work->name == NULL)
276                                 work->name = key->name;
277                         return work;
278                 }
279         }
280         return NULL;
281 }
282
283 static void work_insert(struct rb_root_cached *root,
284                         struct kwork_work *key, struct list_head *sort_list)
285 {
286         int cmp;
287         bool leftmost = true;
288         struct kwork_work *cur;
289         struct rb_node **new = &(root->rb_root.rb_node), *parent = NULL;
290
291         while (*new) {
292                 cur = container_of(*new, struct kwork_work, node);
293                 parent = *new;
294                 cmp = work_cmp(sort_list, key, cur);
295
296                 if (cmp > 0)
297                         new = &((*new)->rb_left);
298                 else {
299                         new = &((*new)->rb_right);
300                         leftmost = false;
301                 }
302         }
303
304         rb_link_node(&key->node, parent, new);
305         rb_insert_color_cached(&key->node, root, leftmost);
306 }
307
308 static struct kwork_work *work_new(struct kwork_work *key)
309 {
310         int i;
311         struct kwork_work *work = zalloc(sizeof(*work));
312
313         if (work == NULL) {
314                 pr_err("Failed to zalloc kwork work\n");
315                 return NULL;
316         }
317
318         for (i = 0; i < KWORK_TRACE_MAX; i++)
319                 INIT_LIST_HEAD(&work->atom_list[i]);
320
321         work->id = key->id;
322         work->cpu = key->cpu;
323         work->name = key->name;
324         work->class = key->class;
325         return work;
326 }
327
328 static struct kwork_work *work_findnew(struct rb_root_cached *root,
329                                        struct kwork_work *key,
330                                        struct list_head *sort_list)
331 {
332         struct kwork_work *work = work_search(root, key, sort_list);
333
334         if (work != NULL)
335                 return work;
336
337         work = work_new(key);
338         if (work)
339                 work_insert(root, work, sort_list);
340
341         return work;
342 }
343
344 static void profile_update_timespan(struct perf_kwork *kwork,
345                                     struct perf_sample *sample)
346 {
347         if (!kwork->summary)
348                 return;
349
350         if ((kwork->timestart == 0) || (kwork->timestart > sample->time))
351                 kwork->timestart = sample->time;
352
353         if (kwork->timeend < sample->time)
354                 kwork->timeend = sample->time;
355 }
356
357 static bool profile_event_match(struct perf_kwork *kwork,
358                                 struct kwork_work *work,
359                                 struct perf_sample *sample)
360 {
361         int cpu = work->cpu;
362         u64 time = sample->time;
363         struct perf_time_interval *ptime = &kwork->ptime;
364
365         if ((kwork->cpu_list != NULL) && !test_bit(cpu, kwork->cpu_bitmap))
366                 return false;
367
368         if (((ptime->start != 0) && (ptime->start > time)) ||
369             ((ptime->end != 0) && (ptime->end < time)))
370                 return false;
371
372         if ((kwork->profile_name != NULL) &&
373             (work->name != NULL) &&
374             (strcmp(work->name, kwork->profile_name) != 0))
375                 return false;
376
377         profile_update_timespan(kwork, sample);
378         return true;
379 }
380
381 static int work_push_atom(struct perf_kwork *kwork,
382                           struct kwork_class *class,
383                           enum kwork_trace_type src_type,
384                           enum kwork_trace_type dst_type,
385                           struct evsel *evsel,
386                           struct perf_sample *sample,
387                           struct machine *machine,
388                           struct kwork_work **ret_work)
389 {
390         struct kwork_atom *atom, *dst_atom;
391         struct kwork_work *work, key;
392
393         BUG_ON(class->work_init == NULL);
394         class->work_init(class, &key, evsel, sample, machine);
395
396         atom = atom_new(kwork, sample);
397         if (atom == NULL)
398                 return -1;
399
400         work = work_findnew(&class->work_root, &key, &kwork->cmp_id);
401         if (work == NULL) {
402                 free(atom);
403                 return -1;
404         }
405
406         if (!profile_event_match(kwork, work, sample))
407                 return 0;
408
409         if (dst_type < KWORK_TRACE_MAX) {
410                 dst_atom = list_last_entry_or_null(&work->atom_list[dst_type],
411                                                    struct kwork_atom, list);
412                 if (dst_atom != NULL) {
413                         atom->prev = dst_atom;
414                         list_del(&dst_atom->list);
415                 }
416         }
417
418         if (ret_work != NULL)
419                 *ret_work = work;
420
421         list_add_tail(&atom->list, &work->atom_list[src_type]);
422
423         return 0;
424 }
425
426 static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork,
427                                         struct kwork_class *class,
428                                         enum kwork_trace_type src_type,
429                                         enum kwork_trace_type dst_type,
430                                         struct evsel *evsel,
431                                         struct perf_sample *sample,
432                                         struct machine *machine,
433                                         struct kwork_work **ret_work)
434 {
435         struct kwork_atom *atom, *src_atom;
436         struct kwork_work *work, key;
437
438         BUG_ON(class->work_init == NULL);
439         class->work_init(class, &key, evsel, sample, machine);
440
441         work = work_findnew(&class->work_root, &key, &kwork->cmp_id);
442         if (ret_work != NULL)
443                 *ret_work = work;
444
445         if (work == NULL)
446                 return NULL;
447
448         if (!profile_event_match(kwork, work, sample))
449                 return NULL;
450
451         atom = list_last_entry_or_null(&work->atom_list[dst_type],
452                                        struct kwork_atom, list);
453         if (atom != NULL)
454                 return atom;
455
456         src_atom = atom_new(kwork, sample);
457         if (src_atom != NULL)
458                 list_add_tail(&src_atom->list, &work->atom_list[src_type]);
459         else {
460                 if (ret_work != NULL)
461                         *ret_work = NULL;
462         }
463
464         return NULL;
465 }
466
467 static void report_update_exit_event(struct kwork_work *work,
468                                      struct kwork_atom *atom,
469                                      struct perf_sample *sample)
470 {
471         u64 delta;
472         u64 exit_time = sample->time;
473         u64 entry_time = atom->time;
474
475         if ((entry_time != 0) && (exit_time >= entry_time)) {
476                 delta = exit_time - entry_time;
477                 if ((delta > work->max_runtime) ||
478                     (work->max_runtime == 0)) {
479                         work->max_runtime = delta;
480                         work->max_runtime_start = entry_time;
481                         work->max_runtime_end = exit_time;
482                 }
483                 work->total_runtime += delta;
484                 work->nr_atoms++;
485         }
486 }
487
488 static int report_entry_event(struct perf_kwork *kwork,
489                               struct kwork_class *class,
490                               struct evsel *evsel,
491                               struct perf_sample *sample,
492                               struct machine *machine)
493 {
494         return work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
495                               KWORK_TRACE_MAX, evsel, sample,
496                               machine, NULL);
497 }
498
499 static int report_exit_event(struct perf_kwork *kwork,
500                              struct kwork_class *class,
501                              struct evsel *evsel,
502                              struct perf_sample *sample,
503                              struct machine *machine)
504 {
505         struct kwork_atom *atom = NULL;
506         struct kwork_work *work = NULL;
507
508         atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
509                              KWORK_TRACE_ENTRY, evsel, sample,
510                              machine, &work);
511         if (work == NULL)
512                 return -1;
513
514         if (atom != NULL) {
515                 report_update_exit_event(work, atom, sample);
516                 atom_del(atom);
517         }
518
519         return 0;
520 }
521
522 static void latency_update_entry_event(struct kwork_work *work,
523                                        struct kwork_atom *atom,
524                                        struct perf_sample *sample)
525 {
526         u64 delta;
527         u64 entry_time = sample->time;
528         u64 raise_time = atom->time;
529
530         if ((raise_time != 0) && (entry_time >= raise_time)) {
531                 delta = entry_time - raise_time;
532                 if ((delta > work->max_latency) ||
533                     (work->max_latency == 0)) {
534                         work->max_latency = delta;
535                         work->max_latency_start = raise_time;
536                         work->max_latency_end = entry_time;
537                 }
538                 work->total_latency += delta;
539                 work->nr_atoms++;
540         }
541 }
542
543 static int latency_raise_event(struct perf_kwork *kwork,
544                                struct kwork_class *class,
545                                struct evsel *evsel,
546                                struct perf_sample *sample,
547                                struct machine *machine)
548 {
549         return work_push_atom(kwork, class, KWORK_TRACE_RAISE,
550                               KWORK_TRACE_MAX, evsel, sample,
551                               machine, NULL);
552 }
553
554 static int latency_entry_event(struct perf_kwork *kwork,
555                                struct kwork_class *class,
556                                struct evsel *evsel,
557                                struct perf_sample *sample,
558                                struct machine *machine)
559 {
560         struct kwork_atom *atom = NULL;
561         struct kwork_work *work = NULL;
562
563         atom = work_pop_atom(kwork, class, KWORK_TRACE_ENTRY,
564                              KWORK_TRACE_RAISE, evsel, sample,
565                              machine, &work);
566         if (work == NULL)
567                 return -1;
568
569         if (atom != NULL) {
570                 latency_update_entry_event(work, atom, sample);
571                 atom_del(atom);
572         }
573
574         return 0;
575 }
576
577 static void timehist_save_callchain(struct perf_kwork *kwork,
578                                     struct perf_sample *sample,
579                                     struct evsel *evsel,
580                                     struct machine *machine)
581 {
582         struct symbol *sym;
583         struct thread *thread;
584         struct callchain_cursor_node *node;
585         struct callchain_cursor *cursor = &callchain_cursor;
586
587         if (!kwork->show_callchain || sample->callchain == NULL)
588                 return;
589
590         /* want main thread for process - has maps */
591         thread = machine__findnew_thread(machine, sample->pid, sample->pid);
592         if (thread == NULL) {
593                 pr_debug("Failed to get thread for pid %d\n", sample->pid);
594                 return;
595         }
596
597         if (thread__resolve_callchain(thread, cursor, evsel, sample,
598                                       NULL, NULL, kwork->max_stack + 2) != 0) {
599                 pr_debug("Failed to resolve callchain, skipping\n");
600                 goto out_put;
601         }
602
603         callchain_cursor_commit(cursor);
604
605         while (true) {
606                 node = callchain_cursor_current(cursor);
607                 if (node == NULL)
608                         break;
609
610                 sym = node->ms.sym;
611                 if (sym) {
612                         if (!strcmp(sym->name, "__softirqentry_text_start") ||
613                             !strcmp(sym->name, "__do_softirq"))
614                                 sym->ignore = 1;
615                 }
616
617                 callchain_cursor_advance(cursor);
618         }
619
620 out_put:
621         thread__put(thread);
622 }
623
624 static void timehist_print_event(struct perf_kwork *kwork,
625                                  struct kwork_work *work,
626                                  struct kwork_atom *atom,
627                                  struct perf_sample *sample,
628                                  struct addr_location *al)
629 {
630         char entrytime[32], exittime[32];
631         char kwork_name[PRINT_KWORK_NAME_WIDTH];
632
633         /*
634          * runtime start
635          */
636         timestamp__scnprintf_usec(atom->time,
637                                   entrytime, sizeof(entrytime));
638         printf(" %*s ", PRINT_TIMESTAMP_WIDTH, entrytime);
639
640         /*
641          * runtime end
642          */
643         timestamp__scnprintf_usec(sample->time,
644                                   exittime, sizeof(exittime));
645         printf(" %*s ", PRINT_TIMESTAMP_WIDTH, exittime);
646
647         /*
648          * cpu
649          */
650         printf(" [%0*d] ", PRINT_CPU_WIDTH, work->cpu);
651
652         /*
653          * kwork name
654          */
655         if (work->class && work->class->work_name) {
656                 work->class->work_name(work, kwork_name,
657                                        PRINT_KWORK_NAME_WIDTH);
658                 printf(" %-*s ", PRINT_KWORK_NAME_WIDTH, kwork_name);
659         } else
660                 printf(" %-*s ", PRINT_KWORK_NAME_WIDTH, "");
661
662         /*
663          *runtime
664          */
665         printf(" %*.*f ",
666                PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
667                (double)(sample->time - atom->time) / NSEC_PER_MSEC);
668
669         /*
670          * delaytime
671          */
672         if (atom->prev != NULL)
673                 printf(" %*.*f ", PRINT_LATENCY_WIDTH, RPINT_DECIMAL_WIDTH,
674                        (double)(atom->time - atom->prev->time) / NSEC_PER_MSEC);
675         else
676                 printf(" %*s ", PRINT_LATENCY_WIDTH, " ");
677
678         /*
679          * callchain
680          */
681         if (kwork->show_callchain) {
682                 printf(" ");
683                 sample__fprintf_sym(sample, al, 0,
684                                     EVSEL__PRINT_SYM | EVSEL__PRINT_ONELINE |
685                                     EVSEL__PRINT_CALLCHAIN_ARROW |
686                                     EVSEL__PRINT_SKIP_IGNORED,
687                                     &callchain_cursor, symbol_conf.bt_stop_list,
688                                     stdout);
689         }
690
691         printf("\n");
692 }
693
694 static int timehist_raise_event(struct perf_kwork *kwork,
695                                 struct kwork_class *class,
696                                 struct evsel *evsel,
697                                 struct perf_sample *sample,
698                                 struct machine *machine)
699 {
700         return work_push_atom(kwork, class, KWORK_TRACE_RAISE,
701                               KWORK_TRACE_MAX, evsel, sample,
702                               machine, NULL);
703 }
704
705 static int timehist_entry_event(struct perf_kwork *kwork,
706                                 struct kwork_class *class,
707                                 struct evsel *evsel,
708                                 struct perf_sample *sample,
709                                 struct machine *machine)
710 {
711         int ret;
712         struct kwork_work *work = NULL;
713
714         ret = work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
715                              KWORK_TRACE_RAISE, evsel, sample,
716                              machine, &work);
717         if (ret)
718                 return ret;
719
720         if (work != NULL)
721                 timehist_save_callchain(kwork, sample, evsel, machine);
722
723         return 0;
724 }
725
726 static int timehist_exit_event(struct perf_kwork *kwork,
727                                struct kwork_class *class,
728                                struct evsel *evsel,
729                                struct perf_sample *sample,
730                                struct machine *machine)
731 {
732         struct kwork_atom *atom = NULL;
733         struct kwork_work *work = NULL;
734         struct addr_location al;
735
736         if (machine__resolve(machine, &al, sample) < 0) {
737                 pr_debug("Problem processing event, skipping it\n");
738                 return -1;
739         }
740
741         atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
742                              KWORK_TRACE_ENTRY, evsel, sample,
743                              machine, &work);
744         if (work == NULL)
745                 return -1;
746
747         if (atom != NULL) {
748                 work->nr_atoms++;
749                 timehist_print_event(kwork, work, atom, sample, &al);
750                 atom_del(atom);
751         }
752
753         return 0;
754 }
755
756 static struct kwork_class kwork_irq;
757 static int process_irq_handler_entry_event(struct perf_tool *tool,
758                                            struct evsel *evsel,
759                                            struct perf_sample *sample,
760                                            struct machine *machine)
761 {
762         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
763
764         if (kwork->tp_handler->entry_event)
765                 return kwork->tp_handler->entry_event(kwork, &kwork_irq,
766                                                       evsel, sample, machine);
767         return 0;
768 }
769
770 static int process_irq_handler_exit_event(struct perf_tool *tool,
771                                           struct evsel *evsel,
772                                           struct perf_sample *sample,
773                                           struct machine *machine)
774 {
775         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
776
777         if (kwork->tp_handler->exit_event)
778                 return kwork->tp_handler->exit_event(kwork, &kwork_irq,
779                                                      evsel, sample, machine);
780         return 0;
781 }
782
783 const struct evsel_str_handler irq_tp_handlers[] = {
784         { "irq:irq_handler_entry", process_irq_handler_entry_event, },
785         { "irq:irq_handler_exit",  process_irq_handler_exit_event,  },
786 };
787
788 static int irq_class_init(struct kwork_class *class,
789                           struct perf_session *session)
790 {
791         if (perf_session__set_tracepoints_handlers(session, irq_tp_handlers)) {
792                 pr_err("Failed to set irq tracepoints handlers\n");
793                 return -1;
794         }
795
796         class->work_root = RB_ROOT_CACHED;
797         return 0;
798 }
799
800 static void irq_work_init(struct kwork_class *class,
801                           struct kwork_work *work,
802                           struct evsel *evsel,
803                           struct perf_sample *sample,
804                           struct machine *machine __maybe_unused)
805 {
806         work->class = class;
807         work->cpu = sample->cpu;
808         work->id = evsel__intval(evsel, sample, "irq");
809         work->name = evsel__strval(evsel, sample, "name");
810 }
811
812 static void irq_work_name(struct kwork_work *work, char *buf, int len)
813 {
814         snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id);
815 }
816
817 static struct kwork_class kwork_irq = {
818         .name           = "irq",
819         .type           = KWORK_CLASS_IRQ,
820         .nr_tracepoints = 2,
821         .tp_handlers    = irq_tp_handlers,
822         .class_init     = irq_class_init,
823         .work_init      = irq_work_init,
824         .work_name      = irq_work_name,
825 };
826
827 static struct kwork_class kwork_softirq;
828 static int process_softirq_raise_event(struct perf_tool *tool,
829                                        struct evsel *evsel,
830                                        struct perf_sample *sample,
831                                        struct machine *machine)
832 {
833         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
834
835         if (kwork->tp_handler->raise_event)
836                 return kwork->tp_handler->raise_event(kwork, &kwork_softirq,
837                                                       evsel, sample, machine);
838
839         return 0;
840 }
841
842 static int process_softirq_entry_event(struct perf_tool *tool,
843                                        struct evsel *evsel,
844                                        struct perf_sample *sample,
845                                        struct machine *machine)
846 {
847         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
848
849         if (kwork->tp_handler->entry_event)
850                 return kwork->tp_handler->entry_event(kwork, &kwork_softirq,
851                                                       evsel, sample, machine);
852
853         return 0;
854 }
855
856 static int process_softirq_exit_event(struct perf_tool *tool,
857                                       struct evsel *evsel,
858                                       struct perf_sample *sample,
859                                       struct machine *machine)
860 {
861         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
862
863         if (kwork->tp_handler->exit_event)
864                 return kwork->tp_handler->exit_event(kwork, &kwork_softirq,
865                                                      evsel, sample, machine);
866
867         return 0;
868 }
869
870 const struct evsel_str_handler softirq_tp_handlers[] = {
871         { "irq:softirq_raise", process_softirq_raise_event, },
872         { "irq:softirq_entry", process_softirq_entry_event, },
873         { "irq:softirq_exit",  process_softirq_exit_event,  },
874 };
875
876 static int softirq_class_init(struct kwork_class *class,
877                               struct perf_session *session)
878 {
879         if (perf_session__set_tracepoints_handlers(session,
880                                                    softirq_tp_handlers)) {
881                 pr_err("Failed to set softirq tracepoints handlers\n");
882                 return -1;
883         }
884
885         class->work_root = RB_ROOT_CACHED;
886         return 0;
887 }
888
889 static char *evsel__softirq_name(struct evsel *evsel, u64 num)
890 {
891         char *name = NULL;
892         bool found = false;
893         struct tep_print_flag_sym *sym = NULL;
894         struct tep_print_arg *args = evsel->tp_format->print_fmt.args;
895
896         if ((args == NULL) || (args->next == NULL))
897                 return NULL;
898
899         /* skip softirq field: "REC->vec" */
900         for (sym = args->next->symbol.symbols; sym != NULL; sym = sym->next) {
901                 if ((eval_flag(sym->value) == (unsigned long long)num) &&
902                     (strlen(sym->str) != 0)) {
903                         found = true;
904                         break;
905                 }
906         }
907
908         if (!found)
909                 return NULL;
910
911         name = strdup(sym->str);
912         if (name == NULL) {
913                 pr_err("Failed to copy symbol name\n");
914                 return NULL;
915         }
916         return name;
917 }
918
919 static void softirq_work_init(struct kwork_class *class,
920                               struct kwork_work *work,
921                               struct evsel *evsel,
922                               struct perf_sample *sample,
923                               struct machine *machine __maybe_unused)
924 {
925         u64 num = evsel__intval(evsel, sample, "vec");
926
927         work->id = num;
928         work->class = class;
929         work->cpu = sample->cpu;
930         work->name = evsel__softirq_name(evsel, num);
931 }
932
933 static void softirq_work_name(struct kwork_work *work, char *buf, int len)
934 {
935         snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id);
936 }
937
938 static struct kwork_class kwork_softirq = {
939         .name           = "softirq",
940         .type           = KWORK_CLASS_SOFTIRQ,
941         .nr_tracepoints = 3,
942         .tp_handlers    = softirq_tp_handlers,
943         .class_init     = softirq_class_init,
944         .work_init      = softirq_work_init,
945         .work_name      = softirq_work_name,
946 };
947
948 static struct kwork_class kwork_workqueue;
949 static int process_workqueue_activate_work_event(struct perf_tool *tool,
950                                                  struct evsel *evsel,
951                                                  struct perf_sample *sample,
952                                                  struct machine *machine)
953 {
954         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
955
956         if (kwork->tp_handler->raise_event)
957                 return kwork->tp_handler->raise_event(kwork, &kwork_workqueue,
958                                                     evsel, sample, machine);
959
960         return 0;
961 }
962
963 static int process_workqueue_execute_start_event(struct perf_tool *tool,
964                                                  struct evsel *evsel,
965                                                  struct perf_sample *sample,
966                                                  struct machine *machine)
967 {
968         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
969
970         if (kwork->tp_handler->entry_event)
971                 return kwork->tp_handler->entry_event(kwork, &kwork_workqueue,
972                                                     evsel, sample, machine);
973
974         return 0;
975 }
976
977 static int process_workqueue_execute_end_event(struct perf_tool *tool,
978                                                struct evsel *evsel,
979                                                struct perf_sample *sample,
980                                                struct machine *machine)
981 {
982         struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool);
983
984         if (kwork->tp_handler->exit_event)
985                 return kwork->tp_handler->exit_event(kwork, &kwork_workqueue,
986                                                    evsel, sample, machine);
987
988         return 0;
989 }
990
991 const struct evsel_str_handler workqueue_tp_handlers[] = {
992         { "workqueue:workqueue_activate_work", process_workqueue_activate_work_event, },
993         { "workqueue:workqueue_execute_start", process_workqueue_execute_start_event, },
994         { "workqueue:workqueue_execute_end",   process_workqueue_execute_end_event,   },
995 };
996
997 static int workqueue_class_init(struct kwork_class *class,
998                                 struct perf_session *session)
999 {
1000         if (perf_session__set_tracepoints_handlers(session,
1001                                                    workqueue_tp_handlers)) {
1002                 pr_err("Failed to set workqueue tracepoints handlers\n");
1003                 return -1;
1004         }
1005
1006         class->work_root = RB_ROOT_CACHED;
1007         return 0;
1008 }
1009
1010 static void workqueue_work_init(struct kwork_class *class,
1011                                 struct kwork_work *work,
1012                                 struct evsel *evsel,
1013                                 struct perf_sample *sample,
1014                                 struct machine *machine)
1015 {
1016         char *modp = NULL;
1017         unsigned long long function_addr = evsel__intval(evsel,
1018                                                          sample, "function");
1019
1020         work->class = class;
1021         work->cpu = sample->cpu;
1022         work->id = evsel__intval(evsel, sample, "work");
1023         work->name = function_addr == 0 ? NULL :
1024                 machine__resolve_kernel_addr(machine, &function_addr, &modp);
1025 }
1026
1027 static void workqueue_work_name(struct kwork_work *work, char *buf, int len)
1028 {
1029         if (work->name != NULL)
1030                 snprintf(buf, len, "(w)%s", work->name);
1031         else
1032                 snprintf(buf, len, "(w)0x%" PRIx64, work->id);
1033 }
1034
1035 static struct kwork_class kwork_workqueue = {
1036         .name           = "workqueue",
1037         .type           = KWORK_CLASS_WORKQUEUE,
1038         .nr_tracepoints = 3,
1039         .tp_handlers    = workqueue_tp_handlers,
1040         .class_init     = workqueue_class_init,
1041         .work_init      = workqueue_work_init,
1042         .work_name      = workqueue_work_name,
1043 };
1044
1045 static struct kwork_class *kwork_class_supported_list[KWORK_CLASS_MAX] = {
1046         [KWORK_CLASS_IRQ]       = &kwork_irq,
1047         [KWORK_CLASS_SOFTIRQ]   = &kwork_softirq,
1048         [KWORK_CLASS_WORKQUEUE] = &kwork_workqueue,
1049 };
1050
1051 static void print_separator(int len)
1052 {
1053         printf(" %.*s\n", len, graph_dotted_line);
1054 }
1055
1056 static int report_print_work(struct perf_kwork *kwork, struct kwork_work *work)
1057 {
1058         int ret = 0;
1059         char kwork_name[PRINT_KWORK_NAME_WIDTH];
1060         char max_runtime_start[32], max_runtime_end[32];
1061         char max_latency_start[32], max_latency_end[32];
1062
1063         printf(" ");
1064
1065         /*
1066          * kwork name
1067          */
1068         if (work->class && work->class->work_name) {
1069                 work->class->work_name(work, kwork_name,
1070                                        PRINT_KWORK_NAME_WIDTH);
1071                 ret += printf(" %-*s |", PRINT_KWORK_NAME_WIDTH, kwork_name);
1072         } else {
1073                 ret += printf(" %-*s |", PRINT_KWORK_NAME_WIDTH, "");
1074         }
1075
1076         /*
1077          * cpu
1078          */
1079         ret += printf(" %0*d |", PRINT_CPU_WIDTH, work->cpu);
1080
1081         /*
1082          * total runtime
1083          */
1084         if (kwork->report == KWORK_REPORT_RUNTIME) {
1085                 ret += printf(" %*.*f ms |",
1086                               PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
1087                               (double)work->total_runtime / NSEC_PER_MSEC);
1088         } else if (kwork->report == KWORK_REPORT_LATENCY) { // avg delay
1089                 ret += printf(" %*.*f ms |",
1090                               PRINT_LATENCY_WIDTH, RPINT_DECIMAL_WIDTH,
1091                               (double)work->total_latency /
1092                               work->nr_atoms / NSEC_PER_MSEC);
1093         }
1094
1095         /*
1096          * count
1097          */
1098         ret += printf(" %*" PRIu64 " |", PRINT_COUNT_WIDTH, work->nr_atoms);
1099
1100         /*
1101          * max runtime, max runtime start, max runtime end
1102          */
1103         if (kwork->report == KWORK_REPORT_RUNTIME) {
1104                 timestamp__scnprintf_usec(work->max_runtime_start,
1105                                           max_runtime_start,
1106                                           sizeof(max_runtime_start));
1107                 timestamp__scnprintf_usec(work->max_runtime_end,
1108                                           max_runtime_end,
1109                                           sizeof(max_runtime_end));
1110                 ret += printf(" %*.*f ms | %*s s | %*s s |",
1111                               PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH,
1112                               (double)work->max_runtime / NSEC_PER_MSEC,
1113                               PRINT_TIMESTAMP_WIDTH, max_runtime_start,
1114                               PRINT_TIMESTAMP_WIDTH, max_runtime_end);
1115         }
1116         /*
1117          * max delay, max delay start, max delay end
1118          */
1119         else if (kwork->report == KWORK_REPORT_LATENCY) {
1120                 timestamp__scnprintf_usec(work->max_latency_start,
1121                                           max_latency_start,
1122                                           sizeof(max_latency_start));
1123                 timestamp__scnprintf_usec(work->max_latency_end,
1124                                           max_latency_end,
1125                                           sizeof(max_latency_end));
1126                 ret += printf(" %*.*f ms | %*s s | %*s s |",
1127                               PRINT_LATENCY_WIDTH, RPINT_DECIMAL_WIDTH,
1128                               (double)work->max_latency / NSEC_PER_MSEC,
1129                               PRINT_TIMESTAMP_WIDTH, max_latency_start,
1130                               PRINT_TIMESTAMP_WIDTH, max_latency_end);
1131         }
1132
1133         printf("\n");
1134         return ret;
1135 }
1136
1137 static int report_print_header(struct perf_kwork *kwork)
1138 {
1139         int ret;
1140
1141         printf("\n ");
1142         ret = printf(" %-*s | %-*s |",
1143                      PRINT_KWORK_NAME_WIDTH, "Kwork Name",
1144                      PRINT_CPU_WIDTH, "Cpu");
1145
1146         if (kwork->report == KWORK_REPORT_RUNTIME) {
1147                 ret += printf(" %-*s |",
1148                               PRINT_RUNTIME_HEADER_WIDTH, "Total Runtime");
1149         } else if (kwork->report == KWORK_REPORT_LATENCY) {
1150                 ret += printf(" %-*s |",
1151                               PRINT_LATENCY_HEADER_WIDTH, "Avg delay");
1152         }
1153
1154         ret += printf(" %-*s |", PRINT_COUNT_WIDTH, "Count");
1155
1156         if (kwork->report == KWORK_REPORT_RUNTIME) {
1157                 ret += printf(" %-*s | %-*s | %-*s |",
1158                               PRINT_RUNTIME_HEADER_WIDTH, "Max runtime",
1159                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max runtime start",
1160                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max runtime end");
1161         } else if (kwork->report == KWORK_REPORT_LATENCY) {
1162                 ret += printf(" %-*s | %-*s | %-*s |",
1163                               PRINT_LATENCY_HEADER_WIDTH, "Max delay",
1164                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max delay start",
1165                               PRINT_TIMESTAMP_HEADER_WIDTH, "Max delay end");
1166         }
1167
1168         printf("\n");
1169         print_separator(ret);
1170         return ret;
1171 }
1172
1173 static void timehist_print_header(void)
1174 {
1175         /*
1176          * header row
1177          */
1178         printf(" %-*s  %-*s  %-*s  %-*s  %-*s  %-*s\n",
1179                PRINT_TIMESTAMP_WIDTH, "Runtime start",
1180                PRINT_TIMESTAMP_WIDTH, "Runtime end",
1181                PRINT_TIMEHIST_CPU_WIDTH, "Cpu",
1182                PRINT_KWORK_NAME_WIDTH, "Kwork name",
1183                PRINT_RUNTIME_WIDTH, "Runtime",
1184                PRINT_RUNTIME_WIDTH, "Delaytime");
1185
1186         /*
1187          * units row
1188          */
1189         printf(" %-*s  %-*s  %-*s  %-*s  %-*s  %-*s\n",
1190                PRINT_TIMESTAMP_WIDTH, "",
1191                PRINT_TIMESTAMP_WIDTH, "",
1192                PRINT_TIMEHIST_CPU_WIDTH, "",
1193                PRINT_KWORK_NAME_WIDTH, "(TYPE)NAME:NUM",
1194                PRINT_RUNTIME_WIDTH, "(msec)",
1195                PRINT_RUNTIME_WIDTH, "(msec)");
1196
1197         /*
1198          * separator
1199          */
1200         printf(" %.*s  %.*s  %.*s  %.*s  %.*s  %.*s\n",
1201                PRINT_TIMESTAMP_WIDTH, graph_dotted_line,
1202                PRINT_TIMESTAMP_WIDTH, graph_dotted_line,
1203                PRINT_TIMEHIST_CPU_WIDTH, graph_dotted_line,
1204                PRINT_KWORK_NAME_WIDTH, graph_dotted_line,
1205                PRINT_RUNTIME_WIDTH, graph_dotted_line,
1206                PRINT_RUNTIME_WIDTH, graph_dotted_line);
1207 }
1208
1209 static void print_summary(struct perf_kwork *kwork)
1210 {
1211         u64 time = kwork->timeend - kwork->timestart;
1212
1213         printf("  Total count            : %9" PRIu64 "\n", kwork->all_count);
1214         printf("  Total runtime   (msec) : %9.3f (%.3f%% load average)\n",
1215                (double)kwork->all_runtime / NSEC_PER_MSEC,
1216                time == 0 ? 0 : (double)kwork->all_runtime / time);
1217         printf("  Total time span (msec) : %9.3f\n",
1218                (double)time / NSEC_PER_MSEC);
1219 }
1220
1221 static unsigned long long nr_list_entry(struct list_head *head)
1222 {
1223         struct list_head *pos;
1224         unsigned long long n = 0;
1225
1226         list_for_each(pos, head)
1227                 n++;
1228
1229         return n;
1230 }
1231
1232 static void print_skipped_events(struct perf_kwork *kwork)
1233 {
1234         int i;
1235         const char *const kwork_event_str[] = {
1236                 [KWORK_TRACE_RAISE] = "raise",
1237                 [KWORK_TRACE_ENTRY] = "entry",
1238                 [KWORK_TRACE_EXIT]  = "exit",
1239         };
1240
1241         if ((kwork->nr_skipped_events[KWORK_TRACE_MAX] != 0) &&
1242             (kwork->nr_events != 0)) {
1243                 printf("  INFO: %.3f%% skipped events (%" PRIu64 " including ",
1244                        (double)kwork->nr_skipped_events[KWORK_TRACE_MAX] /
1245                        (double)kwork->nr_events * 100.0,
1246                        kwork->nr_skipped_events[KWORK_TRACE_MAX]);
1247
1248                 for (i = 0; i < KWORK_TRACE_MAX; i++) {
1249                         printf("%" PRIu64 " %s%s",
1250                                kwork->nr_skipped_events[i],
1251                                kwork_event_str[i],
1252                                (i == KWORK_TRACE_MAX - 1) ? ")\n" : ", ");
1253                 }
1254         }
1255
1256         if (verbose > 0)
1257                 printf("  INFO: use %lld atom pages\n",
1258                        nr_list_entry(&kwork->atom_page_list));
1259 }
1260
1261 static void print_bad_events(struct perf_kwork *kwork)
1262 {
1263         if ((kwork->nr_lost_events != 0) && (kwork->nr_events != 0)) {
1264                 printf("  INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n",
1265                        (double)kwork->nr_lost_events /
1266                        (double)kwork->nr_events * 100.0,
1267                        kwork->nr_lost_events, kwork->nr_events,
1268                        kwork->nr_lost_chunks);
1269         }
1270 }
1271
1272 static void work_sort(struct perf_kwork *kwork, struct kwork_class *class)
1273 {
1274         struct rb_node *node;
1275         struct kwork_work *data;
1276         struct rb_root_cached *root = &class->work_root;
1277
1278         pr_debug("Sorting %s ...\n", class->name);
1279         for (;;) {
1280                 node = rb_first_cached(root);
1281                 if (!node)
1282                         break;
1283
1284                 rb_erase_cached(node, root);
1285                 data = rb_entry(node, struct kwork_work, node);
1286                 work_insert(&kwork->sorted_work_root,
1287                                data, &kwork->sort_list);
1288         }
1289 }
1290
1291 static void perf_kwork__sort(struct perf_kwork *kwork)
1292 {
1293         struct kwork_class *class;
1294
1295         list_for_each_entry(class, &kwork->class_list, list)
1296                 work_sort(kwork, class);
1297 }
1298
1299 static int perf_kwork__check_config(struct perf_kwork *kwork,
1300                                     struct perf_session *session)
1301 {
1302         int ret;
1303         struct evsel *evsel;
1304         struct kwork_class *class;
1305
1306         static struct trace_kwork_handler report_ops = {
1307                 .entry_event = report_entry_event,
1308                 .exit_event  = report_exit_event,
1309         };
1310         static struct trace_kwork_handler latency_ops = {
1311                 .raise_event = latency_raise_event,
1312                 .entry_event = latency_entry_event,
1313         };
1314         static struct trace_kwork_handler timehist_ops = {
1315                 .raise_event = timehist_raise_event,
1316                 .entry_event = timehist_entry_event,
1317                 .exit_event  = timehist_exit_event,
1318         };
1319
1320         switch (kwork->report) {
1321         case KWORK_REPORT_RUNTIME:
1322                 kwork->tp_handler = &report_ops;
1323                 break;
1324         case KWORK_REPORT_LATENCY:
1325                 kwork->tp_handler = &latency_ops;
1326                 break;
1327         case KWORK_REPORT_TIMEHIST:
1328                 kwork->tp_handler = &timehist_ops;
1329                 break;
1330         default:
1331                 pr_debug("Invalid report type %d\n", kwork->report);
1332                 return -1;
1333         }
1334
1335         list_for_each_entry(class, &kwork->class_list, list)
1336                 if ((class->class_init != NULL) &&
1337                     (class->class_init(class, session) != 0))
1338                         return -1;
1339
1340         if (kwork->cpu_list != NULL) {
1341                 ret = perf_session__cpu_bitmap(session,
1342                                                kwork->cpu_list,
1343                                                kwork->cpu_bitmap);
1344                 if (ret < 0) {
1345                         pr_err("Invalid cpu bitmap\n");
1346                         return -1;
1347                 }
1348         }
1349
1350         if (kwork->time_str != NULL) {
1351                 ret = perf_time__parse_str(&kwork->ptime, kwork->time_str);
1352                 if (ret != 0) {
1353                         pr_err("Invalid time span\n");
1354                         return -1;
1355                 }
1356         }
1357
1358         list_for_each_entry(evsel, &session->evlist->core.entries, core.node) {
1359                 if (kwork->show_callchain && !evsel__has_callchain(evsel)) {
1360                         pr_debug("Samples do not have callchains\n");
1361                         kwork->show_callchain = 0;
1362                         symbol_conf.use_callchain = 0;
1363                 }
1364         }
1365
1366         return 0;
1367 }
1368
1369 static int perf_kwork__read_events(struct perf_kwork *kwork)
1370 {
1371         int ret = -1;
1372         struct perf_session *session = NULL;
1373
1374         struct perf_data data = {
1375                 .path  = input_name,
1376                 .mode  = PERF_DATA_MODE_READ,
1377                 .force = kwork->force,
1378         };
1379
1380         session = perf_session__new(&data, &kwork->tool);
1381         if (IS_ERR(session)) {
1382                 pr_debug("Error creating perf session\n");
1383                 return PTR_ERR(session);
1384         }
1385
1386         symbol__init(&session->header.env);
1387
1388         if (perf_kwork__check_config(kwork, session) != 0)
1389                 goto out_delete;
1390
1391         if (session->tevent.pevent &&
1392             tep_set_function_resolver(session->tevent.pevent,
1393                                       machine__resolve_kernel_addr,
1394                                       &session->machines.host) < 0) {
1395                 pr_err("Failed to set libtraceevent function resolver\n");
1396                 goto out_delete;
1397         }
1398
1399         if (kwork->report == KWORK_REPORT_TIMEHIST)
1400                 timehist_print_header();
1401
1402         ret = perf_session__process_events(session);
1403         if (ret) {
1404                 pr_debug("Failed to process events, error %d\n", ret);
1405                 goto out_delete;
1406         }
1407
1408         kwork->nr_events      = session->evlist->stats.nr_events[0];
1409         kwork->nr_lost_events = session->evlist->stats.total_lost;
1410         kwork->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1411
1412 out_delete:
1413         perf_session__delete(session);
1414         return ret;
1415 }
1416
1417 static void process_skipped_events(struct perf_kwork *kwork,
1418                                    struct kwork_work *work)
1419 {
1420         int i;
1421         unsigned long long count;
1422
1423         for (i = 0; i < KWORK_TRACE_MAX; i++) {
1424                 count = nr_list_entry(&work->atom_list[i]);
1425                 kwork->nr_skipped_events[i] += count;
1426                 kwork->nr_skipped_events[KWORK_TRACE_MAX] += count;
1427         }
1428 }
1429
1430 struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork,
1431                                        struct kwork_class *class,
1432                                        struct kwork_work *key)
1433 {
1434         struct kwork_work *work = NULL;
1435
1436         work = work_new(key);
1437         if (work == NULL)
1438                 return NULL;
1439
1440         work_insert(&class->work_root, work, &kwork->cmp_id);
1441         return work;
1442 }
1443
1444 static void sig_handler(int sig)
1445 {
1446         /*
1447          * Simply capture termination signal so that
1448          * the program can continue after pause returns
1449          */
1450         pr_debug("Captuer signal %d\n", sig);
1451 }
1452
1453 static int perf_kwork__report_bpf(struct perf_kwork *kwork)
1454 {
1455         int ret;
1456
1457         signal(SIGINT, sig_handler);
1458         signal(SIGTERM, sig_handler);
1459
1460         ret = perf_kwork__trace_prepare_bpf(kwork);
1461         if (ret)
1462                 return -1;
1463
1464         printf("Starting trace, Hit <Ctrl+C> to stop and report\n");
1465
1466         perf_kwork__trace_start();
1467
1468         /*
1469          * a simple pause, wait here for stop signal
1470          */
1471         pause();
1472
1473         perf_kwork__trace_finish();
1474
1475         perf_kwork__report_read_bpf(kwork);
1476
1477         perf_kwork__report_cleanup_bpf();
1478
1479         return 0;
1480 }
1481
1482 static int perf_kwork__report(struct perf_kwork *kwork)
1483 {
1484         int ret;
1485         struct rb_node *next;
1486         struct kwork_work *work;
1487
1488         if (kwork->use_bpf)
1489                 ret = perf_kwork__report_bpf(kwork);
1490         else
1491                 ret = perf_kwork__read_events(kwork);
1492
1493         if (ret != 0)
1494                 return -1;
1495
1496         perf_kwork__sort(kwork);
1497
1498         setup_pager();
1499
1500         ret = report_print_header(kwork);
1501         next = rb_first_cached(&kwork->sorted_work_root);
1502         while (next) {
1503                 work = rb_entry(next, struct kwork_work, node);
1504                 process_skipped_events(kwork, work);
1505
1506                 if (work->nr_atoms != 0) {
1507                         report_print_work(kwork, work);
1508                         if (kwork->summary) {
1509                                 kwork->all_runtime += work->total_runtime;
1510                                 kwork->all_count += work->nr_atoms;
1511                         }
1512                 }
1513                 next = rb_next(next);
1514         }
1515         print_separator(ret);
1516
1517         if (kwork->summary) {
1518                 print_summary(kwork);
1519                 print_separator(ret);
1520         }
1521
1522         print_bad_events(kwork);
1523         print_skipped_events(kwork);
1524         printf("\n");
1525
1526         return 0;
1527 }
1528
1529 typedef int (*tracepoint_handler)(struct perf_tool *tool,
1530                                   struct evsel *evsel,
1531                                   struct perf_sample *sample,
1532                                   struct machine *machine);
1533
1534 static int perf_kwork__process_tracepoint_sample(struct perf_tool *tool,
1535                                                  union perf_event *event __maybe_unused,
1536                                                  struct perf_sample *sample,
1537                                                  struct evsel *evsel,
1538                                                  struct machine *machine)
1539 {
1540         int err = 0;
1541
1542         if (evsel->handler != NULL) {
1543                 tracepoint_handler f = evsel->handler;
1544
1545                 err = f(tool, evsel, sample, machine);
1546         }
1547
1548         return err;
1549 }
1550
1551 static int perf_kwork__timehist(struct perf_kwork *kwork)
1552 {
1553         /*
1554          * event handlers for timehist option
1555          */
1556         kwork->tool.comm         = perf_event__process_comm;
1557         kwork->tool.exit         = perf_event__process_exit;
1558         kwork->tool.fork         = perf_event__process_fork;
1559         kwork->tool.attr         = perf_event__process_attr;
1560         kwork->tool.tracing_data = perf_event__process_tracing_data;
1561         kwork->tool.build_id     = perf_event__process_build_id;
1562         kwork->tool.ordered_events = true;
1563         kwork->tool.ordering_requires_timestamps = true;
1564         symbol_conf.use_callchain = kwork->show_callchain;
1565
1566         if (symbol__validate_sym_arguments()) {
1567                 pr_err("Failed to validate sym arguments\n");
1568                 return -1;
1569         }
1570
1571         setup_pager();
1572
1573         return perf_kwork__read_events(kwork);
1574 }
1575
1576 static void setup_event_list(struct perf_kwork *kwork,
1577                              const struct option *options,
1578                              const char * const usage_msg[])
1579 {
1580         int i;
1581         struct kwork_class *class;
1582         char *tmp, *tok, *str;
1583
1584         if (kwork->event_list_str == NULL)
1585                 goto null_event_list_str;
1586
1587         str = strdup(kwork->event_list_str);
1588         for (tok = strtok_r(str, ", ", &tmp);
1589              tok; tok = strtok_r(NULL, ", ", &tmp)) {
1590                 for (i = 0; i < KWORK_CLASS_MAX; i++) {
1591                         class = kwork_class_supported_list[i];
1592                         if (strcmp(tok, class->name) == 0) {
1593                                 list_add_tail(&class->list, &kwork->class_list);
1594                                 break;
1595                         }
1596                 }
1597                 if (i == KWORK_CLASS_MAX) {
1598                         usage_with_options_msg(usage_msg, options,
1599                                                "Unknown --event key: `%s'", tok);
1600                 }
1601         }
1602         free(str);
1603
1604 null_event_list_str:
1605         /*
1606          * config all kwork events if not specified
1607          */
1608         if (list_empty(&kwork->class_list)) {
1609                 for (i = 0; i < KWORK_CLASS_MAX; i++) {
1610                         list_add_tail(&kwork_class_supported_list[i]->list,
1611                                       &kwork->class_list);
1612                 }
1613         }
1614
1615         pr_debug("Config event list:");
1616         list_for_each_entry(class, &kwork->class_list, list)
1617                 pr_debug(" %s", class->name);
1618         pr_debug("\n");
1619 }
1620
1621 static int perf_kwork__record(struct perf_kwork *kwork,
1622                               int argc, const char **argv)
1623 {
1624         const char **rec_argv;
1625         unsigned int rec_argc, i, j;
1626         struct kwork_class *class;
1627
1628         const char *const record_args[] = {
1629                 "record",
1630                 "-a",
1631                 "-R",
1632                 "-m", "1024",
1633                 "-c", "1",
1634         };
1635
1636         rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1637
1638         list_for_each_entry(class, &kwork->class_list, list)
1639                 rec_argc += 2 * class->nr_tracepoints;
1640
1641         rec_argv = calloc(rec_argc + 1, sizeof(char *));
1642         if (rec_argv == NULL)
1643                 return -ENOMEM;
1644
1645         for (i = 0; i < ARRAY_SIZE(record_args); i++)
1646                 rec_argv[i] = strdup(record_args[i]);
1647
1648         list_for_each_entry(class, &kwork->class_list, list) {
1649                 for (j = 0; j < class->nr_tracepoints; j++) {
1650                         rec_argv[i++] = strdup("-e");
1651                         rec_argv[i++] = strdup(class->tp_handlers[j].name);
1652                 }
1653         }
1654
1655         for (j = 1; j < (unsigned int)argc; j++, i++)
1656                 rec_argv[i] = argv[j];
1657
1658         BUG_ON(i != rec_argc);
1659
1660         pr_debug("record comm: ");
1661         for (j = 0; j < rec_argc; j++)
1662                 pr_debug("%s ", rec_argv[j]);
1663         pr_debug("\n");
1664
1665         return cmd_record(i, rec_argv);
1666 }
1667
1668 int cmd_kwork(int argc, const char **argv)
1669 {
1670         static struct perf_kwork kwork = {
1671                 .class_list          = LIST_HEAD_INIT(kwork.class_list),
1672                 .tool = {
1673                         .mmap    = perf_event__process_mmap,
1674                         .mmap2   = perf_event__process_mmap2,
1675                         .sample  = perf_kwork__process_tracepoint_sample,
1676                 },
1677                 .atom_page_list      = LIST_HEAD_INIT(kwork.atom_page_list),
1678                 .sort_list           = LIST_HEAD_INIT(kwork.sort_list),
1679                 .cmp_id              = LIST_HEAD_INIT(kwork.cmp_id),
1680                 .sorted_work_root    = RB_ROOT_CACHED,
1681                 .tp_handler          = NULL,
1682                 .profile_name        = NULL,
1683                 .cpu_list            = NULL,
1684                 .time_str            = NULL,
1685                 .force               = false,
1686                 .event_list_str      = NULL,
1687                 .summary             = false,
1688                 .sort_order          = NULL,
1689                 .show_callchain      = false,
1690                 .max_stack           = 5,
1691                 .timestart           = 0,
1692                 .timeend             = 0,
1693                 .nr_events           = 0,
1694                 .nr_lost_chunks      = 0,
1695                 .nr_lost_events      = 0,
1696                 .all_runtime         = 0,
1697                 .all_count           = 0,
1698                 .nr_skipped_events   = { 0 },
1699         };
1700         static const char default_report_sort_order[] = "runtime, max, count";
1701         static const char default_latency_sort_order[] = "avg, max, count";
1702         const struct option kwork_options[] = {
1703         OPT_INCR('v', "verbose", &verbose,
1704                  "be more verbose (show symbol address, etc)"),
1705         OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1706                     "dump raw trace in ASCII"),
1707         OPT_STRING('k', "kwork", &kwork.event_list_str, "kwork",
1708                    "list of kwork to profile (irq, softirq, workqueue, etc)"),
1709         OPT_BOOLEAN('f', "force", &kwork.force, "don't complain, do it"),
1710         OPT_END()
1711         };
1712         const struct option report_options[] = {
1713         OPT_STRING('s', "sort", &kwork.sort_order, "key[,key2...]",
1714                    "sort by key(s): runtime, max, count"),
1715         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
1716                    "list of cpus to profile"),
1717         OPT_STRING('n', "name", &kwork.profile_name, "name",
1718                    "event name to profile"),
1719         OPT_STRING(0, "time", &kwork.time_str, "str",
1720                    "Time span for analysis (start,stop)"),
1721         OPT_STRING('i', "input", &input_name, "file",
1722                    "input file name"),
1723         OPT_BOOLEAN('S', "with-summary", &kwork.summary,
1724                     "Show summary with statistics"),
1725 #ifdef HAVE_BPF_SKEL
1726         OPT_BOOLEAN('b', "use-bpf", &kwork.use_bpf,
1727                     "Use BPF to measure kwork runtime"),
1728 #endif
1729         OPT_PARENT(kwork_options)
1730         };
1731         const struct option latency_options[] = {
1732         OPT_STRING('s', "sort", &kwork.sort_order, "key[,key2...]",
1733                    "sort by key(s): avg, max, count"),
1734         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
1735                    "list of cpus to profile"),
1736         OPT_STRING('n', "name", &kwork.profile_name, "name",
1737                    "event name to profile"),
1738         OPT_STRING(0, "time", &kwork.time_str, "str",
1739                    "Time span for analysis (start,stop)"),
1740         OPT_STRING('i', "input", &input_name, "file",
1741                    "input file name"),
1742 #ifdef HAVE_BPF_SKEL
1743         OPT_BOOLEAN('b', "use-bpf", &kwork.use_bpf,
1744                     "Use BPF to measure kwork latency"),
1745 #endif
1746         OPT_PARENT(kwork_options)
1747         };
1748         const struct option timehist_options[] = {
1749         OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1750                    "file", "vmlinux pathname"),
1751         OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
1752                    "file", "kallsyms pathname"),
1753         OPT_BOOLEAN('g', "call-graph", &kwork.show_callchain,
1754                     "Display call chains if present"),
1755         OPT_UINTEGER(0, "max-stack", &kwork.max_stack,
1756                    "Maximum number of functions to display backtrace."),
1757         OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1758                     "Look for files with symbols relative to this directory"),
1759         OPT_STRING(0, "time", &kwork.time_str, "str",
1760                    "Time span for analysis (start,stop)"),
1761         OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu",
1762                    "list of cpus to profile"),
1763         OPT_STRING('n', "name", &kwork.profile_name, "name",
1764                    "event name to profile"),
1765         OPT_STRING('i', "input", &input_name, "file",
1766                    "input file name"),
1767         OPT_PARENT(kwork_options)
1768         };
1769         const char *kwork_usage[] = {
1770                 NULL,
1771                 NULL
1772         };
1773         const char * const report_usage[] = {
1774                 "perf kwork report [<options>]",
1775                 NULL
1776         };
1777         const char * const latency_usage[] = {
1778                 "perf kwork latency [<options>]",
1779                 NULL
1780         };
1781         const char * const timehist_usage[] = {
1782                 "perf kwork timehist [<options>]",
1783                 NULL
1784         };
1785         const char *const kwork_subcommands[] = {
1786                 "record", "report", "latency", "timehist", NULL
1787         };
1788
1789         argc = parse_options_subcommand(argc, argv, kwork_options,
1790                                         kwork_subcommands, kwork_usage,
1791                                         PARSE_OPT_STOP_AT_NON_OPTION);
1792         if (!argc)
1793                 usage_with_options(kwork_usage, kwork_options);
1794
1795         setup_event_list(&kwork, kwork_options, kwork_usage);
1796         sort_dimension__add(&kwork, "id", &kwork.cmp_id);
1797
1798         if (strlen(argv[0]) > 2 && strstarts("record", argv[0]))
1799                 return perf_kwork__record(&kwork, argc, argv);
1800         else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
1801                 kwork.sort_order = default_report_sort_order;
1802                 if (argc > 1) {
1803                         argc = parse_options(argc, argv, report_options, report_usage, 0);
1804                         if (argc)
1805                                 usage_with_options(report_usage, report_options);
1806                 }
1807                 kwork.report = KWORK_REPORT_RUNTIME;
1808                 setup_sorting(&kwork, report_options, report_usage);
1809                 return perf_kwork__report(&kwork);
1810         } else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) {
1811                 kwork.sort_order = default_latency_sort_order;
1812                 if (argc > 1) {
1813                         argc = parse_options(argc, argv, latency_options, latency_usage, 0);
1814                         if (argc)
1815                                 usage_with_options(latency_usage, latency_options);
1816                 }
1817                 kwork.report = KWORK_REPORT_LATENCY;
1818                 setup_sorting(&kwork, latency_options, latency_usage);
1819                 return perf_kwork__report(&kwork);
1820         } else if (strlen(argv[0]) > 2 && strstarts("timehist", argv[0])) {
1821                 if (argc > 1) {
1822                         argc = parse_options(argc, argv, timehist_options, timehist_usage, 0);
1823                         if (argc)
1824                                 usage_with_options(timehist_usage, timehist_options);
1825                 }
1826                 kwork.report = KWORK_REPORT_TIMEHIST;
1827                 return perf_kwork__timehist(&kwork);
1828         } else
1829                 usage_with_options(kwork_usage, kwork_options);
1830
1831         return 0;
1832 }