xref: /aosp_15_r20/external/trace-cmd/lib/trace-cmd/trace-perf.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <[email protected]>
4  *
5  */
6 #include <unistd.h>
7 #include <sys/syscall.h>
8 #include <sys/mman.h>
9 
10 #include "trace-cmd-private.h"
11 
default_perf_init_pe(struct perf_event_attr * pe)12 static void default_perf_init_pe(struct perf_event_attr *pe)
13 {
14 	pe->type = PERF_TYPE_SOFTWARE;
15 	pe->sample_type = PERF_SAMPLE_CPU;
16 	pe->size = sizeof(struct perf_event_attr);
17 	pe->config = PERF_COUNT_HW_CPU_CYCLES;
18 	pe->disabled = 1;
19 	pe->exclude_kernel = 1;
20 	pe->freq = 1;
21 	pe->sample_freq = 1000;
22 	pe->inherit = 1;
23 	pe->mmap = 1;
24 	pe->comm = 1;
25 	pe->task = 1;
26 	pe->precise_ip = 1;
27 	pe->sample_id_all = 1;
28 	pe->read_format = PERF_FORMAT_ID |
29 			PERF_FORMAT_TOTAL_TIME_ENABLED |
30 			PERF_FORMAT_TOTAL_TIME_RUNNING;
31 }
32 
33 /**
34  * trace_perf_init - Initialize perf context
35  *
36  * @perf: structure, representing perf context, that will be initialized.
37  * @pages: Number of perf memory mapped pages.
38  * @cpu: CPU number, associated with this perf context.
39  * @pid: PID, associated with this perf context.
40  *
41  * The perf context in initialized with default values. The caller can set
42  * custom perf parameters in perf->pe, before calling trace_perf_open() API.
43  *
44  * Returns 0 on success, or -1 in case of an error.
45  *
46  */
trace_perf_init(struct trace_perf * perf,int pages,int cpu,int pid)47 int __hidden trace_perf_init(struct trace_perf *perf, int pages, int cpu, int pid)
48 {
49 	if (!perf)
50 		return -1;
51 
52 	memset(perf, 0, sizeof(struct trace_perf));
53 	default_perf_init_pe(&perf->pe);
54 	perf->cpu = cpu;
55 	perf->pages = pages;
56 	perf->pid = pid;
57 	perf->fd = -1;
58 
59 	return 0;
60 }
61 
62 /**
63  * trace_perf_close - Close perf session
64  *
65  * @perf: structure, representing context of a running perf session, opened
66  *	  with trace_perf_open()
67  *
68  */
trace_perf_close(struct trace_perf * perf)69 void __hidden trace_perf_close(struct trace_perf *perf)
70 {
71 	if (perf->fd >= 0)
72 		close(perf->fd);
73 	perf->fd = -1;
74 	if (perf->mmap && perf->mmap != MAP_FAILED)
75 		munmap(perf->mmap, (perf->pages + 1) * getpagesize());
76 	perf->mmap = NULL;
77 }
78 
79 /**
80  * trace_perf_open - Open perf session
81  *
82  * @perf: structure, representing perf context that will be opened. It must be
83  *	  initialized with trace_perf_init().
84  *
85  * Returns 0 on success, or -1 in case of an error. In case of success, the
86  * session must be closed with trace_perf_close()
87  */
trace_perf_open(struct trace_perf * perf)88 int __hidden trace_perf_open(struct trace_perf *perf)
89 {
90 	perf->fd = syscall(__NR_perf_event_open, &perf->pe, perf->pid, perf->cpu, -1, 0);
91 	if (perf->fd < 0)
92 		return -1;
93 	fcntl(perf->fd, F_SETFL, O_NONBLOCK);
94 
95 	perf->mmap = mmap(NULL, (perf->pages + 1) * getpagesize(),
96 			  PROT_READ | PROT_WRITE, MAP_SHARED, perf->fd, 0);
97 	if (perf->mmap == MAP_FAILED)
98 		goto error;
99 
100 	return 0;
101 
102 error:
103 	trace_perf_close(perf);
104 	return -1;
105 }
106