Home | History | Annotate | Download | only in daemon
      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 
     30 extern op_cpu cpu_type;
     31 
     32 struct opd_event opd_events[OP_MAX_COUNTERS];
     33 
     34 static double cpu_speed;
     35 
     36 static 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 
     44 static 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 
     67 static 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 
     79 void 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 
    129 struct 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 
    150 void 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