|  | /** | 
|  | * @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; | 
|  | } |