blob: b544fb32c1623730d877bec782c16bf29a62c992 [file] [log] [blame]
The Android Open Source Project10e23ee2009-03-03 19:30:30 -08001/**
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"
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070016#include "opd_extended.h"
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080017#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
30extern op_cpu cpu_type;
31
32struct opd_event opd_events[OP_MAX_COUNTERS];
33
34static double cpu_speed;
35
36static void malformed_events(void)
37{
38 fprintf(stderr, "oprofiled: malformed events passed "
Ben Cheng5a4eb4e2009-09-14 16:00:41 -070039 "on the command line\n");
The Android Open Source Project10e23ee2009-03-03 19:30:30 -080040 exit(EXIT_FAILURE);
41}
42
43
44static 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
67static 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
79void 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
129struct opd_event * find_counter_event(unsigned long counter)
130{
131 size_t i;
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700132 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 }
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800138
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
150void fill_header(struct opd_header * header, unsigned long counter,
Ben Cheng5a4eb4e2009-09-14 16:00:41 -0700151 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)
The Android Open Source Project10e23ee2009-03-03 19:30:30 -0800154{
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}