2018-01-05 00:55:04 +03:00
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 Facebook
# include <linux/bpf.h>
# include "bpf_helpers.h"
# ifndef PERF_MAX_STACK_DEPTH
# define PERF_MAX_STACK_DEPTH 127
# endif
struct bpf_map_def SEC ( " maps " ) control_map = {
. type = BPF_MAP_TYPE_ARRAY ,
. key_size = sizeof ( __u32 ) ,
. value_size = sizeof ( __u32 ) ,
. max_entries = 1 ,
} ;
struct bpf_map_def SEC ( " maps " ) stackid_hmap = {
. type = BPF_MAP_TYPE_HASH ,
. key_size = sizeof ( __u32 ) ,
. value_size = sizeof ( __u32 ) ,
2018-04-29 08:28:16 +03:00
. max_entries = 16384 ,
2018-01-05 00:55:04 +03:00
} ;
struct bpf_map_def SEC ( " maps " ) stackmap = {
. type = BPF_MAP_TYPE_STACK_TRACE ,
. key_size = sizeof ( __u32 ) ,
. value_size = sizeof ( __u64 ) * PERF_MAX_STACK_DEPTH ,
2018-04-29 08:28:16 +03:00
. max_entries = 16384 ,
} ;
struct bpf_map_def SEC ( " maps " ) stack_amap = {
. type = BPF_MAP_TYPE_ARRAY ,
. key_size = sizeof ( __u32 ) ,
. value_size = sizeof ( __u64 ) * PERF_MAX_STACK_DEPTH ,
. max_entries = 16384 ,
2018-01-05 00:55:04 +03:00
} ;
/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
struct sched_switch_args {
unsigned long long pad ;
char prev_comm [ 16 ] ;
int prev_pid ;
int prev_prio ;
long long prev_state ;
char next_comm [ 16 ] ;
int next_pid ;
int next_prio ;
} ;
SEC ( " tracepoint/sched/sched_switch " )
int oncpu ( struct sched_switch_args * ctx )
{
2018-04-29 08:28:16 +03:00
__u32 max_len = PERF_MAX_STACK_DEPTH * sizeof ( __u64 ) ;
2018-01-05 00:55:04 +03:00
__u32 key = 0 , val = 0 , * value_p ;
2018-04-29 08:28:16 +03:00
void * stack_p ;
2018-01-05 00:55:04 +03:00
value_p = bpf_map_lookup_elem ( & control_map , & key ) ;
if ( value_p & & * value_p )
return 0 ; /* skip if non-zero *value_p */
/* The size of stackmap and stackid_hmap should be the same */
key = bpf_get_stackid ( ctx , & stackmap , 0 ) ;
2018-04-29 08:28:16 +03:00
if ( ( int ) key > = 0 ) {
2018-01-05 00:55:04 +03:00
bpf_map_update_elem ( & stackid_hmap , & key , & val , 0 ) ;
2018-04-29 08:28:16 +03:00
stack_p = bpf_map_lookup_elem ( & stack_amap , & key ) ;
if ( stack_p )
bpf_get_stack ( ctx , stack_p , max_len , 0 ) ;
}
2018-01-05 00:55:04 +03:00
return 0 ;
}
char _license [ ] SEC ( " license " ) = " GPL " ;
__u32 _version SEC ( " version " ) = 1 ; /* ignored by tracepoints, required by libbpf.a */