| /** |
| * @file daemon/opd_events.c |
| * Event details for each counter |
| * |
| * @remark Copyright 2002, 2003 OProfile authors |
| * @remark Read the file COPYING |
| * |
| * @author John Levon |
| * @author Philippe Elie |
| */ |
| |
| #include "config.h" |
| |
| #include "opd_events.h" |
| #include "opd_printf.h" |
| #include "opd_extended.h" |
| #include "oprofiled.h" |
| |
| #include "op_string.h" |
| #include "op_config.h" |
| #include "op_cpufreq.h" |
| #include "op_cpu_type.h" |
| #include "op_libiberty.h" |
| #include "op_hw_config.h" |
| #include "op_sample_file.h" |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| |
| extern op_cpu cpu_type; |
| |
| struct opd_event opd_events[OP_MAX_COUNTERS]; |
| |
| static double cpu_speed; |
| |
| static void malformed_events(void) |
| { |
| fprintf(stderr, "oprofiled: malformed events passed " |
| "on the command line\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| |
| static char * copy_token(char ** c, char delim) |
| { |
| char * tmp = *c; |
| char * tmp2 = *c; |
| char * str; |
| |
| if (!**c) |
| return NULL; |
| |
| while (*tmp2 && *tmp2 != delim) |
| ++tmp2; |
| |
| if (tmp2 == tmp) |
| return NULL; |
| |
| str = op_xstrndup(tmp, tmp2 - tmp); |
| *c = tmp2; |
| if (**c) |
| ++*c; |
| return str; |
| } |
| |
| |
| static unsigned long copy_ulong(char ** c, char delim) |
| { |
| unsigned long val = 0; |
| char * str = copy_token(c, delim); |
| if (!str) |
| malformed_events(); |
| val = strtoul(str, NULL, 0); |
| free(str); |
| return val; |
| } |
| |
| |
| void opd_parse_events(char const * events) |
| { |
| char * ev = xstrdup(events); |
| char * c; |
| size_t cur = 0; |
| |
| if (cpu_type == CPU_TIMER_INT) { |
| struct opd_event * event = &opd_events[0]; |
| event->name = xstrdup("TIMER"); |
| event->value = event->counter |
| = event->count = event->um = 0; |
| event->kernel = 1; |
| event->user = 1; |
| return; |
| } |
| |
| if (!ev || !strlen(ev)) { |
| fprintf(stderr, "oprofiled: no events passed.\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| verbprintf(vmisc, "Events: %s\n", ev); |
| |
| c = ev; |
| |
| while (*c && cur < op_nr_counters) { |
| struct opd_event * event = &opd_events[cur]; |
| |
| if (!(event->name = copy_token(&c, ':'))) |
| malformed_events(); |
| event->value = copy_ulong(&c, ':'); |
| event->counter = copy_ulong(&c, ':'); |
| event->count = copy_ulong(&c, ':'); |
| event->um = copy_ulong(&c, ':'); |
| event->kernel = copy_ulong(&c, ':'); |
| event->user = copy_ulong(&c, ','); |
| ++cur; |
| } |
| |
| if (*c) { |
| fprintf(stderr, "oprofiled: too many events passed.\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| free(ev); |
| |
| cpu_speed = op_cpu_frequency(); |
| } |
| |
| |
| struct opd_event * find_counter_event(unsigned long counter) |
| { |
| size_t i; |
| struct opd_event * ret = NULL; |
| |
| if (counter >= OP_MAX_COUNTERS) { |
| if((ret = opd_ext_find_counter_event(counter)) != NULL) |
| return ret; |
| } |
| |
| for (i = 0; i < op_nr_counters && opd_events[i].name; ++i) { |
| if (counter == opd_events[i].counter) |
| return &opd_events[i]; |
| } |
| |
| fprintf(stderr, "Unknown event for counter %lu\n", counter); |
| abort(); |
| return NULL; |
| } |
| |
| |
| void 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) |
| { |
| struct opd_event * event = find_counter_event(counter); |
| |
| memset(header, '\0', sizeof(struct opd_header)); |
| header->version = OPD_VERSION; |
| memcpy(header->magic, OPD_MAGIC, sizeof(header->magic)); |
| header->cpu_type = cpu_type; |
| header->ctr_event = event->value; |
| header->ctr_count = event->count; |
| header->ctr_um = event->um; |
| header->is_kernel = is_kernel; |
| header->cg_to_is_kernel = cg_to_is_kernel; |
| header->cpu_speed = cpu_speed; |
| header->mtime = mtime; |
| header->anon_start = anon_start; |
| header->spu_profile = spu_samples; |
| header->embedded_offset = embed_offset; |
| header->cg_to_anon_start = cg_to_anon_start; |
| } |