2121#include "libbpf.h"
2222#include "bpf_load.h"
2323#include "perf-sys.h"
24+ #include "trace_helpers.h"
2425
2526static int pmu_fd ;
2627
27- int page_size ;
28- int page_cnt = 8 ;
29- volatile struct perf_event_mmap_page * header ;
30-
31- typedef void (* print_fn )(void * data , int size );
32-
33- static int perf_event_mmap (int fd )
34- {
35- void * base ;
36- int mmap_size ;
37-
38- page_size = getpagesize ();
39- mmap_size = page_size * (page_cnt + 1 );
40-
41- base = mmap (NULL , mmap_size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 );
42- if (base == MAP_FAILED ) {
43- printf ("mmap err\n" );
44- return -1 ;
45- }
46-
47- header = base ;
48- return 0 ;
49- }
50-
51- static int perf_event_poll (int fd )
52- {
53- struct pollfd pfd = { .fd = fd , .events = POLLIN };
54-
55- return poll (& pfd , 1 , 1000 );
56- }
57-
58- struct perf_event_sample {
59- struct perf_event_header header ;
60- __u32 size ;
61- char data [];
62- };
63-
64- static void perf_event_read (print_fn fn )
65- {
66- __u64 data_tail = header -> data_tail ;
67- __u64 data_head = header -> data_head ;
68- __u64 buffer_size = page_cnt * page_size ;
69- void * base , * begin , * end ;
70- char buf [256 ];
71-
72- asm volatile ("" ::: "memory" ); /* in real code it should be smp_rmb() */
73- if (data_head == data_tail )
74- return ;
75-
76- base = ((char * )header ) + page_size ;
77-
78- begin = base + data_tail % buffer_size ;
79- end = base + data_head % buffer_size ;
80-
81- while (begin != end ) {
82- struct perf_event_sample * e ;
83-
84- e = begin ;
85- if (begin + e -> header .size > base + buffer_size ) {
86- long len = base + buffer_size - begin ;
87-
88- assert (len < e -> header .size );
89- memcpy (buf , begin , len );
90- memcpy (buf + len , base , e -> header .size - len );
91- e = (void * ) buf ;
92- begin = base + e -> header .size - len ;
93- } else if (begin + e -> header .size == base + buffer_size ) {
94- begin = base ;
95- } else {
96- begin += e -> header .size ;
97- }
98-
99- if (e -> header .type == PERF_RECORD_SAMPLE ) {
100- fn (e -> data , e -> size );
101- } else if (e -> header .type == PERF_RECORD_LOST ) {
102- struct {
103- struct perf_event_header header ;
104- __u64 id ;
105- __u64 lost ;
106- } * lost = (void * ) e ;
107- printf ("lost %lld events\n" , lost -> lost );
108- } else {
109- printf ("unknown event type=%d size=%d\n" ,
110- e -> header .type , e -> header .size );
111- }
112- }
113-
114- __sync_synchronize (); /* smp_mb() */
115- header -> data_tail = data_head ;
116- }
117-
11828static __u64 time_get_ns (void )
11929{
12030 struct timespec ts ;
@@ -127,7 +37,7 @@ static __u64 start_time;
12737
12838#define MAX_CNT 100000ll
12939
130- static void print_bpf_output (void * data , int size )
40+ static int print_bpf_output (void * data , int size )
13141{
13242 static __u64 cnt ;
13343 struct {
@@ -138,16 +48,18 @@ static void print_bpf_output(void *data, int size)
13848 if (e -> cookie != 0x12345678 ) {
13949 printf ("BUG pid %llx cookie %llx sized %d\n" ,
14050 e -> pid , e -> cookie , size );
141- kill ( 0 , SIGINT ) ;
51+ return PERF_EVENT_ERROR ;
14252 }
14353
14454 cnt ++ ;
14555
14656 if (cnt == MAX_CNT ) {
14757 printf ("recv %lld events per sec\n" ,
14858 MAX_CNT * 1000000000ll / (time_get_ns () - start_time ));
149- kill ( 0 , SIGINT ) ;
59+ return PERF_EVENT_DONE ;
15060 }
61+
62+ return PERF_EVENT_CONT ;
15163}
15264
15365static void test_bpf_perf_event (void )
@@ -170,6 +82,7 @@ int main(int argc, char **argv)
17082{
17183 char filename [256 ];
17284 FILE * f ;
85+ int ret ;
17386
17487 snprintf (filename , sizeof (filename ), "%s_kern.o" , argv [0 ]);
17588
@@ -187,10 +100,7 @@ int main(int argc, char **argv)
187100 (void ) f ;
188101
189102 start_time = time_get_ns ();
190- for (;;) {
191- perf_event_poll (pmu_fd );
192- perf_event_read (print_bpf_output );
193- }
194-
195- return 0 ;
103+ ret = perf_event_poller (pmu_fd , print_bpf_output );
104+ kill (0 , SIGINT );
105+ return ret ;
196106}
0 commit comments