int perf_event__synthesize_thread_map2(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, struct machine *machine) { union perf_event *event; int i, err, size; size = sizeof(event->thread_map); size += threads->nr * sizeof(event->thread_map.entries[0]); event = zalloc(size); if (!event) return -ENOMEM; event->header.type = PERF_RECORD_THREAD_MAP; event->header.size = size; event->thread_map.nr = threads->nr; for (i = 0; i < threads->nr; i++) { struct thread_map_event_entry *entry = &event->thread_map.entries[i]; char *comm = thread_map__comm(threads, i); if (!comm) comm = (char *) ""; entry->pid = thread_map__pid(threads, i); strncpy((char *) &entry->comm, comm, sizeof(entry->comm)); } err = process(tool, event, NULL, machine); free(event); return err; }
void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp, struct perf_evlist *evlist, int idx, bool per_cpu) { mp->idx = idx; if (per_cpu) { mp->cpu = evlist->cpus->map[idx]; if (evlist->threads) mp->tid = thread_map__pid(evlist->threads, 0); else mp->tid = -1; } else { mp->cpu = -1; mp->tid = thread_map__pid(evlist->threads, idx); } }
size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) { int i; size_t printed = fprintf(fp, "%d thread%s: ", threads->nr, threads->nr > 1 ? "s" : ""); for (i = 0; i < threads->nr; ++i) printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i)); return printed + fprintf(fp, "\n"); }
int test__thread_map(int subtest __maybe_unused) { struct thread_map *map; /* test map on current pid */ map = thread_map__new_by_pid(getpid()); TEST_ASSERT_VAL("failed to alloc map", map); thread_map__read_comms(map); TEST_ASSERT_VAL("wrong nr", map->nr == 1); TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == getpid()); TEST_ASSERT_VAL("wrong comm", thread_map__comm(map, 0) && !strcmp(thread_map__comm(map, 0), "perf")); TEST_ASSERT_VAL("wrong refcnt", atomic_read(&map->refcnt) == 1); thread_map__put(map); /* test dummy pid */ map = thread_map__new_dummy(); TEST_ASSERT_VAL("failed to alloc map", map); thread_map__read_comms(map); TEST_ASSERT_VAL("wrong nr", map->nr == 1); TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == -1); TEST_ASSERT_VAL("wrong comm", thread_map__comm(map, 0) && !strcmp(thread_map__comm(map, 0), "dummy")); TEST_ASSERT_VAL("wrong refcnt", atomic_read(&map->refcnt) == 1); thread_map__put(map); return 0; }
static void comm_init(struct thread_map *map, int i) { pid_t pid = thread_map__pid(map, i); char *comm = NULL; /* dummy pid comm initialization */ if (pid == -1) { map->map[i].comm = strdup("dummy"); return; } /* * The comm name is like extra bonus ;-), * so just warn if we fail for any reason. */ if (get_comm(&comm, pid)) pr_warning("Couldn't resolve comm name for pid %d\n", pid); map->map[i].comm = comm; }
int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, struct machine *machine, bool mmap_data, unsigned int proc_map_timeout) { union perf_event *comm_event, *mmap_event, *fork_event; int err = -1, thread, j; comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size); if (comm_event == NULL) goto out; mmap_event = malloc(sizeof(mmap_event->mmap2) + machine->id_hdr_size); if (mmap_event == NULL) goto out_free_comm; fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size); if (fork_event == NULL) goto out_free_mmap; err = 0; for (thread = 0; thread < threads->nr; ++thread) { if (__event__synthesize_thread(comm_event, mmap_event, fork_event, thread_map__pid(threads, thread), 0, process, tool, machine, mmap_data, proc_map_timeout)) { err = -1; break; } /* * comm.pid is set to thread group id by * perf_event__synthesize_comm */ if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) { bool need_leader = true; /* is thread group leader in thread_map? */ for (j = 0; j < threads->nr; ++j) { if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) { need_leader = false; break; } } /* if not, generate events for it */ if (need_leader && __event__synthesize_thread(comm_event, mmap_event, fork_event, comm_event->comm.pid, 0, process, tool, machine, mmap_data, proc_map_timeout)) { err = -1; break; } } } free(fork_event); out_free_mmap: free(mmap_event); out_free_comm: free(comm_event); out: return err; }
struct perf_sample *sample __maybe_unused, struct machine *machine __maybe_unused) { struct thread_map_event *map = &event->thread_map; struct thread_map *threads; TEST_ASSERT_VAL("wrong nr", map->nr == 1); TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid()); TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, "perf")); threads = thread_map__new_event(&event->thread_map); TEST_ASSERT_VAL("failed to alloc map", threads); TEST_ASSERT_VAL("wrong nr", threads->nr == 1); TEST_ASSERT_VAL("wrong pid", thread_map__pid(threads, 0) == getpid()); TEST_ASSERT_VAL("wrong comm", thread_map__comm(threads, 0) && !strcmp(thread_map__comm(threads, 0), "perf")); TEST_ASSERT_VAL("wrong refcnt", atomic_read(&threads->refcnt) == 1); thread_map__put(threads); return 0; } int test__thread_map_synthesize(int subtest __maybe_unused) { struct thread_map *threads; /* test map on current pid */ threads = thread_map__new_by_pid(getpid());