~ [ 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 (Version linux-6.11.5) and /tools/perf/builtin-kwork.c (Version linux-6.5.13)


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

~ [ 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