op_alloc_counter.c
Go to the documentation of this file.00001
00014 #include <stdlib.h>
00015 #include <ctype.h>
00016 #include <dirent.h>
00017
00018 #include "op_events.h"
00019 #include "op_libiberty.h"
00020
00021
00022 typedef struct counter_arc_head {
00024 struct list_head next;
00025 } counter_arc_head;
00026
00027
00028 typedef struct counter_arc {
00030 int counter;
00032 struct list_head next;
00033 } counter_arc;
00034
00035
00044 static counter_arc_head *
00045 build_counter_arc(struct op_event const * pev[], int nr_events)
00046 {
00047 counter_arc_head * ctr_arc;
00048 int i;
00049
00050 ctr_arc = xmalloc(nr_events * sizeof(*ctr_arc));
00051
00052 for (i = 0; i < nr_events; ++i) {
00053 int j;
00054 u32 mask = pev[i]->counter_mask;
00055
00056 list_init(&ctr_arc[i].next);
00057 for (j = 0; mask; ++j) {
00058 if (mask & (1 << j)) {
00059 counter_arc * arc =
00060 xmalloc(sizeof(counter_arc));
00061 arc->counter = j;
00062
00063
00064
00065
00066
00067
00068
00069 list_add_tail(&arc->next, &ctr_arc[i].next);
00070 mask &= ~(1 << j);
00071 }
00072 }
00073 }
00074
00075 return ctr_arc;
00076 }
00077
00078
00085 static void delete_counter_arc(counter_arc_head * ctr_arc, int nr_events)
00086 {
00087 int i;
00088 for (i = 0; i < nr_events; ++i) {
00089 struct list_head * pos, * pos2;
00090 list_for_each_safe(pos, pos2, &ctr_arc[i].next) {
00091 counter_arc * arc = list_entry(pos, counter_arc, next);
00092 list_del(&arc->next);
00093 free(arc);
00094 }
00095 }
00096 free(ctr_arc);
00097 }
00098
00099
00125 static int
00126 allocate_counter(counter_arc_head const * ctr_arc, int max_depth, int depth,
00127 u32 allocated_mask, size_t * counter_map)
00128 {
00129 struct list_head * pos;
00130
00131 if (depth == max_depth)
00132 return 1;
00133
00134
00135 if((&ctr_arc[depth].next)->next == &ctr_arc[depth].next) {
00136 counter_map[depth] = -1;
00137 if (allocate_counter(ctr_arc, max_depth, depth + 1,
00138 allocated_mask,
00139 counter_map))
00140 return 1;
00141 } else {
00142 list_for_each(pos, &ctr_arc[depth].next) {
00143 counter_arc const * arc = list_entry(pos, counter_arc, next);
00144
00145 if (allocated_mask & (1 << arc->counter))
00146 continue;
00147
00148 counter_map[depth] = arc->counter;
00149
00150 if (allocate_counter(ctr_arc, max_depth, depth + 1,
00151 allocated_mask | (1 << arc->counter),
00152 counter_map))
00153 return 1;
00154 }
00155 }
00156
00157 return 0;
00158 }
00159
00160
00161
00162 static int perfcounterdir(const struct dirent * entry)
00163 {
00164 return (isdigit(entry->d_name[0]));
00165 }
00166
00167
00175 static int op_get_counter_mask(u32 * mask)
00176 {
00177 struct dirent **counterlist;
00178 int count, i;
00179
00180 u32 available=0;
00181
00182 count = scandir("/dev/oprofile", &counterlist, perfcounterdir,
00183 alphasort);
00184 if (count < 0)
00185
00186 return -1;
00187
00188 for (i=0; i<count; ++i) {
00189 available |= 1 << atoi(counterlist[i]->d_name);
00190 free(counterlist[i]);
00191 }
00192
00193 if (op_cpu_has_timer_fs()) {
00194 available |= 1 << (op_get_nr_counters(op_get_cpu_type()) - 1);
00195 count++;
00196 }
00197 *mask=~available;
00198 free(counterlist);
00199 return count;
00200 }
00201
00202 size_t * map_event_to_counter(struct op_event const * pev[], int nr_events,
00203 op_cpu cpu_type)
00204 {
00205 counter_arc_head * ctr_arc;
00206 size_t * counter_map;
00207 int i, nr_counters, nr_pmc_events;
00208 op_cpu curr_cpu_type;
00209 u32 unavailable_counters = 0;
00210
00211
00212
00213
00214
00215
00216 curr_cpu_type = op_get_cpu_type();
00217 if (cpu_type != curr_cpu_type)
00218 nr_counters = op_get_nr_counters(cpu_type);
00219 else
00220 nr_counters = op_get_counter_mask(&unavailable_counters);
00221
00222
00223 if (nr_counters <= 0) {
00224 nr_counters = op_get_nr_counters(cpu_type);
00225 unavailable_counters = (~0) << nr_counters;
00226 }
00227
00228
00229 for (i = 0, nr_pmc_events = 0; i < nr_events; i++)
00230 if(pev[i]->ext == NULL)
00231 if (++nr_pmc_events > nr_counters)
00232 return 0;
00233
00234 ctr_arc = build_counter_arc(pev, nr_events);
00235
00236 counter_map = xmalloc(nr_events * sizeof(size_t));
00237
00238 if (!allocate_counter(ctr_arc, nr_events, 0, unavailable_counters,
00239 counter_map)) {
00240 free(counter_map);
00241 counter_map = 0;
00242 }
00243
00244 delete_counter_arc(ctr_arc, nr_events);
00245 return counter_map;
00246 }