2009-06-26 18:28:00 +04:00
# ifndef __PERF_CALLCHAIN_H
# define __PERF_CALLCHAIN_H
# include "../perf.h"
2009-07-01 21:46:08 +04:00
# include <linux/list.h>
2009-07-01 19:28:37 +04:00
# include <linux/rbtree.h>
2010-05-09 18:47:13 +04:00
# include "event.h"
2009-07-01 07:35:14 +04:00
# include "symbol.h"
2009-06-26 18:28:00 +04:00
2014-05-05 14:46:17 +04:00
enum perf_call_graph_mode {
CALLCHAIN_NONE ,
CALLCHAIN_FP ,
CALLCHAIN_DWARF ,
CALLCHAIN_MAX
} ;
2009-07-02 19:58:21 +04:00
enum chain_mode {
2009-08-08 04:16:24 +04:00
CHAIN_NONE ,
2009-07-05 09:39:21 +04:00
CHAIN_FLAT ,
CHAIN_GRAPH_ABS ,
CHAIN_GRAPH_REL
2009-07-02 19:58:21 +04:00
} ;
2009-06-26 18:28:00 +04:00
2011-06-07 19:49:46 +04:00
enum chain_order {
ORDER_CALLER ,
ORDER_CALLEE
} ;
2009-06-26 18:28:00 +04:00
struct callchain_node {
struct callchain_node * parent ;
2009-07-01 14:37:06 +04:00
struct list_head val ;
2013-10-11 09:15:36 +04:00
struct rb_node rb_node_in ; /* to insert nodes in an rbtree */
struct rb_node rb_node ; /* to sort nodes in an output tree */
struct rb_root rb_root_in ; /* input tree of children */
struct rb_root rb_root ; /* sorted output tree of children */
2009-07-01 14:37:06 +04:00
unsigned int val_nr ;
u64 hit ;
2009-08-07 09:11:05 +04:00
u64 children_hit ;
2009-06-26 18:28:00 +04:00
} ;
2010-08-22 22:05:22 +04:00
struct callchain_root {
u64 max_depth ;
struct callchain_node node ;
} ;
2009-07-05 09:39:21 +04:00
struct callchain_param ;
2010-08-22 22:05:22 +04:00
typedef void ( * sort_chain_func_t ) ( struct rb_root * , struct callchain_root * ,
2009-07-05 09:39:21 +04:00
u64 , struct callchain_param * ) ;
2013-07-19 02:33:57 +04:00
enum chain_key {
CCKEY_FUNCTION ,
CCKEY_ADDRESS
} ;
2009-07-05 09:39:21 +04:00
struct callchain_param {
2014-09-23 05:01:41 +04:00
bool enabled ;
enum perf_call_graph_mode record_mode ;
u32 dump_size ;
2009-07-05 09:39:21 +04:00
enum chain_mode mode ;
2010-05-10 03:28:10 +04:00
u32 print_limit ;
2009-07-05 09:39:21 +04:00
double min_percent ;
sort_chain_func_t sort ;
2011-06-07 19:49:46 +04:00
enum chain_order order ;
2013-07-19 02:33:57 +04:00
enum chain_key key ;
2009-07-05 09:39:21 +04:00
} ;
2009-06-26 18:28:00 +04:00
struct callchain_list {
2009-07-01 14:37:06 +04:00
u64 ip ;
2010-03-24 22:40:18 +03:00
struct map_symbol ms ;
2009-06-26 18:28:00 +04:00
struct list_head list ;
} ;
2011-01-14 06:51:58 +03:00
/*
* A callchain cursor is a single linked list that
* let one feed a callchain progressively .
2012-07-17 20:20:59 +04:00
* It keeps persistent allocated entries to minimize
2011-01-14 06:51:58 +03:00
* allocations .
*/
struct callchain_cursor_node {
u64 ip ;
struct map * map ;
struct symbol * sym ;
struct callchain_cursor_node * next ;
} ;
struct callchain_cursor {
u64 nr ;
struct callchain_cursor_node * first ;
struct callchain_cursor_node * * last ;
u64 pos ;
struct callchain_cursor_node * curr ;
} ;
2012-05-31 09:43:26 +04:00
extern __thread struct callchain_cursor callchain_cursor ;
2010-08-22 22:05:22 +04:00
static inline void callchain_init ( struct callchain_root * root )
2009-06-26 18:28:00 +04:00
{
2010-08-22 22:05:22 +04:00
INIT_LIST_HEAD ( & root - > node . val ) ;
2010-07-08 08:06:17 +04:00
2010-08-22 22:05:22 +04:00
root - > node . parent = NULL ;
root - > node . hit = 0 ;
2010-08-27 04:28:40 +04:00
root - > node . children_hit = 0 ;
2013-10-11 09:15:36 +04:00
root - > node . rb_root_in = RB_ROOT ;
2010-08-22 22:05:22 +04:00
root - > max_depth = 0 ;
2009-06-26 18:28:00 +04:00
}
2011-01-14 06:51:59 +03:00
static inline u64 callchain_cumul_hits ( struct callchain_node * node )
2009-08-07 09:11:05 +04:00
{
return node - > hit + node - > children_hit ;
}
2011-01-14 06:52:00 +03:00
int callchain_register_param ( struct callchain_param * param ) ;
2011-01-14 06:51:58 +03:00
int callchain_append ( struct callchain_root * root ,
struct callchain_cursor * cursor ,
u64 period ) ;
int callchain_merge ( struct callchain_cursor * cursor ,
struct callchain_root * dst , struct callchain_root * src ) ;
2010-05-09 18:47:13 +04:00
2011-01-14 06:51:58 +03:00
/*
* Initialize a cursor before adding entries inside , but keep
* the previously allocated entries as a cache .
*/
static inline void callchain_cursor_reset ( struct callchain_cursor * cursor )
{
cursor - > nr = 0 ;
cursor - > last = & cursor - > first ;
}
int callchain_cursor_append ( struct callchain_cursor * cursor , u64 ip ,
struct map * map , struct symbol * sym ) ;
/* Close a cursor writing session. Initialize for the reader */
static inline void callchain_cursor_commit ( struct callchain_cursor * cursor )
{
cursor - > curr = cursor - > first ;
cursor - > pos = 0 ;
}
/* Cursor reading iteration helpers */
static inline struct callchain_cursor_node *
callchain_cursor_current ( struct callchain_cursor * cursor )
{
if ( cursor - > pos = = cursor - > nr )
return NULL ;
return cursor - > curr ;
}
static inline void callchain_cursor_advance ( struct callchain_cursor * cursor )
{
cursor - > curr = cursor - > curr - > next ;
cursor - > pos + + ;
}
2012-12-11 23:46:05 +04:00
struct option ;
2014-01-14 09:25:35 +04:00
struct hist_entry ;
2012-12-11 23:46:05 +04:00
2014-09-23 05:01:41 +04:00
int record_parse_callchain ( const char * arg ) ;
2012-12-11 23:46:05 +04:00
int record_parse_callchain_opt ( const struct option * opt , const char * arg , int unset ) ;
2013-10-26 18:25:33 +04:00
int record_callchain_opt ( const struct option * opt , const char * arg , int unset ) ;
2014-01-14 09:25:35 +04:00
int sample__resolve_callchain ( struct perf_sample * sample , struct symbol * * parent ,
struct perf_evsel * evsel , struct addr_location * al ,
int max_stack ) ;
int hist_entry__append_callchain ( struct hist_entry * he , struct perf_sample * sample ) ;
2013-10-31 08:58:30 +04:00
int fill_callchain_info ( struct addr_location * al , struct callchain_cursor_node * node ,
bool hide_unresolved ) ;
2014-01-14 09:25:35 +04:00
2012-12-11 23:46:05 +04:00
extern const char record_callchain_help [ ] ;
2014-04-07 22:55:24 +04:00
int parse_callchain_report_opt ( const char * arg ) ;
2012-09-10 08:38:00 +04:00
static inline void callchain_cursor_snapshot ( struct callchain_cursor * dest ,
struct callchain_cursor * src )
{
* dest = * src ;
dest - > first = src - > curr ;
dest - > nr - = src - > pos ;
}
2014-06-25 19:49:03 +04:00
# ifdef HAVE_SKIP_CALLCHAIN_IDX
extern int arch_skip_callchain_idx ( struct machine * machine ,
struct thread * thread , struct ip_callchain * chain ) ;
# else
static inline int arch_skip_callchain_idx ( struct machine * machine __maybe_unused ,
struct thread * thread __maybe_unused ,
struct ip_callchain * chain __maybe_unused )
{
return - 1 ;
}
# endif
2009-09-24 20:02:18 +04:00
# endif /* __PERF_CALLCHAIN_H */