forked from Minki/linux
dd2e18e9ac
When looking at PT or brstackinsn traces with 'perf script' it can be very useful to see the source code. This adds a simple facility to print them with 'perf script', if the information is available through dwarf % perf record ... % perf script -F insn,ip,sym,srccode ... 4004c6 main 5 for (i = 0; i < 10000000; i++) 4004cd main 5 for (i = 0; i < 10000000; i++) 4004c6 main 5 for (i = 0; i < 10000000; i++) 4004cd main 5 for (i = 0; i < 10000000; i++) 4004cd main 5 for (i = 0; i < 10000000; i++) 4004cd main 5 for (i = 0; i < 10000000; i++) 4004cd main 5 for (i = 0; i < 10000000; i++) 4004cd main 5 for (i = 0; i < 10000000; i++) 4004b3 main 6 v++; % perf record -b ... % perf script -F insn,ip,sym,srccode,brstackinsn ... main+22: 0000000000400543 insn: e8 ca ff ff ff # PRED |18 f1(); f1: 0000000000400512 insn: 55 |10 { 0000000000400513 insn: 48 89 e5 0000000000400516 insn: b8 00 00 00 00 |11 f2(); 000000000040051b insn: e8 d6 ff ff ff # PRED f2: 00000000004004f6 insn: 55 |5 { 00000000004004f7 insn: 48 89 e5 00000000004004fa insn: 8b 05 2c 0b 20 00 |6 c = a / b; 0000000000400500 insn: 8b 0d 2a 0b 20 00 0000000000400506 insn: 99 0000000000400507 insn: f7 f9 0000000000400509 insn: 89 05 29 0b 20 00 000000000040050f insn: 90 |7 } 0000000000400510 insn: 5d 0000000000400511 insn: c3 # PRED f1+14: 0000000000400520 insn: b8 00 00 00 00 |12 f2(); 0000000000400525 insn: e8 cc ff ff ff # PRED f2: 00000000004004f6 insn: 55 |5 { 00000000004004f7 insn: 48 89 e5 00000000004004fa insn: 8b 05 2c 0b 20 00 |6 c = a / b; Not supported for callchains currently, would need some layout changes there. Committer notes: Fixed the build on Alpine Linux (3.4 .. 3.8) by addressing this warning: In file included from util/srccode.c:19:0: /usr/include/sys/fcntl.h:1:2: error: #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h> [-Werror=cpp] #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h> ^~~~~~~ cc1: all warnings being treated as errors Signed-off-by: Andi Kleen <ak@linux.intel.com> Tested-by: Jiri Olsa <jolsa@kernel.org> Link: http://lkml.kernel.org/r/20181204001848.24769-1-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
143 lines
3.7 KiB
C
143 lines
3.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __PERF_THREAD_H
|
|
#define __PERF_THREAD_H
|
|
|
|
#include <linux/refcount.h>
|
|
#include <linux/rbtree.h>
|
|
#include <linux/list.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include "symbol.h"
|
|
#include "map.h"
|
|
#include <strlist.h>
|
|
#include <intlist.h>
|
|
#include "rwsem.h"
|
|
|
|
struct thread_stack;
|
|
struct unwind_libunwind_ops;
|
|
|
|
struct thread {
|
|
union {
|
|
struct rb_node rb_node;
|
|
struct list_head node;
|
|
};
|
|
struct map_groups *mg;
|
|
pid_t pid_; /* Not all tools update this */
|
|
pid_t tid;
|
|
pid_t ppid;
|
|
int cpu;
|
|
refcount_t refcnt;
|
|
bool comm_set;
|
|
int comm_len;
|
|
bool dead; /* if set thread has exited */
|
|
struct list_head namespaces_list;
|
|
struct rw_semaphore namespaces_lock;
|
|
struct list_head comm_list;
|
|
struct rw_semaphore comm_lock;
|
|
u64 db_id;
|
|
|
|
void *priv;
|
|
struct thread_stack *ts;
|
|
struct nsinfo *nsinfo;
|
|
struct srccode_state srccode_state;
|
|
#ifdef HAVE_LIBUNWIND_SUPPORT
|
|
void *addr_space;
|
|
struct unwind_libunwind_ops *unwind_libunwind_ops;
|
|
#endif
|
|
bool filter;
|
|
int filter_entry_depth;
|
|
};
|
|
|
|
struct machine;
|
|
struct namespaces;
|
|
struct comm;
|
|
|
|
struct thread *thread__new(pid_t pid, pid_t tid);
|
|
int thread__init_map_groups(struct thread *thread, struct machine *machine);
|
|
void thread__delete(struct thread *thread);
|
|
|
|
struct thread *thread__get(struct thread *thread);
|
|
void thread__put(struct thread *thread);
|
|
|
|
static inline void __thread__zput(struct thread **thread)
|
|
{
|
|
thread__put(*thread);
|
|
*thread = NULL;
|
|
}
|
|
|
|
#define thread__zput(thread) __thread__zput(&thread)
|
|
|
|
static inline void thread__exited(struct thread *thread)
|
|
{
|
|
thread->dead = true;
|
|
}
|
|
|
|
struct namespaces *thread__namespaces(const struct thread *thread);
|
|
int thread__set_namespaces(struct thread *thread, u64 timestamp,
|
|
struct namespaces_event *event);
|
|
|
|
int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
|
|
bool exec);
|
|
static inline int thread__set_comm(struct thread *thread, const char *comm,
|
|
u64 timestamp)
|
|
{
|
|
return __thread__set_comm(thread, comm, timestamp, false);
|
|
}
|
|
|
|
int thread__set_comm_from_proc(struct thread *thread);
|
|
|
|
int thread__comm_len(struct thread *thread);
|
|
struct comm *thread__comm(const struct thread *thread);
|
|
struct comm *thread__exec_comm(const struct thread *thread);
|
|
const char *thread__comm_str(const struct thread *thread);
|
|
int thread__insert_map(struct thread *thread, struct map *map);
|
|
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone);
|
|
size_t thread__fprintf(struct thread *thread, FILE *fp);
|
|
|
|
struct thread *thread__main_thread(struct machine *machine, struct thread *thread);
|
|
|
|
struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
|
|
struct addr_location *al);
|
|
struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 addr,
|
|
struct addr_location *al);
|
|
|
|
struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode,
|
|
u64 addr, struct addr_location *al);
|
|
struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode,
|
|
u64 addr, struct addr_location *al);
|
|
|
|
void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
|
|
struct addr_location *al);
|
|
|
|
static inline void *thread__priv(struct thread *thread)
|
|
{
|
|
return thread->priv;
|
|
}
|
|
|
|
static inline void thread__set_priv(struct thread *thread, void *p)
|
|
{
|
|
thread->priv = p;
|
|
}
|
|
|
|
static inline bool thread__is_filtered(struct thread *thread)
|
|
{
|
|
if (symbol_conf.comm_list &&
|
|
!strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) {
|
|
return true;
|
|
}
|
|
|
|
if (symbol_conf.pid_list &&
|
|
!intlist__has_entry(symbol_conf.pid_list, thread->pid_)) {
|
|
return true;
|
|
}
|
|
|
|
if (symbol_conf.tid_list &&
|
|
!intlist__has_entry(symbol_conf.tid_list, thread->tid)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif /* __PERF_THREAD_H */
|