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

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

Version: ~ [ linux-5.10-rc1 ] ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include "builtin.h"
  2 #include "util/color.h"
  3 #include "util/evlist.h"
  4 #include "util/machine.h"
  5 #include "util/thread.h"
  6 #include "util/parse-options.h"
  7 #include "util/thread_map.h"
  8 #include "event-parse.h"
  9 
 10 #include <libaudit.h>
 11 #include <stdlib.h>
 12 
 13 static struct syscall_fmt {
 14         const char *name;
 15         const char *alias;
 16         bool       errmsg;
 17         bool       timeout;
 18 } syscall_fmts[] = {
 19         { .name     = "access",     .errmsg = true, },
 20         { .name     = "arch_prctl", .errmsg = true, .alias = "prctl", },
 21         { .name     = "fstat",      .errmsg = true, .alias = "newfstat", },
 22         { .name     = "fstatat",    .errmsg = true, .alias = "newfstatat", },
 23         { .name     = "futex",      .errmsg = true, },
 24         { .name     = "open",       .errmsg = true, },
 25         { .name     = "poll",       .errmsg = true, .timeout = true, },
 26         { .name     = "ppoll",      .errmsg = true, .timeout = true, },
 27         { .name     = "read",       .errmsg = true, },
 28         { .name     = "recvfrom",   .errmsg = true, },
 29         { .name     = "select",     .errmsg = true, .timeout = true, },
 30         { .name     = "socket",     .errmsg = true, },
 31         { .name     = "stat",       .errmsg = true, .alias = "newstat", },
 32 };
 33 
 34 static int syscall_fmt__cmp(const void *name, const void *fmtp)
 35 {
 36         const struct syscall_fmt *fmt = fmtp;
 37         return strcmp(name, fmt->name);
 38 }
 39 
 40 static struct syscall_fmt *syscall_fmt__find(const char *name)
 41 {
 42         const int nmemb = ARRAY_SIZE(syscall_fmts);
 43         return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
 44 }
 45 
 46 struct syscall {
 47         struct event_format *tp_format;
 48         const char          *name;
 49         struct syscall_fmt  *fmt;
 50 };
 51 
 52 static size_t fprintf_duration(unsigned long t, FILE *fp)
 53 {
 54         double duration = (double)t / NSEC_PER_MSEC;
 55         size_t printed = fprintf(fp, "(");
 56 
 57         if (duration >= 1.0)
 58                 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
 59         else if (duration >= 0.01)
 60                 printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
 61         else
 62                 printed += color_fprintf(fp, PERF_COLOR_NORMAL, "%6.3f ms", duration);
 63         return printed + fprintf(stdout, "): ");
 64 }
 65 
 66 struct thread_trace {
 67         u64               entry_time;
 68         u64               exit_time;
 69         bool              entry_pending;
 70         unsigned long     nr_events;
 71         char              *entry_str;
 72         double            runtime_ms;
 73 };
 74 
 75 static struct thread_trace *thread_trace__new(void)
 76 {
 77         return zalloc(sizeof(struct thread_trace));
 78 }
 79 
 80 static struct thread_trace *thread__trace(struct thread *thread)
 81 {
 82         struct thread_trace *ttrace;
 83 
 84         if (thread == NULL)
 85                 goto fail;
 86 
 87         if (thread->priv == NULL)
 88                 thread->priv = thread_trace__new();
 89                 
 90         if (thread->priv == NULL)
 91                 goto fail;
 92 
 93         ttrace = thread->priv;
 94         ++ttrace->nr_events;
 95 
 96         return ttrace;
 97 fail:
 98         color_fprintf(stdout, PERF_COLOR_RED,
 99                       "WARNING: not enough memory, dropping samples!\n");
100         return NULL;
101 }
102 
103 struct trace {
104         int                     audit_machine;
105         struct {
106                 int             max;
107                 struct syscall  *table;
108         } syscalls;
109         struct perf_record_opts opts;
110         struct machine          host;
111         u64                     base_time;
112         unsigned long           nr_events;
113         bool                    sched;
114         bool                    multiple_threads;
115         double                  duration_filter;
116         double                  runtime_ms;
117 };
118 
119 static bool trace__filter_duration(struct trace *trace, double t)
120 {
121         return t < (trace->duration_filter * NSEC_PER_MSEC);
122 }
123 
124 static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
125 {
126         double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
127 
128         return fprintf(fp, "%10.3f ", ts);
129 }
130 
131 static bool done = false;
132 
133 static void sig_handler(int sig __maybe_unused)
134 {
135         done = true;
136 }
137 
138 static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
139                                         u64 duration, u64 tstamp, FILE *fp)
140 {
141         size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
142         printed += fprintf_duration(duration, fp);
143 
144         if (trace->multiple_threads)
145                 printed += fprintf(fp, "%d ", thread->pid);
146 
147         return printed;
148 }
149 
150 static int trace__process_event(struct machine *machine, union perf_event *event)
151 {
152         int ret = 0;
153 
154         switch (event->header.type) {
155         case PERF_RECORD_LOST:
156                 color_fprintf(stdout, PERF_COLOR_RED,
157                               "LOST %" PRIu64 " events!\n", event->lost.lost);
158                 ret = machine__process_lost_event(machine, event);
159         default:
160                 ret = machine__process_event(machine, event);
161                 break;
162         }
163 
164         return ret;
165 }
166 
167 static int trace__tool_process(struct perf_tool *tool __maybe_unused,
168                                union perf_event *event,
169                                struct perf_sample *sample __maybe_unused,
170                                struct machine *machine)
171 {
172         return trace__process_event(machine, event);
173 }
174 
175 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
176 {
177         int err = symbol__init();
178 
179         if (err)
180                 return err;
181 
182         machine__init(&trace->host, "", HOST_KERNEL_ID);
183         machine__create_kernel_maps(&trace->host);
184 
185         if (perf_target__has_task(&trace->opts.target)) {
186                 err = perf_event__synthesize_thread_map(NULL, evlist->threads,
187                                                         trace__tool_process,
188                                                         &trace->host);
189         } else {
190                 err = perf_event__synthesize_threads(NULL, trace__tool_process,
191                                                      &trace->host);
192         }
193 
194         if (err)
195                 symbol__exit();
196 
197         return err;
198 }
199 
200 static int trace__read_syscall_info(struct trace *trace, int id)
201 {
202         char tp_name[128];
203         struct syscall *sc;
204         const char *name = audit_syscall_to_name(id, trace->audit_machine);
205 
206         if (name == NULL)
207                 return -1;
208 
209         if (id > trace->syscalls.max) {
210                 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
211 
212                 if (nsyscalls == NULL)
213                         return -1;
214 
215                 if (trace->syscalls.max != -1) {
216                         memset(nsyscalls + trace->syscalls.max + 1, 0,
217                                (id - trace->syscalls.max) * sizeof(*sc));
218                 } else {
219                         memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
220                 }
221 
222                 trace->syscalls.table = nsyscalls;
223                 trace->syscalls.max   = id;
224         }
225 
226         sc = trace->syscalls.table + id;
227         sc->name = name;
228         sc->fmt  = syscall_fmt__find(sc->name);
229 
230         snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
231         sc->tp_format = event_format__new("syscalls", tp_name);
232 
233         if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
234                 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
235                 sc->tp_format = event_format__new("syscalls", tp_name);
236         }
237 
238         return sc->tp_format != NULL ? 0 : -1;
239 }
240 
241 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
242                                       unsigned long *args)
243 {
244         int i = 0;
245         size_t printed = 0;
246 
247         if (sc->tp_format != NULL) {
248                 struct format_field *field;
249 
250                 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
251                         printed += scnprintf(bf + printed, size - printed,
252                                              "%s%s: %ld", printed ? ", " : "",
253                                              field->name, args[i++]);
254                 }
255         } else {
256                 while (i < 6) {
257                         printed += scnprintf(bf + printed, size - printed,
258                                              "%sarg%d: %ld",
259                                              printed ? ", " : "", i, args[i]);
260                         ++i;
261                 }
262         }
263 
264         return printed;
265 }
266 
267 typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
268                                   struct perf_sample *sample);
269 
270 static struct syscall *trace__syscall_info(struct trace *trace,
271                                            struct perf_evsel *evsel,
272                                            struct perf_sample *sample)
273 {
274         int id = perf_evsel__intval(evsel, sample, "id");
275 
276         if (id < 0) {
277                 printf("Invalid syscall %d id, skipping...\n", id);
278                 return NULL;
279         }
280 
281         if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
282             trace__read_syscall_info(trace, id))
283                 goto out_cant_read;
284 
285         if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
286                 goto out_cant_read;
287 
288         return &trace->syscalls.table[id];
289 
290 out_cant_read:
291         printf("Problems reading syscall %d", id);
292         if (id <= trace->syscalls.max && trace->syscalls.table[id].name != NULL)
293                 printf("(%s)", trace->syscalls.table[id].name);
294         puts(" information");
295         return NULL;
296 }
297 
298 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
299                             struct perf_sample *sample)
300 {
301         char *msg;
302         void *args;
303         size_t printed = 0;
304         struct thread *thread = machine__findnew_thread(&trace->host, sample->tid);
305         struct syscall *sc = trace__syscall_info(trace, evsel, sample);
306         struct thread_trace *ttrace = thread__trace(thread);
307 
308         if (ttrace == NULL || sc == NULL)
309                 return -1;
310 
311         args = perf_evsel__rawptr(evsel, sample, "args");
312         if (args == NULL) {
313                 printf("Problems reading syscall arguments\n");
314                 return -1;
315         }
316 
317         ttrace = thread->priv;
318 
319         if (ttrace->entry_str == NULL) {
320                 ttrace->entry_str = malloc(1024);
321                 if (!ttrace->entry_str)
322                         return -1;
323         }
324 
325         ttrace->entry_time = sample->time;
326         msg = ttrace->entry_str;
327         printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
328 
329         printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,  args);
330 
331         if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
332                 if (!trace->duration_filter) {
333                         trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, stdout);
334                         printf("%-70s\n", ttrace->entry_str);
335                 }
336         } else
337                 ttrace->entry_pending = true;
338 
339         return 0;
340 }
341 
342 static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
343                            struct perf_sample *sample)
344 {
345         int ret;
346         u64 duration = 0;
347         struct thread *thread = machine__findnew_thread(&trace->host, sample->tid);
348         struct thread_trace *ttrace = thread__trace(thread);
349         struct syscall *sc = trace__syscall_info(trace, evsel, sample);
350 
351         if (ttrace == NULL || sc == NULL)
352                 return -1;
353 
354         ret = perf_evsel__intval(evsel, sample, "ret");
355 
356         ttrace = thread->priv;
357 
358         ttrace->exit_time = sample->time;
359 
360         if (ttrace->entry_time) {
361                 duration = sample->time - ttrace->entry_time;
362                 if (trace__filter_duration(trace, duration))
363                         goto out;
364         } else if (trace->duration_filter)
365                 goto out;
366 
367         trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, stdout);
368 
369         if (ttrace->entry_pending) {
370                 printf("%-70s", ttrace->entry_str);
371         } else {
372                 printf(" ... [");
373                 color_fprintf(stdout, PERF_COLOR_YELLOW, "continued");
374                 printf("]: %s()", sc->name);
375         }
376 
377         if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
378                 char bf[256];
379                 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
380                            *e = audit_errno_to_name(-ret);
381 
382                 printf(") = -1 %s %s", e, emsg);
383         } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
384                 printf(") = 0 Timeout");
385         else
386                 printf(") = %d", ret);
387 
388         putchar('\n');
389 out:
390         ttrace->entry_pending = false;
391 
392         return 0;
393 }
394 
395 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
396                                      struct perf_sample *sample)
397 {
398         u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
399         double runtime_ms = (double)runtime / NSEC_PER_MSEC;
400         struct thread *thread = machine__findnew_thread(&trace->host, sample->tid);
401         struct thread_trace *ttrace = thread__trace(thread);
402 
403         if (ttrace == NULL)
404                 goto out_dump;
405 
406         ttrace->runtime_ms += runtime_ms;
407         trace->runtime_ms += runtime_ms;
408         return 0;
409 
410 out_dump:
411         printf("%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
412                evsel->name,
413                perf_evsel__strval(evsel, sample, "comm"),
414                (pid_t)perf_evsel__intval(evsel, sample, "pid"),
415                runtime,
416                perf_evsel__intval(evsel, sample, "vruntime"));
417         return 0;
418 }
419 
420 static int trace__run(struct trace *trace, int argc, const char **argv)
421 {
422         struct perf_evlist *evlist = perf_evlist__new();
423         struct perf_evsel *evsel;
424         int err = -1, i;
425         unsigned long before;
426         const bool forks = argc > 0;
427 
428         if (evlist == NULL) {
429                 printf("Not enough memory to run!\n");
430                 goto out;
431         }
432 
433         if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
434             perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
435                 printf("Couldn't read the raw_syscalls tracepoints information!\n");
436                 goto out_delete_evlist;
437         }
438 
439         if (trace->sched &&
440             perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
441                                    trace__sched_stat_runtime)) {
442                 printf("Couldn't read the sched_stat_runtime tracepoint information!\n");
443                 goto out_delete_evlist;
444         }
445 
446         err = perf_evlist__create_maps(evlist, &trace->opts.target);
447         if (err < 0) {
448                 printf("Problems parsing the target to trace, check your options!\n");
449                 goto out_delete_evlist;
450         }
451 
452         err = trace__symbols_init(trace, evlist);
453         if (err < 0) {
454                 printf("Problems initializing symbol libraries!\n");
455                 goto out_delete_maps;
456         }
457 
458         perf_evlist__config(evlist, &trace->opts);
459 
460         signal(SIGCHLD, sig_handler);
461         signal(SIGINT, sig_handler);
462 
463         if (forks) {
464                 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
465                                                     argv, false, false);
466                 if (err < 0) {
467                         printf("Couldn't run the workload!\n");
468                         goto out_delete_maps;
469                 }
470         }
471 
472         err = perf_evlist__open(evlist);
473         if (err < 0) {
474                 printf("Couldn't create the events: %s\n", strerror(errno));
475                 goto out_delete_maps;
476         }
477 
478         err = perf_evlist__mmap(evlist, UINT_MAX, false);
479         if (err < 0) {
480                 printf("Couldn't mmap the events: %s\n", strerror(errno));
481                 goto out_close_evlist;
482         }
483 
484         perf_evlist__enable(evlist);
485 
486         if (forks)
487                 perf_evlist__start_workload(evlist);
488 
489         trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1;
490 again:
491         before = trace->nr_events;
492 
493         for (i = 0; i < evlist->nr_mmaps; i++) {
494                 union perf_event *event;
495 
496                 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
497                         const u32 type = event->header.type;
498                         tracepoint_handler handler;
499                         struct perf_sample sample;
500 
501                         ++trace->nr_events;
502 
503                         err = perf_evlist__parse_sample(evlist, event, &sample);
504                         if (err) {
505                                 printf("Can't parse sample, err = %d, skipping...\n", err);
506                                 continue;
507                         }
508 
509                         if (trace->base_time == 0)
510                                 trace->base_time = sample.time;
511 
512                         if (type != PERF_RECORD_SAMPLE) {
513                                 trace__process_event(&trace->host, event);
514                                 continue;
515                         }
516 
517                         evsel = perf_evlist__id2evsel(evlist, sample.id);
518                         if (evsel == NULL) {
519                                 printf("Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
520                                 continue;
521                         }
522 
523                         if (sample.raw_data == NULL) {
524                                 printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
525                                        perf_evsel__name(evsel), sample.tid,
526                                        sample.cpu, sample.raw_size);
527                                 continue;
528                         }
529 
530                         handler = evsel->handler.func;
531                         handler(trace, evsel, &sample);
532                 }
533         }
534 
535         if (trace->nr_events == before) {
536                 if (done)
537                         goto out_unmap_evlist;
538 
539                 poll(evlist->pollfd, evlist->nr_fds, -1);
540         }
541 
542         if (done)
543                 perf_evlist__disable(evlist);
544 
545         goto again;
546 
547 out_unmap_evlist:
548         perf_evlist__munmap(evlist);
549 out_close_evlist:
550         perf_evlist__close(evlist);
551 out_delete_maps:
552         perf_evlist__delete_maps(evlist);
553 out_delete_evlist:
554         perf_evlist__delete(evlist);
555 out:
556         return err;
557 }
558 
559 static size_t trace__fprintf_threads_header(FILE *fp)
560 {
561         size_t printed;
562 
563         printed  = fprintf(fp, "\n _____________________________________________________________________\n");
564         printed += fprintf(fp," __)    Summary of events    (__\n\n");
565         printed += fprintf(fp,"              [ task - pid ]     [ events ] [ ratio ]  [ runtime ]\n");
566         printed += fprintf(fp," _____________________________________________________________________\n\n");
567 
568         return printed;
569 }
570 
571 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
572 {
573         size_t printed = trace__fprintf_threads_header(fp);
574         struct rb_node *nd;
575 
576         for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
577                 struct thread *thread = rb_entry(nd, struct thread, rb_node);
578                 struct thread_trace *ttrace = thread->priv;
579                 const char *color;
580                 double ratio;
581 
582                 if (ttrace == NULL)
583                         continue;
584 
585                 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
586 
587                 color = PERF_COLOR_NORMAL;
588                 if (ratio > 50.0)
589                         color = PERF_COLOR_RED;
590                 else if (ratio > 25.0)
591                         color = PERF_COLOR_GREEN;
592                 else if (ratio > 5.0)
593                         color = PERF_COLOR_YELLOW;
594 
595                 printed += color_fprintf(fp, color, "%20s", thread->comm);
596                 printed += fprintf(fp, " - %-5d :%11lu   [", thread->pid, ttrace->nr_events);
597                 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
598                 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
599         }
600 
601         return printed;
602 }
603 
604 static int trace__set_duration(const struct option *opt, const char *str,
605                                int unset __maybe_unused)
606 {
607         struct trace *trace = opt->value;
608 
609         trace->duration_filter = atof(str);
610         return 0;
611 }
612 
613 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
614 {
615         const char * const trace_usage[] = {
616                 "perf trace [<options>] [<command>]",
617                 "perf trace [<options>] -- <command> [<options>]",
618                 NULL
619         };
620         struct trace trace = {
621                 .audit_machine = audit_detect_machine(),
622                 .syscalls = {
623                         . max = -1,
624                 },
625                 .opts = {
626                         .target = {
627                                 .uid       = UINT_MAX,
628                                 .uses_mmap = true,
629                         },
630                         .user_freq     = UINT_MAX,
631                         .user_interval = ULLONG_MAX,
632                         .no_delay      = true,
633                         .mmap_pages    = 1024,
634                 },
635         };
636         const struct option trace_options[] = {
637         OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
638                     "trace events on existing process id"),
639         OPT_STRING(0, "tid", &trace.opts.target.tid, "tid",
640                     "trace events on existing thread id"),
641         OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide,
642                     "system-wide collection from all CPUs"),
643         OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu",
644                     "list of cpus to monitor"),
645         OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
646                     "child tasks do not inherit counters"),
647         OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages,
648                      "number of mmap data pages"),
649         OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user",
650                    "user to profile"),
651         OPT_CALLBACK(0, "duration", &trace, "float",
652                      "show only events with duration > N.M ms",
653                      trace__set_duration),
654         OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
655         OPT_END()
656         };
657         int err;
658         char bf[BUFSIZ];
659 
660         argc = parse_options(argc, argv, trace_options, trace_usage, 0);
661 
662         err = perf_target__validate(&trace.opts.target);
663         if (err) {
664                 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
665                 printf("%s", bf);
666                 return err;
667         }
668 
669         err = perf_target__parse_uid(&trace.opts.target);
670         if (err) {
671                 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
672                 printf("%s", bf);
673                 return err;
674         }
675 
676         if (!argc && perf_target__none(&trace.opts.target))
677                 trace.opts.target.system_wide = true;
678 
679         err = trace__run(&trace, argc, argv);
680 
681         if (trace.sched && !err)
682                 trace__fprintf_thread_summary(&trace, stdout);
683 
684         return err;
685 }
686 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp