2019-05-28 10:10:09 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2016-04-06 18:43:31 -07:00
/* Copyright (c) 2016 Facebook
*/
# define _GNU_SOURCE
# include <sched.h>
2018-07-04 22:36:38 +09:00
# include <errno.h>
2016-04-06 18:43:31 -07:00
# include <stdio.h>
# include <sys/types.h>
# include <asm/unistd.h>
# include <fcntl.h>
# include <unistd.h>
# include <assert.h>
# include <sys/wait.h>
# include <stdlib.h>
# include <signal.h>
# include <linux/bpf.h>
# include <string.h>
# include <time.h>
2018-05-14 22:35:02 -07:00
# include <bpf/bpf.h>
2020-11-24 09:03:08 +00:00
# include <bpf/libbpf.h>
2016-04-06 18:43:31 -07:00
# define MAX_CNT 1000000
2020-11-24 09:03:08 +00:00
static struct bpf_link * links [ 2 ] ;
static struct bpf_object * obj ;
static int cnt ;
2016-04-06 18:43:31 -07:00
static __u64 time_get_ns ( void )
{
struct timespec ts ;
clock_gettime ( CLOCK_MONOTONIC , & ts ) ;
return ts . tv_sec * 1000000000ull + ts . tv_nsec ;
}
static void test_task_rename ( int cpu )
{
__u64 start_time ;
char buf [ ] = " test \n " ;
int i , fd ;
fd = open ( " /proc/self/comm " , O_WRONLY | O_TRUNC ) ;
if ( fd < 0 ) {
printf ( " couldn't open /proc \n " ) ;
exit ( 1 ) ;
}
start_time = time_get_ns ( ) ;
2018-07-04 22:36:38 +09:00
for ( i = 0 ; i < MAX_CNT ; i + + ) {
if ( write ( fd , buf , sizeof ( buf ) ) < 0 ) {
printf ( " task rename failed: %s \n " , strerror ( errno ) ) ;
close ( fd ) ;
return ;
}
}
2016-04-06 18:43:31 -07:00
printf ( " task_rename:%d: %lld events per sec \n " ,
cpu , MAX_CNT * 1000000000ll / ( time_get_ns ( ) - start_time ) ) ;
close ( fd ) ;
}
static void test_urandom_read ( int cpu )
{
__u64 start_time ;
char buf [ 4 ] ;
int i , fd ;
fd = open ( " /dev/urandom " , O_RDONLY ) ;
if ( fd < 0 ) {
printf ( " couldn't open /dev/urandom \n " ) ;
exit ( 1 ) ;
}
start_time = time_get_ns ( ) ;
2018-07-04 22:36:38 +09:00
for ( i = 0 ; i < MAX_CNT ; i + + ) {
if ( read ( fd , buf , sizeof ( buf ) ) < 0 ) {
printf ( " failed to read from /dev/urandom: %s \n " , strerror ( errno ) ) ;
close ( fd ) ;
return ;
}
}
2016-04-06 18:43:31 -07:00
printf ( " urandom_read:%d: %lld events per sec \n " ,
cpu , MAX_CNT * 1000000000ll / ( time_get_ns ( ) - start_time ) ) ;
close ( fd ) ;
}
static void loop ( int cpu , int flags )
{
cpu_set_t cpuset ;
CPU_ZERO ( & cpuset ) ;
CPU_SET ( cpu , & cpuset ) ;
sched_setaffinity ( 0 , sizeof ( cpuset ) , & cpuset ) ;
if ( flags & 1 )
test_task_rename ( cpu ) ;
if ( flags & 2 )
test_urandom_read ( cpu ) ;
}
static void run_perf_test ( int tasks , int flags )
{
pid_t pid [ tasks ] ;
int i ;
for ( i = 0 ; i < tasks ; i + + ) {
pid [ i ] = fork ( ) ;
if ( pid [ i ] = = 0 ) {
loop ( i , flags ) ;
exit ( 0 ) ;
} else if ( pid [ i ] = = - 1 ) {
printf ( " couldn't spawn #%d process \n " , i ) ;
exit ( 1 ) ;
}
}
for ( i = 0 ; i < tasks ; i + + ) {
int status ;
assert ( waitpid ( pid [ i ] , & status , 0 ) = = pid [ i ] ) ;
assert ( status = = 0 ) ;
}
}
2020-11-24 09:03:08 +00:00
static int load_progs ( char * filename )
{
struct bpf_program * prog ;
int err = 0 ;
obj = bpf_object__open_file ( filename , NULL ) ;
err = libbpf_get_error ( obj ) ;
if ( err < 0 ) {
fprintf ( stderr , " ERROR: opening BPF object file failed \n " ) ;
return err ;
}
/* load BPF program */
err = bpf_object__load ( obj ) ;
if ( err < 0 ) {
fprintf ( stderr , " ERROR: loading BPF object file failed \n " ) ;
return err ;
}
bpf_object__for_each_program ( prog , obj ) {
links [ cnt ] = bpf_program__attach ( prog ) ;
err = libbpf_get_error ( links [ cnt ] ) ;
if ( err < 0 ) {
fprintf ( stderr , " ERROR: bpf_program__attach failed \n " ) ;
links [ cnt ] = NULL ;
return err ;
}
cnt + + ;
}
return err ;
}
2016-04-06 18:43:31 -07:00
static void unload_progs ( void )
{
2020-11-24 09:03:08 +00:00
while ( cnt )
bpf_link__destroy ( links [ - - cnt ] ) ;
bpf_object__close ( obj ) ;
2016-04-06 18:43:31 -07:00
}
int main ( int argc , char * * argv )
{
2020-11-24 09:03:08 +00:00
int num_cpu = sysconf ( _SC_NPROCESSORS_ONLN ) ;
2016-04-06 18:43:31 -07:00
int test_flags = ~ 0 ;
2020-11-24 09:03:08 +00:00
char filename [ 256 ] ;
int err = 0 ;
2016-04-06 18:43:31 -07:00
if ( argc > 1 )
test_flags = atoi ( argv [ 1 ] ) ? : test_flags ;
if ( argc > 2 )
num_cpu = atoi ( argv [ 2 ] ) ? : num_cpu ;
if ( test_flags & 0x3 ) {
printf ( " BASE \n " ) ;
run_perf_test ( num_cpu , test_flags ) ;
}
if ( test_flags & 0xC ) {
snprintf ( filename , sizeof ( filename ) ,
" %s_kprobe_kern.o " , argv [ 0 ] ) ;
2020-11-24 09:03:08 +00:00
2016-04-06 18:43:31 -07:00
printf ( " w/KPROBE \n " ) ;
2020-11-24 09:03:08 +00:00
err = load_progs ( filename ) ;
if ( ! err )
run_perf_test ( num_cpu , test_flags > > 2 ) ;
2016-04-06 18:43:31 -07:00
unload_progs ( ) ;
}
if ( test_flags & 0x30 ) {
snprintf ( filename , sizeof ( filename ) ,
" %s_tp_kern.o " , argv [ 0 ] ) ;
printf ( " w/TRACEPOINT \n " ) ;
2020-11-24 09:03:08 +00:00
err = load_progs ( filename ) ;
if ( ! err )
run_perf_test ( num_cpu , test_flags > > 4 ) ;
2016-04-06 18:43:31 -07:00
unload_progs ( ) ;
}
2018-03-28 12:05:39 -07:00
if ( test_flags & 0xC0 ) {
snprintf ( filename , sizeof ( filename ) ,
" %s_raw_tp_kern.o " , argv [ 0 ] ) ;
printf ( " w/RAW_TRACEPOINT \n " ) ;
2020-11-24 09:03:08 +00:00
err = load_progs ( filename ) ;
if ( ! err )
run_perf_test ( num_cpu , test_flags > > 6 ) ;
2018-03-28 12:05:39 -07:00
unload_progs ( ) ;
}
2020-11-24 09:03:08 +00:00
return err ;
2016-04-06 18:43:31 -07:00
}