1 /**
2 * @file daemon/opd_events.c
3 * Event details for each counter
4 *
5 * @remark Copyright 2002, 2003 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author John Levon
9 * @author Philippe Elie
10 */
11
12 #include "config.h"
13
14 #include "opd_events.h"
15 #include "opd_printf.h"
16 #include "opd_extended.h"
17 #include "oprofiled.h"
18
19 #include "op_string.h"
20 #include "op_config.h"
21 #include "op_cpufreq.h"
22 #include "op_cpu_type.h"
23 #include "op_libiberty.h"
24 #include "op_hw_config.h"
25 #include "op_sample_file.h"
26
27 #include <stdlib.h>
28 #include <stdio.h>
29
30 extern op_cpu cpu_type;
31
32 struct opd_event opd_events[OP_MAX_COUNTERS];
33
34 static double cpu_speed;
35
malformed_events(void)36 static void malformed_events(void)
37 {
38 fprintf(stderr, "oprofiled: malformed events passed "
39 "on the command line\n");
40 exit(EXIT_FAILURE);
41 }
42
43
copy_token(char ** c,char delim)44 static char * copy_token(char ** c, char delim)
45 {
46 char * tmp = *c;
47 char * tmp2 = *c;
48 char * str;
49
50 if (!**c)
51 return NULL;
52
53 while (*tmp2 && *tmp2 != delim)
54 ++tmp2;
55
56 if (tmp2 == tmp)
57 return NULL;
58
59 str = op_xstrndup(tmp, tmp2 - tmp);
60 *c = tmp2;
61 if (**c)
62 ++*c;
63 return str;
64 }
65
66
copy_ulong(char ** c,char delim)67 static unsigned long copy_ulong(char ** c, char delim)
68 {
69 unsigned long val = 0;
70 char * str = copy_token(c, delim);
71 if (!str)
72 malformed_events();
73 val = strtoul(str, NULL, 0);
74 free(str);
75 return val;
76 }
77
78
opd_parse_events(char const * events)79 void opd_parse_events(char const * events)
80 {
81 char * ev = xstrdup(events);
82 char * c;
83 size_t cur = 0;
84
85 if (cpu_type == CPU_TIMER_INT) {
86 struct opd_event * event = &opd_events[0];
87 event->name = xstrdup("TIMER");
88 event->value = event->counter
89 = event->count = event->um = 0;
90 event->kernel = 1;
91 event->user = 1;
92 return;
93 }
94
95 if (!ev || !strlen(ev)) {
96 fprintf(stderr, "oprofiled: no events passed.\n");
97 exit(EXIT_FAILURE);
98 }
99
100 verbprintf(vmisc, "Events: %s\n", ev);
101
102 c = ev;
103
104 while (*c && cur < op_nr_counters) {
105 struct opd_event * event = &opd_events[cur];
106
107 if (!(event->name = copy_token(&c, ':')))
108 malformed_events();
109 event->value = copy_ulong(&c, ':');
110 event->counter = copy_ulong(&c, ':');
111 event->count = copy_ulong(&c, ':');
112 event->um = copy_ulong(&c, ':');
113 event->kernel = copy_ulong(&c, ':');
114 event->user = copy_ulong(&c, ',');
115 ++cur;
116 }
117
118 if (*c) {
119 fprintf(stderr, "oprofiled: too many events passed.\n");
120 exit(EXIT_FAILURE);
121 }
122
123 free(ev);
124
125 cpu_speed = op_cpu_frequency();
126 }
127
128
find_counter_event(unsigned long counter)129 struct opd_event * find_counter_event(unsigned long counter)
130 {
131 size_t i;
132 struct opd_event * ret = NULL;
133
134 if (counter >= OP_MAX_COUNTERS) {
135 if((ret = opd_ext_find_counter_event(counter)) != NULL)
136 return ret;
137 }
138
139 for (i = 0; i < op_nr_counters && opd_events[i].name; ++i) {
140 if (counter == opd_events[i].counter)
141 return &opd_events[i];
142 }
143
144 fprintf(stderr, "Unknown event for counter %lu\n", counter);
145 abort();
146 return NULL;
147 }
148
149
fill_header(struct opd_header * header,unsigned long counter,vma_t anon_start,vma_t cg_to_anon_start,int is_kernel,int cg_to_is_kernel,int spu_samples,uint64_t embed_offset,time_t mtime)150 void fill_header(struct opd_header * header, unsigned long counter,
151 vma_t anon_start, vma_t cg_to_anon_start,
152 int is_kernel, int cg_to_is_kernel,
153 int spu_samples, uint64_t embed_offset, time_t mtime)
154 {
155 struct opd_event * event = find_counter_event(counter);
156
157 memset(header, '\0', sizeof(struct opd_header));
158 header->version = OPD_VERSION;
159 memcpy(header->magic, OPD_MAGIC, sizeof(header->magic));
160 header->cpu_type = cpu_type;
161 header->ctr_event = event->value;
162 header->ctr_count = event->count;
163 header->ctr_um = event->um;
164 header->is_kernel = is_kernel;
165 header->cg_to_is_kernel = cg_to_is_kernel;
166 header->cpu_speed = cpu_speed;
167 header->mtime = mtime;
168 header->anon_start = anon_start;
169 header->spu_profile = spu_samples;
170 header->embedded_offset = embed_offset;
171 header->cg_to_anon_start = cg_to_anon_start;
172 }
173