opd_events.c revision 5a4eb4eb367eccd4b976d1feae96cea96d2c50f2
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
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 "
39		"on the command line\n");
40	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;
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
150void 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