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