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


** Warning: Cannot open xref database.

  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * builtin-kwork.c                                
  4  *                                                
  5  * Copyright (c) 2022  Huawei Inc,  Yang Jihon    
  6  */                                               
  7                                                   
  8 #include "builtin.h"                              
  9                                                   
 10 #include "util/data.h"                            
 11 #include "util/evlist.h"                          
 12 #include "util/evsel.h"                           
 13 #include "util/header.h"                          
 14 #include "util/kwork.h"                           
 15 #include "util/debug.h"                           
 16 #include "util/session.h"                         
 17 #include "util/symbol.h"                          
 18 #include "util/thread.h"                          
 19 #include "util/string2.h"                         
 20 #include "util/callchain.h"                       
 21 #include "util/evsel_fprintf.h"                   
 22 #include "util/util.h"                            
 23                                                   
 24 #include <subcmd/pager.h>                         
 25 #include <subcmd/parse-options.h>                 
 26 #include <traceevent/event-parse.h>               
 27                                                   
 28 #include <errno.h>                                
 29 #include <inttypes.h>                             
 30 #include <signal.h>                               
 31 #include <linux/err.h>                            
 32 #include <linux/time64.h>                         
 33 #include <linux/zalloc.h>                         
 34                                                   
 35 /*                                                
 36  * report header elements width                   
 37  */                                               
 38 #define PRINT_CPU_WIDTH 4                         
 39 #define PRINT_COUNT_WIDTH 9                       
 40 #define PRINT_RUNTIME_WIDTH 10                    
 41 #define PRINT_LATENCY_WIDTH 10                    
 42 #define PRINT_TIMESTAMP_WIDTH 17                  
 43 #define PRINT_KWORK_NAME_WIDTH 30                 
 44 #define RPINT_DECIMAL_WIDTH 3                     
 45 #define PRINT_BRACKETPAIR_WIDTH 2                 
 46 #define PRINT_TIME_UNIT_SEC_WIDTH 2               
 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    
 54 #define PRINT_LATENCY_HEADER_WIDTH (PRINT_LATE    
 55 #define PRINT_TIMEHIST_CPU_WIDTH (PRINT_CPU_WI    
 56 #define PRINT_TIMESTAMP_HEADER_WIDTH (PRINT_TI    
 57                                                   
 58 struct sort_dimension {                           
 59         const char      *name;                    
 60         int             (*cmp)(struct kwork_wo    
 61         struct          list_head list;           
 62 };                                                
 63                                                   
 64 static int id_cmp(struct kwork_work *l, struct    
 65 {                                                 
 66         if (l->cpu > r->cpu)                      
 67                 return 1;                         
 68         if (l->cpu < r->cpu)                      
 69                 return -1;                        
 70                                                   
 71         if (l->id > r->id)                        
 72                 return 1;                         
 73         if (l->id < r->id)                        
 74                 return -1;                        
 75                                                   
 76         return 0;                                 
 77 }                                                 
 78                                                   
 79 static int count_cmp(struct kwork_work *l, str    
 80 {                                                 
 81         if (l->nr_atoms > r->nr_atoms)            
 82                 return 1;                         
 83         if (l->nr_atoms < r->nr_atoms)            
 84                 return -1;                        
 85                                                   
 86         return 0;                                 
 87 }                                                 
 88                                                   
 89 static int runtime_cmp(struct kwork_work *l, s    
 90 {                                                 
 91         if (l->total_runtime > r->total_runtim    
 92                 return 1;                         
 93         if (l->total_runtime < r->total_runtim    
 94                 return -1;                        
 95                                                   
 96         return 0;                                 
 97 }                                                 
 98                                                   
 99 static int max_runtime_cmp(struct kwork_work *    
100 {                                                 
101         if (l->max_runtime > r->max_runtime)      
102                 return 1;                         
103         if (l->max_runtime < r->max_runtime)      
104                 return -1;                        
105                                                   
106         return 0;                                 
107 }                                                 
108                                                   
109 static int avg_latency_cmp(struct kwork_work *    
110 {                                                 
111         u64 avgl, avgr;                           
112                                                   
113         if (!r->nr_atoms)                         
114                 return 1;                         
115         if (!l->nr_atoms)                         
116                 return -1;                        
117                                                   
118         avgl = l->total_latency / l->nr_atoms;    
119         avgr = r->total_latency / r->nr_atoms;    
120                                                   
121         if (avgl > avgr)                          
122                 return 1;                         
123         if (avgl < avgr)                          
124                 return -1;                        
125                                                   
126         return 0;                                 
127 }                                                 
128                                                   
129 static int max_latency_cmp(struct kwork_work *    
130 {                                                 
131         if (l->max_latency > r->max_latency)      
132                 return 1;                         
133         if (l->max_latency < r->max_latency)      
134                 return -1;                        
135                                                   
136         return 0;                                 
137 }                                                 
138                                                   
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    
168                                const char *tok    
169 {                                                 
170         size_t i;                                 
171         static struct sort_dimension max_sort_    
172                 .name = "max",                    
173                 .cmp  = max_runtime_cmp,          
174         };                                        
175         static struct sort_dimension id_sort_d    
176                 .name = "id",                     
177                 .cmp  = id_cmp,                   
178         };                                        
179         static struct sort_dimension runtime_s    
180                 .name = "runtime",                
181                 .cmp  = runtime_cmp,              
182         };                                        
183         static struct sort_dimension count_sor    
184                 .name = "count",                  
185                 .cmp  = count_cmp,                
186         };                                        
187         static struct sort_dimension avg_sort_    
188                 .name = "avg",                    
189                 .cmp  = avg_latency_cmp,          
190         };                                        
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    
200                 &id_sort_dimension,               
201                 &max_sort_dimension,              
202                 &count_sort_dimension,            
203                 &runtime_sort_dimension,          
204                 &avg_sort_dimension,              
205                 &rate_sort_dimension,             
206                 &tid_sort_dimension,              
207         };                                        
208                                                   
209         if (kwork->report == KWORK_REPORT_LATE    
210                 max_sort_dimension.cmp = max_l    
211                                                   
212         for (i = 0; i < ARRAY_SIZE(available_s    
213                 if (!strcmp(available_sorts[i]    
214                         list_add_tail(&availab    
215                         return 0;                 
216                 }                                 
217         }                                         
218                                                   
219         return -1;                                
220 }                                                 
221                                                   
222 static void setup_sorting(struct perf_kwork *k    
223                           const struct option     
224                           const char * const u    
225 {                                                 
226         char *tmp, *tok, *str = strdup(kwork->    
227                                                   
228         for (tok = strtok_r(str, ", ", &tmp);     
229              tok; tok = strtok_r(NULL, ", ", &    
230                 if (sort_dimension__add(kwork,    
231                         usage_with_options_msg    
232                                                   
233         }                                         
234                                                   
235         pr_debug("Sort order: %s\n", kwork->so    
236         free(str);                                
237 }                                                 
238                                                   
239 static struct kwork_atom *atom_new(struct perf    
240                                    struct perf    
241 {                                                 
242         unsigned long i;                          
243         struct kwork_atom_page *page;             
244         struct kwork_atom *atom = NULL;           
245                                                   
246         list_for_each_entry(page, &kwork->atom    
247                 if (!bitmap_full(page->bitmap,    
248                         i = find_first_zero_bi    
249                         BUG_ON(i >= NR_ATOM_PE    
250                         atom = &page->atoms[i]    
251                         goto found_atom;          
252                 }                                 
253         }                                         
254                                                   
255         /*                                        
256          * new page                               
257          */                                       
258         page = zalloc(sizeof(*page));             
259         if (page == NULL) {                       
260                 pr_err("Failed to zalloc kwork    
261                 return NULL;                      
262         }                                         
263                                                   
264         i = 0;                                    
265         atom = &page->atoms[0];                   
266         list_add_tail(&page->list, &kwork->ato    
267                                                   
268 found_atom:                                       
269         __set_bit(i, page->bitmap);               
270         atom->time = sample->time;                
271         atom->prev = NULL;                        
272         atom->page_addr = page;                   
273         atom->bit_inpage = i;                     
274         return atom;                              
275 }                                                 
276                                                   
277 static void atom_free(struct kwork_atom *atom)    
278 {                                                 
279         if (atom->prev != NULL)                   
280                 atom_free(atom->prev);            
281                                                   
282         __clear_bit(atom->bit_inpage,             
283                     ((struct kwork_atom_page *    
284 }                                                 
285                                                   
286 static void atom_del(struct kwork_atom *atom)     
287 {                                                 
288         list_del(&atom->list);                    
289         atom_free(atom);                          
290 }                                                 
291                                                   
292 static int work_cmp(struct list_head *list,       
293                     struct kwork_work *l, stru    
294 {                                                 
295         int ret = 0;                              
296         struct sort_dimension *sort;              
297                                                   
298         BUG_ON(list_empty(list));                 
299                                                   
300         list_for_each_entry(sort, list, list)     
301                 ret = sort->cmp(l, r);            
302                 if (ret)                          
303                         return ret;               
304         }                                         
305                                                   
306         return ret;                               
307 }                                                 
308                                                   
309 static struct kwork_work *work_search(struct r    
310                                       struct k    
311                                       struct l    
312 {                                                 
313         int cmp;                                  
314         struct kwork_work *work;                  
315         struct rb_node *node = root->rb_root.r    
316                                                   
317         while (node) {                            
318                 work = container_of(node, stru    
319                 cmp = work_cmp(sort_list, key,    
320                 if (cmp > 0)                      
321                         node = node->rb_left;     
322                 else if (cmp < 0)                 
323                         node = node->rb_right;    
324                 else {                            
325                         if (work->name == NULL    
326                                 work->name = k    
327                         return work;              
328                 }                                 
329         }                                         
330         return NULL;                              
331 }                                                 
332                                                   
333 static void work_insert(struct rb_root_cached     
334                         struct kwork_work *key    
335 {                                                 
336         int cmp;                                  
337         bool leftmost = true;                     
338         struct kwork_work *cur;                   
339         struct rb_node **new = &(root->rb_root    
340                                                   
341         while (*new) {                            
342                 cur = container_of(*new, struc    
343                 parent = *new;                    
344                 cmp = work_cmp(sort_list, key,    
345                                                   
346                 if (cmp > 0)                      
347                         new = &((*new)->rb_lef    
348                 else {                            
349                         new = &((*new)->rb_rig    
350                         leftmost = false;         
351                 }                                 
352         }                                         
353                                                   
354         rb_link_node(&key->node, parent, new);    
355         rb_insert_color_cached(&key->node, roo    
356 }                                                 
357                                                   
358 static struct kwork_work *work_new(struct kwor    
359 {                                                 
360         int i;                                    
361         struct kwork_work *work = zalloc(sizeo    
362                                                   
363         if (work == NULL) {                       
364                 pr_err("Failed to zalloc kwork    
365                 return NULL;                      
366         }                                         
367                                                   
368         for (i = 0; i < KWORK_TRACE_MAX; i++)     
369                 INIT_LIST_HEAD(&work->atom_lis    
370                                                   
371         work->id = key->id;                       
372         work->cpu = key->cpu;                     
373         work->name = key->name;                   
374         work->class = key->class;                 
375         return work;                              
376 }                                                 
377                                                   
378 static struct kwork_work *work_findnew(struct     
379                                        struct     
380                                        struct     
381 {                                                 
382         struct kwork_work *work = work_search(    
383                                                   
384         if (work != NULL)                         
385                 return work;                      
386                                                   
387         work = work_new(key);                     
388         if (work)                                 
389                 work_insert(root, work, sort_l    
390                                                   
391         return work;                              
392 }                                                 
393                                                   
394 static void profile_update_timespan(struct per    
395                                     struct per    
396 {                                                 
397         if (!kwork->summary)                      
398                 return;                           
399                                                   
400         if ((kwork->timestart == 0) || (kwork-    
401                 kwork->timestart = sample->tim    
402                                                   
403         if (kwork->timeend < sample->time)        
404                 kwork->timeend = sample->time;    
405 }                                                 
406                                                   
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    
419                                 struct kwork_w    
420                                 struct perf_sa    
421 {                                                 
422         int cpu = work->cpu;                      
423         u64 time = sample->time;                  
424         struct perf_time_interval *ptime = &kw    
425                                                   
426         if ((kwork->cpu_list != NULL) && !test    
427                 return false;                     
428                                                   
429         if (((ptime->start != 0) && (ptime->st    
430             ((ptime->end != 0) && (ptime->end     
431                 return false;                     
432                                                   
433         /*                                        
434          * report top needs to collect the run    
435          * calculate the load of each core.       
436          */                                       
437         if ((kwork->report != KWORK_REPORT_TOP    
438             !profile_name_match(kwork, work))     
439                 return false;                     
440         }                                         
441                                                   
442         profile_update_timespan(kwork, sample)    
443         return true;                              
444 }                                                 
445                                                   
446 static int work_push_atom(struct perf_kwork *k    
447                           struct kwork_class *    
448                           enum kwork_trace_typ    
449                           enum kwork_trace_typ    
450                           struct evsel *evsel,    
451                           struct perf_sample *    
452                           struct machine *mach    
453                           struct kwork_work **    
454                           bool overwrite)         
455 {                                                 
456         struct kwork_atom *atom, *dst_atom, *l    
457         struct kwork_work *work, key;             
458                                                   
459         BUG_ON(class->work_init == NULL);         
460         class->work_init(kwork, class, &key, s    
461                                                   
462         atom = atom_new(kwork, sample);           
463         if (atom == NULL)                         
464                 return -1;                        
465                                                   
466         work = work_findnew(&class->work_root,    
467         if (work == NULL) {                       
468                 atom_free(atom);                  
469                 return -1;                        
470         }                                         
471                                                   
472         if (!profile_event_match(kwork, work,     
473                 atom_free(atom);                  
474                 return 0;                         
475         }                                         
476                                                   
477         if (dst_type < KWORK_TRACE_MAX) {         
478                 dst_atom = list_last_entry_or_    
479                                                   
480                 if (dst_atom != NULL) {           
481                         atom->prev = dst_atom;    
482                         list_del(&dst_atom->li    
483                 }                                 
484         }                                         
485                                                   
486         if (ret_work != NULL)                     
487                 *ret_work = work;                 
488                                                   
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    
501                                                   
502         return 0;                                 
503 }                                                 
504                                                   
505 static struct kwork_atom *work_pop_atom(struct    
506                                         struct    
507                                         enum k    
508                                         enum k    
509                                         struct    
510                                         struct    
511                                         struct    
512                                         struct    
513 {                                                 
514         struct kwork_atom *atom, *src_atom;       
515         struct kwork_work *work, key;             
516                                                   
517         BUG_ON(class->work_init == NULL);         
518         class->work_init(kwork, class, &key, s    
519                                                   
520         work = work_findnew(&class->work_root,    
521         if (ret_work != NULL)                     
522                 *ret_work = work;                 
523                                                   
524         if (work == NULL)                         
525                 return NULL;                      
526                                                   
527         if (!profile_event_match(kwork, work,     
528                 return NULL;                      
529                                                   
530         atom = list_last_entry_or_null(&work->    
531                                        struct     
532         if (atom != NULL)                         
533                 return atom;                      
534                                                   
535         src_atom = atom_new(kwork, sample);       
536         if (src_atom != NULL)                     
537                 list_add_tail(&src_atom->list,    
538         else {                                    
539                 if (ret_work != NULL)             
540                         *ret_work = NULL;         
541         }                                         
542                                                   
543         return NULL;                              
544 }                                                 
545                                                   
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    
579                                      struct kw    
580                                      struct pe    
581 {                                                 
582         u64 delta;                                
583         u64 exit_time = sample->time;             
584         u64 entry_time = atom->time;              
585                                                   
586         if ((entry_time != 0) && (exit_time >=    
587                 delta = exit_time - entry_time    
588                 if ((delta > work->max_runtime    
589                     (work->max_runtime == 0))     
590                         work->max_runtime = de    
591                         work->max_runtime_star    
592                         work->max_runtime_end     
593                 }                                 
594                 work->total_runtime += delta;     
595                 work->nr_atoms++;                 
596         }                                         
597 }                                                 
598                                                   
599 static int report_entry_event(struct perf_kwor    
600                               struct kwork_cla    
601                               struct evsel *ev    
602                               struct perf_samp    
603                               struct machine *    
604 {                                                 
605         return work_push_atom(kwork, class, KW    
606                               KWORK_TRACE_MAX,    
607                               machine, NULL, t    
608 }                                                 
609                                                   
610 static int report_exit_event(struct perf_kwork    
611                              struct kwork_clas    
612                              struct evsel *evs    
613                              struct perf_sampl    
614                              struct machine *m    
615 {                                                 
616         struct kwork_atom *atom = NULL;           
617         struct kwork_work *work = NULL;           
618                                                   
619         atom = work_pop_atom(kwork, class, KWO    
620                              KWORK_TRACE_ENTRY    
621                              machine, &work);     
622         if (work == NULL)                         
623                 return -1;                        
624                                                   
625         if (atom != NULL) {                       
626                 report_update_exit_event(work,    
627                 atom_del(atom);                   
628         }                                         
629                                                   
630         return 0;                                 
631 }                                                 
632                                                   
633 static void latency_update_entry_event(struct     
634                                        struct     
635                                        struct     
636 {                                                 
637         u64 delta;                                
638         u64 entry_time = sample->time;            
639         u64 raise_time = atom->time;              
640                                                   
641         if ((raise_time != 0) && (entry_time >    
642                 delta = entry_time - raise_tim    
643                 if ((delta > work->max_latency    
644                     (work->max_latency == 0))     
645                         work->max_latency = de    
646                         work->max_latency_star    
647                         work->max_latency_end     
648                 }                                 
649                 work->total_latency += delta;     
650                 work->nr_atoms++;                 
651         }                                         
652 }                                                 
653                                                   
654 static int latency_raise_event(struct perf_kwo    
655                                struct kwork_cl    
656                                struct evsel *e    
657                                struct perf_sam    
658                                struct machine     
659 {                                                 
660         return work_push_atom(kwork, class, KW    
661                               KWORK_TRACE_MAX,    
662                               machine, NULL, t    
663 }                                                 
664                                                   
665 static int latency_entry_event(struct perf_kwo    
666                                struct kwork_cl    
667                                struct evsel *e    
668                                struct perf_sam    
669                                struct machine     
670 {                                                 
671         struct kwork_atom *atom = NULL;           
672         struct kwork_work *work = NULL;           
673                                                   
674         atom = work_pop_atom(kwork, class, KWO    
675                              KWORK_TRACE_RAISE    
676                              machine, &work);     
677         if (work == NULL)                         
678                 return -1;                        
679                                                   
680         if (atom != NULL) {                       
681                 latency_update_entry_event(wor    
682                 atom_del(atom);                   
683         }                                         
684                                                   
685         return 0;                                 
686 }                                                 
687                                                   
688 static void timehist_save_callchain(struct per    
689                                     struct per    
690                                     struct evs    
691                                     struct mac    
692 {                                                 
693         struct symbol *sym;                       
694         struct thread *thread;                    
695         struct callchain_cursor_node *node;       
696         struct callchain_cursor *cursor;          
697                                                   
698         if (!kwork->show_callchain || sample->    
699                 return;                           
700                                                   
701         /* want main thread for process - has     
702         thread = machine__findnew_thread(machi    
703         if (thread == NULL) {                     
704                 pr_debug("Failed to get thread    
705                 return;                           
706         }                                         
707                                                   
708         cursor = get_tls_callchain_cursor();      
709                                                   
710         if (thread__resolve_callchain(thread,     
711                                       NULL, NU    
712                 pr_debug("Failed to resolve ca    
713                 goto out_put;                     
714         }                                         
715                                                   
716         callchain_cursor_commit(cursor);          
717                                                   
718         while (true) {                            
719                 node = callchain_cursor_curren    
720                 if (node == NULL)                 
721                         break;                    
722                                                   
723                 sym = node->ms.sym;               
724                 if (sym) {                        
725                         if (!strcmp(sym->name,    
726                             !strcmp(sym->name,    
727                                 sym->ignore =     
728                 }                                 
729                                                   
730                 callchain_cursor_advance(curso    
731         }                                         
732                                                   
733 out_put:                                          
734         thread__put(thread);                      
735 }                                                 
736                                                   
737 static void timehist_print_event(struct perf_k    
738                                  struct kwork_    
739                                  struct kwork_    
740                                  struct perf_s    
741                                  struct addr_l    
742 {                                                 
743         char entrytime[32], exittime[32];         
744         char kwork_name[PRINT_KWORK_NAME_WIDTH    
745                                                   
746         /*                                        
747          * runtime start                          
748          */                                       
749         timestamp__scnprintf_usec(atom->time,     
750                                   entrytime, s    
751         printf(" %*s ", PRINT_TIMESTAMP_WIDTH,    
752                                                   
753         /*                                        
754          * runtime end                            
755          */                                       
756         timestamp__scnprintf_usec(sample->time    
757                                   exittime, si    
758         printf(" %*s ", PRINT_TIMESTAMP_WIDTH,    
759                                                   
760         /*                                        
761          * cpu                                    
762          */                                       
763         printf(" [%0*d] ", PRINT_CPU_WIDTH, wo    
764                                                   
765         /*                                        
766          * kwork name                             
767          */                                       
768         if (work->class && work->class->work_n    
769                 work->class->work_name(work, k    
770                                        PRINT_K    
771                 printf(" %-*s ", PRINT_KWORK_N    
772         } else                                    
773                 printf(" %-*s ", PRINT_KWORK_N    
774                                                   
775         /*                                        
776          *runtime                                 
777          */                                       
778         printf(" %*.*f ",                         
779                PRINT_RUNTIME_WIDTH, RPINT_DECI    
780                (double)(sample->time - atom->t    
781                                                   
782         /*                                        
783          * delaytime                              
784          */                                       
785         if (atom->prev != NULL)                   
786                 printf(" %*.*f ", PRINT_LATENC    
787                        (double)(atom->time - a    
788         else                                      
789                 printf(" %*s ", PRINT_LATENCY_    
790                                                   
791         /*                                        
792          * callchain                              
793          */                                       
794         if (kwork->show_callchain) {              
795                 struct callchain_cursor *curso    
796                                                   
797                 if (cursor == NULL)               
798                         return;                   
799                                                   
800                 printf(" ");                      
801                                                   
802                 sample__fprintf_sym(sample, al    
803                                     EVSEL__PRI    
804                                     EVSEL__PRI    
805                                     EVSEL__PRI    
806                                     cursor, sy    
807                                     stdout);      
808         }                                         
809                                                   
810         printf("\n");                             
811 }                                                 
812                                                   
813 static int timehist_raise_event(struct perf_kw    
814                                 struct kwork_c    
815                                 struct evsel *    
816                                 struct perf_sa    
817                                 struct machine    
818 {                                                 
819         return work_push_atom(kwork, class, KW    
820                               KWORK_TRACE_MAX,    
821                               machine, NULL, t    
822 }                                                 
823                                                   
824 static int timehist_entry_event(struct perf_kw    
825                                 struct kwork_c    
826                                 struct evsel *    
827                                 struct perf_sa    
828                                 struct machine    
829 {                                                 
830         int ret;                                  
831         struct kwork_work *work = NULL;           
832                                                   
833         ret = work_push_atom(kwork, class, KWO    
834                              KWORK_TRACE_RAISE    
835                              machine, &work, t    
836         if (ret)                                  
837                 return ret;                       
838                                                   
839         if (work != NULL)                         
840                 timehist_save_callchain(kwork,    
841                                                   
842         return 0;                                 
843 }                                                 
844                                                   
845 static int timehist_exit_event(struct perf_kwo    
846                                struct kwork_cl    
847                                struct evsel *e    
848                                struct perf_sam    
849                                struct machine     
850 {                                                 
851         struct kwork_atom *atom = NULL;           
852         struct kwork_work *work = NULL;           
853         struct addr_location al;                  
854         int ret = 0;                              
855                                                   
856         addr_location__init(&al);                 
857         if (machine__resolve(machine, &al, sam    
858                 pr_debug("Problem processing e    
859                 ret = -1;                         
860                 goto out;                         
861         }                                         
862                                                   
863         atom = work_pop_atom(kwork, class, KWO    
864                              KWORK_TRACE_ENTRY    
865                              machine, &work);     
866         if (work == NULL) {                       
867                 ret = -1;                         
868                 goto out;                         
869         }                                         
870                                                   
871         if (atom != NULL) {                       
872                 work->nr_atoms++;                 
873                 timehist_print_event(kwork, wo    
874                 atom_del(atom);                   
875         }                                         
876                                                   
877 out:                                              
878         addr_location__exit(&al);                 
879         return ret;                               
880 }                                                 
881                                                   
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;              
961 static int process_irq_handler_entry_event(str    
962                                            str    
963                                            str    
964                                            str    
965 {                                                 
966         struct perf_kwork *kwork = container_o    
967                                                   
968         if (kwork->tp_handler->entry_event)       
969                 return kwork->tp_handler->entr    
970                                                   
971         return 0;                                 
972 }                                                 
973                                                   
974 static int process_irq_handler_exit_event(stru    
975                                           stru    
976                                           stru    
977                                           stru    
978 {                                                 
979         struct perf_kwork *kwork = container_o    
980                                                   
981         if (kwork->tp_handler->exit_event)        
982                 return kwork->tp_handler->exit    
983                                                   
984         return 0;                                 
985 }                                                 
986                                                   
987 const struct evsel_str_handler irq_tp_handlers    
988         { "irq:irq_handler_entry", process_irq    
989         { "irq:irq_handler_exit",  process_irq    
990 };                                                
991                                                   
992 static int irq_class_init(struct kwork_class *    
993                           struct perf_session     
994 {                                                 
995         if (perf_session__set_tracepoints_hand    
996                 pr_err("Failed to set irq trac    
997                 return -1;                        
998         }                                         
999                                                   
1000         class->work_root = RB_ROOT_CACHED;       
1001         return 0;                                
1002 }                                                
1003                                                  
1004 static void irq_work_init(struct perf_kwork *    
1005                           struct kwork_class     
1006                           struct kwork_work *    
1007                           enum kwork_trace_ty    
1008                           struct evsel *evsel    
1009                           struct perf_sample     
1010                           struct machine *mac    
1011 {                                                
1012         work->class = class;                     
1013         work->cpu = sample->cpu;                 
1014                                                  
1015         if (kwork->report == KWORK_REPORT_TOP    
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 }                                                
1023                                                  
1024 static void irq_work_name(struct kwork_work *    
1025 {                                                
1026         snprintf(buf, len, "%s:%" PRIu64 "",     
1027 }                                                
1028                                                  
1029 static struct kwork_class kwork_irq = {          
1030         .name           = "irq",                 
1031         .type           = KWORK_CLASS_IRQ,       
1032         .nr_tracepoints = 2,                     
1033         .tp_handlers    = irq_tp_handlers,       
1034         .class_init     = irq_class_init,        
1035         .work_init      = irq_work_init,         
1036         .work_name      = irq_work_name,         
1037 };                                               
1038                                                  
1039 static struct kwork_class kwork_softirq;         
1040 static int process_softirq_raise_event(struct    
1041                                        struct    
1042                                        struct    
1043                                        struct    
1044 {                                                
1045         struct perf_kwork *kwork = container_    
1046                                                  
1047         if (kwork->tp_handler->raise_event)      
1048                 return kwork->tp_handler->rai    
1049                                                  
1050                                                  
1051         return 0;                                
1052 }                                                
1053                                                  
1054 static int process_softirq_entry_event(struct    
1055                                        struct    
1056                                        struct    
1057                                        struct    
1058 {                                                
1059         struct perf_kwork *kwork = container_    
1060                                                  
1061         if (kwork->tp_handler->entry_event)      
1062                 return kwork->tp_handler->ent    
1063                                                  
1064                                                  
1065         return 0;                                
1066 }                                                
1067                                                  
1068 static int process_softirq_exit_event(struct     
1069                                       struct     
1070                                       struct     
1071                                       struct     
1072 {                                                
1073         struct perf_kwork *kwork = container_    
1074                                                  
1075         if (kwork->tp_handler->exit_event)       
1076                 return kwork->tp_handler->exi    
1077                                                  
1078                                                  
1079         return 0;                                
1080 }                                                
1081                                                  
1082 const struct evsel_str_handler softirq_tp_han    
1083         { "irq:softirq_raise", process_softir    
1084         { "irq:softirq_entry", process_softir    
1085         { "irq:softirq_exit",  process_softir    
1086 };                                               
1087                                                  
1088 static int softirq_class_init(struct kwork_cl    
1089                               struct perf_ses    
1090 {                                                
1091         if (perf_session__set_tracepoints_han    
1092                                                  
1093                 pr_err("Failed to set softirq    
1094                 return -1;                       
1095         }                                        
1096                                                  
1097         class->work_root = RB_ROOT_CACHED;       
1098         return 0;                                
1099 }                                                
1100                                                  
1101 static char *evsel__softirq_name(struct evsel    
1102 {                                                
1103         char *name = NULL;                       
1104         bool found = false;                      
1105         struct tep_print_flag_sym *sym = NULL    
1106         struct tep_print_arg *args = evsel->t    
1107                                                  
1108         if ((args == NULL) || (args->next ==     
1109                 return NULL;                     
1110                                                  
1111         /* skip softirq field: "REC->vec" */     
1112         for (sym = args->next->symbol.symbols    
1113                 if ((eval_flag(sym->value) ==    
1114                     (strlen(sym->str) != 0))     
1115                         found = true;            
1116                         break;                   
1117                 }                                
1118         }                                        
1119                                                  
1120         if (!found)                              
1121                 return NULL;                     
1122                                                  
1123         name = strdup(sym->str);                 
1124         if (name == NULL) {                      
1125                 pr_err("Failed to copy symbol    
1126                 return NULL;                     
1127         }                                        
1128         return name;                             
1129 }                                                
1130                                                  
1131 static void softirq_work_init(struct perf_kwo    
1132                               struct kwork_cl    
1133                               struct kwork_wo    
1134                               enum kwork_trac    
1135                               struct evsel *e    
1136                               struct perf_sam    
1137                               struct machine     
1138 {                                                
1139         u64 num;                                 
1140                                                  
1141         work->class = class;                     
1142         work->cpu = sample->cpu;                 
1143                                                  
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 }                                                
1153                                                  
1154 static void softirq_work_name(struct kwork_wo    
1155 {                                                
1156         snprintf(buf, len, "(s)%s:%" PRIu64 "    
1157 }                                                
1158                                                  
1159 static struct kwork_class kwork_softirq = {      
1160         .name           = "softirq",             
1161         .type           = KWORK_CLASS_SOFTIRQ    
1162         .nr_tracepoints = 3,                     
1163         .tp_handlers    = softirq_tp_handlers    
1164         .class_init     = softirq_class_init,    
1165         .work_init      = softirq_work_init,     
1166         .work_name      = softirq_work_name,     
1167 };                                               
1168                                                  
1169 static struct kwork_class kwork_workqueue;       
1170 static int process_workqueue_activate_work_ev    
1171                                                  
1172                                                  
1173                                                  
1174 {                                                
1175         struct perf_kwork *kwork = container_    
1176                                                  
1177         if (kwork->tp_handler->raise_event)      
1178                 return kwork->tp_handler->rai    
1179                                                  
1180                                                  
1181         return 0;                                
1182 }                                                
1183                                                  
1184 static int process_workqueue_execute_start_ev    
1185                                                  
1186                                                  
1187                                                  
1188 {                                                
1189         struct perf_kwork *kwork = container_    
1190                                                  
1191         if (kwork->tp_handler->entry_event)      
1192                 return kwork->tp_handler->ent    
1193                                                  
1194                                                  
1195         return 0;                                
1196 }                                                
1197                                                  
1198 static int process_workqueue_execute_end_even    
1199                                                  
1200                                                  
1201                                                  
1202 {                                                
1203         struct perf_kwork *kwork = container_    
1204                                                  
1205         if (kwork->tp_handler->exit_event)       
1206                 return kwork->tp_handler->exi    
1207                                                  
1208                                                  
1209         return 0;                                
1210 }                                                
1211                                                  
1212 const struct evsel_str_handler workqueue_tp_h    
1213         { "workqueue:workqueue_activate_work"    
1214         { "workqueue:workqueue_execute_start"    
1215         { "workqueue:workqueue_execute_end",     
1216 };                                               
1217                                                  
1218 static int workqueue_class_init(struct kwork_    
1219                                 struct perf_s    
1220 {                                                
1221         if (perf_session__set_tracepoints_han    
1222                                                  
1223                 pr_err("Failed to set workque    
1224                 return -1;                       
1225         }                                        
1226                                                  
1227         class->work_root = RB_ROOT_CACHED;       
1228         return 0;                                
1229 }                                                
1230                                                  
1231 static void workqueue_work_init(struct perf_k    
1232                                 struct kwork_    
1233                                 struct kwork_    
1234                                 enum kwork_tr    
1235                                 struct evsel     
1236                                 struct perf_s    
1237                                 struct machin    
1238 {                                                
1239         char *modp = NULL;                       
1240         unsigned long long function_addr = ev    
1241                                                  
1242                                                  
1243         work->class = class;                     
1244         work->cpu = sample->cpu;                 
1245         work->id = evsel__intval(evsel, sampl    
1246         work->name = function_addr == 0 ? NUL    
1247                 machine__resolve_kernel_addr(    
1248 }                                                
1249                                                  
1250 static void workqueue_work_name(struct kwork_    
1251 {                                                
1252         if (work->name != NULL)                  
1253                 snprintf(buf, len, "(w)%s", w    
1254         else                                     
1255                 snprintf(buf, len, "(w)0x%" P    
1256 }                                                
1257                                                  
1258 static struct kwork_class kwork_workqueue = {    
1259         .name           = "workqueue",           
1260         .type           = KWORK_CLASS_WORKQUE    
1261         .nr_tracepoints = 3,                     
1262         .tp_handlers    = workqueue_tp_handle    
1263         .class_init     = workqueue_class_ini    
1264         .work_init      = workqueue_work_init    
1265         .work_name      = workqueue_work_name    
1266 };                                               
1267                                                  
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    
1335         [KWORK_CLASS_IRQ]       = &kwork_irq,    
1336         [KWORK_CLASS_SOFTIRQ]   = &kwork_soft    
1337         [KWORK_CLASS_WORKQUEUE] = &kwork_work    
1338         [KWORK_CLASS_SCHED]     = &kwork_sche    
1339 };                                               
1340                                                  
1341 static void print_separator(int len)             
1342 {                                                
1343         printf(" %.*s\n", len, graph_dotted_l    
1344 }                                                
1345                                                  
1346 static int report_print_work(struct perf_kwor    
1347 {                                                
1348         int ret = 0;                             
1349         char kwork_name[PRINT_KWORK_NAME_WIDT    
1350         char max_runtime_start[32], max_runti    
1351         char max_latency_start[32], max_laten    
1352                                                  
1353         printf(" ");                             
1354                                                  
1355         /*                                       
1356          * kwork name                            
1357          */                                      
1358         if (work->class && work->class->work_    
1359                 work->class->work_name(work,     
1360                                        PRINT_    
1361                 ret += printf(" %-*s |", PRIN    
1362         } else {                                 
1363                 ret += printf(" %-*s |", PRIN    
1364         }                                        
1365                                                  
1366         /*                                       
1367          * cpu                                   
1368          */                                      
1369         ret += printf(" %0*d |", PRINT_CPU_WI    
1370                                                  
1371         /*                                       
1372          * total runtime                         
1373          */                                      
1374         if (kwork->report == KWORK_REPORT_RUN    
1375                 ret += printf(" %*.*f ms |",     
1376                               PRINT_RUNTIME_W    
1377                               (double)work->t    
1378         } else if (kwork->report == KWORK_REP    
1379                 ret += printf(" %*.*f ms |",     
1380                               PRINT_LATENCY_W    
1381                               (double)work->t    
1382                               work->nr_atoms     
1383         }                                        
1384                                                  
1385         /*                                       
1386          * count                                 
1387          */                                      
1388         ret += printf(" %*" PRIu64 " |", PRIN    
1389                                                  
1390         /*                                       
1391          * max runtime, max runtime start, ma    
1392          */                                      
1393         if (kwork->report == KWORK_REPORT_RUN    
1394                 timestamp__scnprintf_usec(wor    
1395                                           max    
1396                                           siz    
1397                 timestamp__scnprintf_usec(wor    
1398                                           max    
1399                                           siz    
1400                 ret += printf(" %*.*f ms | %*    
1401                               PRINT_RUNTIME_W    
1402                               (double)work->m    
1403                               PRINT_TIMESTAMP    
1404                               PRINT_TIMESTAMP    
1405         }                                        
1406         /*                                       
1407          * max delay, max delay start, max de    
1408          */                                      
1409         else if (kwork->report == KWORK_REPOR    
1410                 timestamp__scnprintf_usec(wor    
1411                                           max    
1412                                           siz    
1413                 timestamp__scnprintf_usec(wor    
1414                                           max    
1415                                           siz    
1416                 ret += printf(" %*.*f ms | %*    
1417                               PRINT_LATENCY_W    
1418                               (double)work->m    
1419                               PRINT_TIMESTAMP    
1420                               PRINT_TIMESTAMP    
1421         }                                        
1422                                                  
1423         printf("\n");                            
1424         return ret;                              
1425 }                                                
1426                                                  
1427 static int report_print_header(struct perf_kw    
1428 {                                                
1429         int ret;                                 
1430                                                  
1431         printf("\n ");                           
1432         ret = printf(" %-*s | %-*s |",           
1433                      PRINT_KWORK_NAME_WIDTH,     
1434                      PRINT_CPU_WIDTH, "Cpu");    
1435                                                  
1436         if (kwork->report == KWORK_REPORT_RUN    
1437                 ret += printf(" %-*s |",         
1438                               PRINT_RUNTIME_H    
1439         } else if (kwork->report == KWORK_REP    
1440                 ret += printf(" %-*s |",         
1441                               PRINT_LATENCY_H    
1442         }                                        
1443                                                  
1444         ret += printf(" %-*s |", PRINT_COUNT_    
1445                                                  
1446         if (kwork->report == KWORK_REPORT_RUN    
1447                 ret += printf(" %-*s | %-*s |    
1448                               PRINT_RUNTIME_H    
1449                               PRINT_TIMESTAMP    
1450                               PRINT_TIMESTAMP    
1451         } else if (kwork->report == KWORK_REP    
1452                 ret += printf(" %-*s | %-*s |    
1453                               PRINT_LATENCY_H    
1454                               PRINT_TIMESTAMP    
1455                               PRINT_TIMESTAMP    
1456         }                                        
1457                                                  
1458         printf("\n");                            
1459         print_separator(ret);                    
1460         return ret;                              
1461 }                                                
1462                                                  
1463 static void timehist_print_header(void)          
1464 {                                                
1465         /*                                       
1466          * header row                            
1467          */                                      
1468         printf(" %-*s  %-*s  %-*s  %-*s  %-*s    
1469                PRINT_TIMESTAMP_WIDTH, "Runtim    
1470                PRINT_TIMESTAMP_WIDTH, "Runtim    
1471                PRINT_TIMEHIST_CPU_WIDTH, "Cpu    
1472                PRINT_KWORK_NAME_WIDTH, "Kwork    
1473                PRINT_RUNTIME_WIDTH, "Runtime"    
1474                PRINT_RUNTIME_WIDTH, "Delaytim    
1475                                                  
1476         /*                                       
1477          * units row                             
1478          */                                      
1479         printf(" %-*s  %-*s  %-*s  %-*s  %-*s    
1480                PRINT_TIMESTAMP_WIDTH, "",        
1481                PRINT_TIMESTAMP_WIDTH, "",        
1482                PRINT_TIMEHIST_CPU_WIDTH, "",     
1483                PRINT_KWORK_NAME_WIDTH, "(TYPE    
1484                PRINT_RUNTIME_WIDTH, "(msec)",    
1485                PRINT_RUNTIME_WIDTH, "(msec)")    
1486                                                  
1487         /*                                       
1488          * separator                             
1489          */                                      
1490         printf(" %.*s  %.*s  %.*s  %.*s  %.*s    
1491                PRINT_TIMESTAMP_WIDTH, graph_d    
1492                PRINT_TIMESTAMP_WIDTH, graph_d    
1493                PRINT_TIMEHIST_CPU_WIDTH, grap    
1494                PRINT_KWORK_NAME_WIDTH, graph_    
1495                PRINT_RUNTIME_WIDTH, graph_dot    
1496                PRINT_RUNTIME_WIDTH, graph_dot    
1497 }                                                
1498                                                  
1499 static void print_summary(struct perf_kwork *    
1500 {                                                
1501         u64 time = kwork->timeend - kwork->ti    
1502                                                  
1503         printf("  Total count            : %9    
1504         printf("  Total runtime   (msec) : %9    
1505                (double)kwork->all_runtime / N    
1506                time == 0 ? 0 : (double)kwork-    
1507         printf("  Total time span (msec) : %9    
1508                (double)time / NSEC_PER_MSEC);    
1509 }                                                
1510                                                  
1511 static unsigned long long nr_list_entry(struc    
1512 {                                                
1513         struct list_head *pos;                   
1514         unsigned long long n = 0;                
1515                                                  
1516         list_for_each(pos, head)                 
1517                 n++;                             
1518                                                  
1519         return n;                                
1520 }                                                
1521                                                  
1522 static void print_skipped_events(struct perf_    
1523 {                                                
1524         int i;                                   
1525         const char *const kwork_event_str[] =    
1526                 [KWORK_TRACE_RAISE] = "raise"    
1527                 [KWORK_TRACE_ENTRY] = "entry"    
1528                 [KWORK_TRACE_EXIT]  = "exit",    
1529         };                                       
1530                                                  
1531         if ((kwork->nr_skipped_events[KWORK_T    
1532             (kwork->nr_events != 0)) {           
1533                 printf("  INFO: %.3f%% skippe    
1534                        (double)kwork->nr_skip    
1535                        (double)kwork->nr_even    
1536                        kwork->nr_skipped_even    
1537                                                  
1538                 for (i = 0; i < KWORK_TRACE_M    
1539                         printf("%" PRIu64 " %    
1540                                kwork->nr_skip    
1541                                kwork_event_st    
1542                                (i == KWORK_TR    
1543                 }                                
1544         }                                        
1545                                                  
1546         if (verbose > 0)                         
1547                 printf("  INFO: use %lld atom    
1548                        nr_list_entry(&kwork->    
1549 }                                                
1550                                                  
1551 static void print_bad_events(struct perf_kwor    
1552 {                                                
1553         if ((kwork->nr_lost_events != 0) && (    
1554                 printf("  INFO: %.3f%% lost e    
1555                        (double)kwork->nr_lost    
1556                        (double)kwork->nr_even    
1557                        kwork->nr_lost_events,    
1558                        kwork->nr_lost_chunks)    
1559         }                                        
1560 }                                                
1561                                                  
1562 const char *graph_load = "|||||||||||||||||||    
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 {                                                
1686         struct rb_node *node;                    
1687         struct kwork_work *data;                 
1688                                                  
1689         pr_debug("Sorting %s ...\n", class->n    
1690         for (;;) {                               
1691                 node = rb_first_cached(root);    
1692                 if (!node)                       
1693                         break;                   
1694                                                  
1695                 rb_erase_cached(node, root);     
1696                 data = rb_entry(node, struct     
1697                 work_insert(&kwork->sorted_wo    
1698                                data, &kwork->    
1699         }                                        
1700 }                                                
1701                                                  
1702 static void perf_kwork__sort(struct perf_kwor    
1703 {                                                
1704         struct kwork_class *class;               
1705                                                  
1706         list_for_each_entry(class, &kwork->cl    
1707                 work_sort(kwork, class, &clas    
1708 }                                                
1709                                                  
1710 static int perf_kwork__check_config(struct pe    
1711                                     struct pe    
1712 {                                                
1713         int ret;                                 
1714         struct evsel *evsel;                     
1715         struct kwork_class *class;               
1716                                                  
1717         static struct trace_kwork_handler rep    
1718                 .entry_event = report_entry_e    
1719                 .exit_event  = report_exit_ev    
1720         };                                       
1721         static struct trace_kwork_handler lat    
1722                 .raise_event = latency_raise_    
1723                 .entry_event = latency_entry_    
1724         };                                       
1725         static struct trace_kwork_handler tim    
1726                 .raise_event = timehist_raise    
1727                 .entry_event = timehist_entry    
1728                 .exit_event  = timehist_exit_    
1729         };                                       
1730         static struct trace_kwork_handler top    
1731                 .entry_event        = timehis    
1732                 .exit_event         = top_exi    
1733                 .sched_switch_event = top_sch    
1734         };                                       
1735                                                  
1736         switch (kwork->report) {                 
1737         case KWORK_REPORT_RUNTIME:               
1738                 kwork->tp_handler = &report_o    
1739                 break;                           
1740         case KWORK_REPORT_LATENCY:               
1741                 kwork->tp_handler = &latency_    
1742                 break;                           
1743         case KWORK_REPORT_TIMEHIST:              
1744                 kwork->tp_handler = &timehist    
1745                 break;                           
1746         case KWORK_REPORT_TOP:                   
1747                 kwork->tp_handler = &top_ops;    
1748                 break;                           
1749         default:                                 
1750                 pr_debug("Invalid report type    
1751                 return -1;                       
1752         }                                        
1753                                                  
1754         list_for_each_entry(class, &kwork->cl    
1755                 if ((class->class_init != NUL    
1756                     (class->class_init(class,    
1757                         return -1;               
1758                                                  
1759         if (kwork->cpu_list != NULL) {           
1760                 ret = perf_session__cpu_bitma    
1761                                                  
1762                                                  
1763                 if (ret < 0) {                   
1764                         pr_err("Invalid cpu b    
1765                         return -1;               
1766                 }                                
1767         }                                        
1768                                                  
1769         if (kwork->time_str != NULL) {           
1770                 ret = perf_time__parse_str(&k    
1771                 if (ret != 0) {                  
1772                         pr_err("Invalid time     
1773                         return -1;               
1774                 }                                
1775         }                                        
1776                                                  
1777         list_for_each_entry(evsel, &session->    
1778                 if (kwork->show_callchain &&     
1779                         pr_debug("Samples do     
1780                         kwork->show_callchain    
1781                         symbol_conf.use_callc    
1782                 }                                
1783         }                                        
1784                                                  
1785         return 0;                                
1786 }                                                
1787                                                  
1788 static int perf_kwork__read_events(struct per    
1789 {                                                
1790         int ret = -1;                            
1791         struct perf_session *session = NULL;     
1792                                                  
1793         struct perf_data data = {                
1794                 .path  = input_name,             
1795                 .mode  = PERF_DATA_MODE_READ,    
1796                 .force = kwork->force,           
1797         };                                       
1798                                                  
1799         session = perf_session__new(&data, &k    
1800         if (IS_ERR(session)) {                   
1801                 pr_debug("Error creating perf    
1802                 return PTR_ERR(session);         
1803         }                                        
1804                                                  
1805         symbol__init(&session->header.env);      
1806                                                  
1807         if (perf_kwork__check_config(kwork, s    
1808                 goto out_delete;                 
1809                                                  
1810         if (session->tevent.pevent &&            
1811             tep_set_function_resolver(session    
1812                                       machine    
1813                                       &sessio    
1814                 pr_err("Failed to set libtrac    
1815                 goto out_delete;                 
1816         }                                        
1817                                                  
1818         if (kwork->report == KWORK_REPORT_TIM    
1819                 timehist_print_header();         
1820                                                  
1821         ret = perf_session__process_events(se    
1822         if (ret) {                               
1823                 pr_debug("Failed to process e    
1824                 goto out_delete;                 
1825         }                                        
1826                                                  
1827         kwork->nr_events      = session->evli    
1828         kwork->nr_lost_events = session->evli    
1829         kwork->nr_lost_chunks = session->evli    
1830                                                  
1831 out_delete:                                      
1832         perf_session__delete(session);           
1833         return ret;                              
1834 }                                                
1835                                                  
1836 static void process_skipped_events(struct per    
1837                                    struct kwo    
1838 {                                                
1839         int i;                                   
1840         unsigned long long count;                
1841                                                  
1842         for (i = 0; i < KWORK_TRACE_MAX; i++)    
1843                 count = nr_list_entry(&work->    
1844                 kwork->nr_skipped_events[i] +    
1845                 kwork->nr_skipped_events[KWOR    
1846         }                                        
1847 }                                                
1848                                                  
1849 struct kwork_work *perf_kwork_add_work(struct    
1850                                        struct    
1851                                        struct    
1852 {                                                
1853         struct kwork_work *work = NULL;          
1854                                                  
1855         work = work_new(key);                    
1856         if (work == NULL)                        
1857                 return NULL;                     
1858                                                  
1859         work_insert(&class->work_root, work,     
1860         return work;                             
1861 }                                                
1862                                                  
1863 static void sig_handler(int sig)                 
1864 {                                                
1865         /*                                       
1866          * Simply capture termination signal     
1867          * the program can continue after pau    
1868          */                                      
1869         pr_debug("Capture signal %d\n", sig);    
1870 }                                                
1871                                                  
1872 static int perf_kwork__report_bpf(struct perf    
1873 {                                                
1874         int ret;                                 
1875                                                  
1876         signal(SIGINT, sig_handler);             
1877         signal(SIGTERM, sig_handler);            
1878                                                  
1879         ret = perf_kwork__trace_prepare_bpf(k    
1880         if (ret)                                 
1881                 return -1;                       
1882                                                  
1883         printf("Starting trace, Hit <Ctrl+C>     
1884                                                  
1885         perf_kwork__trace_start();               
1886                                                  
1887         /*                                       
1888          * a simple pause, wait here for stop    
1889          */                                      
1890         pause();                                 
1891                                                  
1892         perf_kwork__trace_finish();              
1893                                                  
1894         perf_kwork__report_read_bpf(kwork);      
1895                                                  
1896         perf_kwork__report_cleanup_bpf();        
1897                                                  
1898         return 0;                                
1899 }                                                
1900                                                  
1901 static int perf_kwork__report(struct perf_kwo    
1902 {                                                
1903         int ret;                                 
1904         struct rb_node *next;                    
1905         struct kwork_work *work;                 
1906                                                  
1907         if (kwork->use_bpf)                      
1908                 ret = perf_kwork__report_bpf(    
1909         else                                     
1910                 ret = perf_kwork__read_events    
1911                                                  
1912         if (ret != 0)                            
1913                 return -1;                       
1914                                                  
1915         perf_kwork__sort(kwork);                 
1916                                                  
1917         setup_pager();                           
1918                                                  
1919         ret = report_print_header(kwork);        
1920         next = rb_first_cached(&kwork->sorted    
1921         while (next) {                           
1922                 work = rb_entry(next, struct     
1923                 process_skipped_events(kwork,    
1924                                                  
1925                 if (work->nr_atoms != 0) {       
1926                         report_print_work(kwo    
1927                         if (kwork->summary) {    
1928                                 kwork->all_ru    
1929                                 kwork->all_co    
1930                         }                        
1931                 }                                
1932                 next = rb_next(next);            
1933         }                                        
1934         print_separator(ret);                    
1935                                                  
1936         if (kwork->summary) {                    
1937                 print_summary(kwork);            
1938                 print_separator(ret);            
1939         }                                        
1940                                                  
1941         print_bad_events(kwork);                 
1942         print_skipped_events(kwork);             
1943         printf("\n");                            
1944                                                  
1945         return 0;                                
1946 }                                                
1947                                                  
1948 typedef int (*tracepoint_handler)(struct perf    
1949                                   struct evse    
1950                                   struct perf    
1951                                   struct mach    
1952                                                  
1953 static int perf_kwork__process_tracepoint_sam    
1954                                                  
1955                                                  
1956                                                  
1957                                                  
1958 {                                                
1959         int err = 0;                             
1960                                                  
1961         if (evsel->handler != NULL) {            
1962                 tracepoint_handler f = evsel-    
1963                                                  
1964                 err = f(tool, evsel, sample,     
1965         }                                        
1966                                                  
1967         return err;                              
1968 }                                                
1969                                                  
1970 static int perf_kwork__timehist(struct perf_k    
1971 {                                                
1972         /*                                       
1973          * event handlers for timehist option    
1974          */                                      
1975         kwork->tool.comm         = perf_event    
1976         kwork->tool.exit         = perf_event    
1977         kwork->tool.fork         = perf_event    
1978         kwork->tool.attr         = perf_event    
1979         kwork->tool.tracing_data = perf_event    
1980         kwork->tool.build_id     = perf_event    
1981         kwork->tool.ordered_events = true;       
1982         kwork->tool.ordering_requires_timesta    
1983         symbol_conf.use_callchain = kwork->sh    
1984                                                  
1985         if (symbol__validate_sym_arguments())    
1986                 pr_err("Failed to validate sy    
1987                 return -1;                       
1988         }                                        
1989                                                  
1990         setup_pager();                           
1991                                                  
1992         return perf_kwork__read_events(kwork)    
1993 }                                                
1994                                                  
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    
2238                              const struct opt    
2239                              const char * con    
2240 {                                                
2241         int i;                                   
2242         struct kwork_class *class;               
2243         char *tmp, *tok, *str;                   
2244                                                  
2245         /*                                       
2246          * set default events list if not spe    
2247          */                                      
2248         if (kwork->event_list_str == NULL)       
2249                 kwork->event_list_str = "irq,    
2250                                                  
2251         str = strdup(kwork->event_list_str);     
2252         for (tok = strtok_r(str, ", ", &tmp);    
2253              tok; tok = strtok_r(NULL, ", ",     
2254                 for (i = 0; i < KWORK_CLASS_M    
2255                         class = kwork_class_s    
2256                         if (strcmp(tok, class    
2257                                 list_add_tail    
2258                                 break;           
2259                         }                        
2260                 }                                
2261                 if (i == KWORK_CLASS_MAX) {      
2262                         usage_with_options_ms    
2263                                                  
2264                 }                                
2265         }                                        
2266         free(str);                               
2267                                                  
2268         pr_debug("Config event list:");          
2269         list_for_each_entry(class, &kwork->cl    
2270                 pr_debug(" %s", class->name);    
2271         pr_debug("\n");                          
2272 }                                                
2273                                                  
2274 static int perf_kwork__record(struct perf_kwo    
2275                               int argc, const    
2276 {                                                
2277         const char **rec_argv;                   
2278         unsigned int rec_argc, i, j;             
2279         struct kwork_class *class;               
2280                                                  
2281         const char *const record_args[] = {      
2282                 "record",                        
2283                 "-a",                            
2284                 "-R",                            
2285                 "-m", "1024",                    
2286                 "-c", "1",                       
2287         };                                       
2288                                                  
2289         rec_argc = ARRAY_SIZE(record_args) +     
2290                                                  
2291         list_for_each_entry(class, &kwork->cl    
2292                 rec_argc += 2 * class->nr_tra    
2293                                                  
2294         rec_argv = calloc(rec_argc + 1, sizeo    
2295         if (rec_argv == NULL)                    
2296                 return -ENOMEM;                  
2297                                                  
2298         for (i = 0; i < ARRAY_SIZE(record_arg    
2299                 rec_argv[i] = strdup(record_a    
2300                                                  
2301         list_for_each_entry(class, &kwork->cl    
2302                 for (j = 0; j < class->nr_tra    
2303                         rec_argv[i++] = strdu    
2304                         rec_argv[i++] = strdu    
2305                 }                                
2306         }                                        
2307                                                  
2308         for (j = 1; j < (unsigned int)argc; j    
2309                 rec_argv[i] = argv[j];           
2310                                                  
2311         BUG_ON(i != rec_argc);                   
2312                                                  
2313         pr_debug("record comm: ");               
2314         for (j = 0; j < rec_argc; j++)           
2315                 pr_debug("%s ", rec_argv[j]);    
2316         pr_debug("\n");                          
2317                                                  
2318         return cmd_record(i, rec_argv);          
2319 }                                                
2320                                                  
2321 int cmd_kwork(int argc, const char **argv)       
2322 {                                                
2323         static struct perf_kwork kwork = {       
2324                 .class_list          = LIST_H    
2325                 .tool = {                        
2326                         .mmap           = per    
2327                         .mmap2          = per    
2328                         .sample         = per    
2329                         .ordered_events = tru    
2330                 },                               
2331                 .atom_page_list      = LIST_H    
2332                 .sort_list           = LIST_H    
2333                 .cmp_id              = LIST_H    
2334                 .sorted_work_root    = RB_ROO    
2335                 .tp_handler          = NULL,     
2336                 .profile_name        = NULL,     
2337                 .cpu_list            = NULL,     
2338                 .time_str            = NULL,     
2339                 .force               = false,    
2340                 .event_list_str      = NULL,     
2341                 .summary             = false,    
2342                 .sort_order          = NULL,     
2343                 .show_callchain      = false,    
2344                 .max_stack           = 5,        
2345                 .timestart           = 0,        
2346                 .timeend             = 0,        
2347                 .nr_events           = 0,        
2348                 .nr_lost_chunks      = 0,        
2349                 .nr_lost_events      = 0,        
2350                 .all_runtime         = 0,        
2351                 .all_count           = 0,        
2352                 .nr_skipped_events   = { 0 },    
2353         };                                       
2354         static const char default_report_sort    
2355         static const char default_latency_sor    
2356         static const char default_top_sort_or    
2357         const struct option kwork_options[] =    
2358         OPT_INCR('v', "verbose", &verbose,       
2359                  "be more verbose (show symbo    
2360         OPT_BOOLEAN('D', "dump-raw-trace", &d    
2361                     "dump raw trace in ASCII"    
2362         OPT_STRING('k', "kwork", &kwork.event    
2363                    "list of kwork to profile     
2364         OPT_BOOLEAN('f', "force", &kwork.forc    
2365         OPT_END()                                
2366         };                                       
2367         const struct option report_options[]     
2368         OPT_STRING('s', "sort", &kwork.sort_o    
2369                    "sort by key(s): runtime,     
2370         OPT_STRING('C', "cpu", &kwork.cpu_lis    
2371                    "list of cpus to profile")    
2372         OPT_STRING('n', "name", &kwork.profil    
2373                    "event name to profile"),     
2374         OPT_STRING(0, "time", &kwork.time_str    
2375                    "Time span for analysis (s    
2376         OPT_STRING('i', "input", &input_name,    
2377                    "input file name"),           
2378         OPT_BOOLEAN('S', "with-summary", &kwo    
2379                     "Show summary with statis    
2380 #ifdef HAVE_BPF_SKEL                             
2381         OPT_BOOLEAN('b', "use-bpf", &kwork.us    
2382                     "Use BPF to measure kwork    
2383 #endif                                           
2384         OPT_PARENT(kwork_options)                
2385         };                                       
2386         const struct option latency_options[]    
2387         OPT_STRING('s', "sort", &kwork.sort_o    
2388                    "sort by key(s): avg, max,    
2389         OPT_STRING('C', "cpu", &kwork.cpu_lis    
2390                    "list of cpus to profile")    
2391         OPT_STRING('n', "name", &kwork.profil    
2392                    "event name to profile"),     
2393         OPT_STRING(0, "time", &kwork.time_str    
2394                    "Time span for analysis (s    
2395         OPT_STRING('i', "input", &input_name,    
2396                    "input file name"),           
2397 #ifdef HAVE_BPF_SKEL                             
2398         OPT_BOOLEAN('b', "use-bpf", &kwork.us    
2399                     "Use BPF to measure kwork    
2400 #endif                                           
2401         OPT_PARENT(kwork_options)                
2402         };                                       
2403         const struct option timehist_options[    
2404         OPT_STRING('k', "vmlinux", &symbol_co    
2405                    "file", "vmlinux pathname"    
2406         OPT_STRING(0, "kallsyms", &symbol_con    
2407                    "file", "kallsyms pathname    
2408         OPT_BOOLEAN('g', "call-graph", &kwork    
2409                     "Display call chains if p    
2410         OPT_UINTEGER(0, "max-stack", &kwork.m    
2411                    "Maximum number of functio    
2412         OPT_STRING(0, "symfs", &symbol_conf.s    
2413                     "Look for files with symb    
2414         OPT_STRING(0, "time", &kwork.time_str    
2415                    "Time span for analysis (s    
2416         OPT_STRING('C', "cpu", &kwork.cpu_lis    
2417                    "list of cpus to profile")    
2418         OPT_STRING('n', "name", &kwork.profil    
2419                    "event name to profile"),     
2420         OPT_STRING('i', "input", &input_name,    
2421                    "input file name"),           
2422         OPT_PARENT(kwork_options)                
2423         };                                       
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[] = {            
2442                 NULL,                            
2443                 NULL                             
2444         };                                       
2445         const char * const report_usage[] = {    
2446                 "perf kwork report [<options>    
2447                 NULL                             
2448         };                                       
2449         const char * const latency_usage[] =     
2450                 "perf kwork latency [<options    
2451                 NULL                             
2452         };                                       
2453         const char * const timehist_usage[] =    
2454                 "perf kwork timehist [<option    
2455                 NULL                             
2456         };                                       
2457         const char * const top_usage[] = {       
2458                 "perf kwork top [<options>]",    
2459                 NULL                             
2460         };                                       
2461         const char *const kwork_subcommands[]    
2462                 "record", "report", "latency"    
2463         };                                       
2464                                                  
2465         argc = parse_options_subcommand(argc,    
2466                                         kwork    
2467                                         PARSE    
2468         if (!argc)                               
2469                 usage_with_options(kwork_usag    
2470                                                  
2471         sort_dimension__add(&kwork, "id", &kw    
2472                                                  
2473         if (strlen(argv[0]) > 2 && strstarts(    
2474                 setup_event_list(&kwork, kwor    
2475                 return perf_kwork__record(&kw    
2476         } else if (strlen(argv[0]) > 2 && str    
2477                 kwork.sort_order = default_re    
2478                 if (argc > 1) {                  
2479                         argc = parse_options(    
2480                         if (argc)                
2481                                 usage_with_op    
2482                 }                                
2483                 kwork.report = KWORK_REPORT_R    
2484                 setup_sorting(&kwork, report_    
2485                 setup_event_list(&kwork, kwor    
2486                 return perf_kwork__report(&kw    
2487         } else if (strlen(argv[0]) > 2 && str    
2488                 kwork.sort_order = default_la    
2489                 if (argc > 1) {                  
2490                         argc = parse_options(    
2491                         if (argc)                
2492                                 usage_with_op    
2493                 }                                
2494                 kwork.report = KWORK_REPORT_L    
2495                 setup_sorting(&kwork, latency    
2496                 setup_event_list(&kwork, kwor    
2497                 return perf_kwork__report(&kw    
2498         } else if (strlen(argv[0]) > 2 && str    
2499                 if (argc > 1) {                  
2500                         argc = parse_options(    
2501                         if (argc)                
2502                                 usage_with_op    
2503                 }                                
2504                 kwork.report = KWORK_REPORT_T    
2505                 setup_event_list(&kwork, kwor    
2506                 return perf_kwork__timehist(&    
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                                   
2521                 usage_with_options(kwork_usag    
2522                                                  
2523         return 0;                                
2524 }                                                
2525                                                  

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

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

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

sflogo.php