• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <unistd.h>
2 #include <sys/syscall.h>
3 #include <sys/mman.h>
4 #include <signal.h>
5 #include <linux/perf_event.h>
6 
7 #include <tracefs.h>
8 
perf_init_pe(struct perf_event_attr * pe)9 static void perf_init_pe(struct perf_event_attr *pe)
10 {
11 	memset(pe, 0, sizeof(struct perf_event_attr));
12 	pe->type = PERF_TYPE_SOFTWARE;
13 	pe->sample_type = PERF_SAMPLE_CPU;
14 	pe->size = sizeof(struct perf_event_attr);
15 	pe->config = PERF_COUNT_HW_CPU_CYCLES;
16 	pe->disabled = 1;
17 	pe->exclude_kernel = 1;
18 	pe->freq = 1;
19 	pe->sample_freq = 1000;
20 	pe->inherit = 1;
21 	pe->mmap = 1;
22 	pe->comm = 1;
23 	pe->task = 1;
24 	pe->precise_ip = 1;
25 	pe->sample_id_all = 1;
26 	pe->read_format = PERF_FORMAT_ID |
27 			PERF_FORMAT_TOTAL_TIME_ENABLED|
28 			PERF_FORMAT_TOTAL_TIME_RUNNING;
29 
30 }
31 
perf_event_open(struct perf_event_attr * event,pid_t pid,int cpu,int group_fd,unsigned long flags)32 static long perf_event_open(struct perf_event_attr *event, pid_t pid,
33 			    int cpu, int group_fd, unsigned long flags)
34 {
35 	return syscall(__NR_perf_event_open, event, pid, cpu, group_fd, flags);
36 }
37 
38 #define MAP_SIZE (9 * getpagesize())
39 
perf_mmap(int fd)40 static struct perf_event_mmap_page *perf_mmap(int fd)
41 {
42 	struct perf_event_mmap_page *perf_mmap;
43 
44 	/* associate a buffer with the file */
45 	perf_mmap = mmap(NULL, MAP_SIZE,
46 			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
47 	if (perf_mmap == MAP_FAILED)
48 		return NULL;
49 
50 	return perf_mmap;
51 }
52 
perf_read_maps(int cpu,int * shift,int * mult,long long * offset)53 static int perf_read_maps(int cpu, int *shift, int *mult, long long *offset)
54 {
55 	struct perf_event_attr perf_attr;
56 	struct perf_event_mmap_page *mpage;
57 	int fd;
58 
59 	/* We succeed if theres' nothing to do! */
60 	if (!shift && !mult && !offset)
61 		return 0;
62 
63 	perf_init_pe(&perf_attr);
64 	fd = perf_event_open(&perf_attr, getpid(), cpu, -1, 0);
65 	if (fd < 0)
66 		return -1;
67 
68 	mpage = perf_mmap(fd);
69 	if (!mpage) {
70 		close(fd);
71 		return -1;
72 	}
73 
74 	if (shift)
75 		*shift = mpage->time_shift;
76 	if (mult)
77 		*mult = mpage->time_mult;
78 	if (offset)
79 		*offset = mpage->time_offset;
80 	munmap(mpage, MAP_SIZE);
81 	return 0;
82 }
83 
84 /**
85  * tracefs_time_conversion - Find how the kernel converts the raw counters
86  * @cpu: The CPU to check for
87  * @shift: If non-NULL it will be set to the shift value
88  * @mult: If non-NULL it will be set to the multiplier value
89  * @offset: If non-NULL it will be set to the offset
90  */
tracefs_time_conversion(int cpu,int * shift,int * mult,long long * offset)91 int tracefs_time_conversion(int cpu, int *shift, int *mult, long long *offset)
92 {
93 	return perf_read_maps(cpu, shift, mult, offset);
94 }
95