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