mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 05:04:00 +08:00
f62d3f0f45
When we were processing a PERF_RECORD_EXIT event we first used machine__findnew_thread for both the thread exiting and for its parent, only to use just the thread struct associated with the one exiting, and to just delete it. If it existed, i.e. not created at this very moment in machine__findnew_thread, it will be moved to the machine->dead_threads linked list, because we may have hist_entries pointing to it, but if it was created just do be deleted, it will just sit there with no references at all. Use the new machine__find_thread() method so that if it is not there, we don't create it. As a bonus the parent thread will also not be created at this point. Create process_fork() and process_exit() helpers to use this and make the builtins use it instead of the generic process_task(), ditched by this patch. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-z7n2y98ebjyrvmytaope4vdl@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
90 lines
2.3 KiB
C
90 lines
2.3 KiB
C
/*
|
|
* build-id.c
|
|
*
|
|
* build-id support
|
|
*
|
|
* Copyright (C) 2009, 2010 Red Hat Inc.
|
|
* Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
*/
|
|
#include "util.h"
|
|
#include <stdio.h>
|
|
#include "build-id.h"
|
|
#include "event.h"
|
|
#include "symbol.h"
|
|
#include <linux/kernel.h>
|
|
#include "debug.h"
|
|
#include "session.h"
|
|
#include "tool.h"
|
|
|
|
static int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
|
|
union perf_event *event,
|
|
struct perf_sample *sample __maybe_unused,
|
|
struct perf_evsel *evsel __maybe_unused,
|
|
struct machine *machine)
|
|
{
|
|
struct addr_location al;
|
|
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
|
struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
|
|
|
|
if (thread == NULL) {
|
|
pr_err("problem processing %d event, skipping it.\n",
|
|
event->header.type);
|
|
return -1;
|
|
}
|
|
|
|
thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
|
|
event->ip.ip, &al);
|
|
|
|
if (al.map != NULL)
|
|
al.map->dso->hit = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
|
|
union perf_event *event,
|
|
struct perf_sample *sample
|
|
__maybe_unused,
|
|
struct machine *machine)
|
|
{
|
|
struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
|
|
|
|
dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
|
|
event->fork.ppid, event->fork.ptid);
|
|
|
|
if (thread) {
|
|
rb_erase(&thread->rb_node, &machine->threads);
|
|
machine->last_match = NULL;
|
|
thread__delete(thread);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct perf_tool build_id__mark_dso_hit_ops = {
|
|
.sample = build_id__mark_dso_hit,
|
|
.mmap = perf_event__process_mmap,
|
|
.fork = perf_event__process_fork,
|
|
.exit = perf_event__exit_del_thread,
|
|
.attr = perf_event__process_attr,
|
|
.build_id = perf_event__process_build_id,
|
|
};
|
|
|
|
char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
|
|
{
|
|
char build_id_hex[BUILD_ID_SIZE * 2 + 1];
|
|
|
|
if (!self->has_build_id)
|
|
return NULL;
|
|
|
|
build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex);
|
|
if (bf == NULL) {
|
|
if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
|
|
build_id_hex, build_id_hex + 2) < 0)
|
|
return NULL;
|
|
} else
|
|
snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
|
|
build_id_hex, build_id_hex + 2);
|
|
return bf;
|
|
}
|