static void do_test(struct allocated_counter const * it) { size_t i; size_t * counter_map; size_t nr_events; struct parsed_event parsed[MAX_EVENTS]; struct op_event const * event[MAX_EVENTS]; op_events(it->cpu_type); nr_events = parse_events(parsed, MAX_EVENTS, it->events); for (i = 0; i < nr_events; ++i) { event[i] = find_event_by_name(parsed[i].name, parsed[i].unit_mask, parsed[i].unit_mask_valid); if (!event[i]) { if (it->failure == fail_to_find_event) goto free_events; printf("Can't find events %s for cpu %s\n", parsed[i].name, op_get_cpu_type_str(it->cpu_type)); exit(EXIT_FAILURE); } } counter_map = map_event_to_counter(event, nr_events, it->cpu_type); if (!counter_map) { if (it->failure == fail_to_alloc_counter) goto free_events; printf("Can't map this set of events to counter:\n"); show_events(it->events); exit(EXIT_FAILURE); } for (i = 0; i < nr_events; ++i) { if (counter_map[i] != it->alloc_map[i]) { printf("Incorrect allocation map for these events:\n"); show_events(it->events); printf("(expect, found):\n"); show_counter_map(it->alloc_map, nr_events); show_counter_map(counter_map, nr_events); exit(EXIT_FAILURE); } } if (it->failure != no_failure) { /* test should fail but success! */ printf("test should fail with a failure type %d but succeed " "for events:\n", it->failure); for (i = 0; i < nr_events; ++i) printf("%s\n", it->events[i]); exit(EXIT_FAILURE); } free(counter_map); free_events: op_free_events(); }
static void resolve_events(void) { size_t count; size_t i, j; size_t * counter_map; size_t nr_counters = op_get_nr_counters(cpu_type); struct op_event const * selected_events[nr_counters]; count = parse_events(parsed_events, nr_counters, chosen_events); if (count > nr_counters) { fprintf(stderr, "Not enough hardware counters.\n"); exit(EXIT_FAILURE); } for (i = 0; i < count; ++i) { for (j = i + 1; j < count; ++j) { struct parsed_event * pev1 = &parsed_events[i]; struct parsed_event * pev2 = &parsed_events[j]; if (!strcmp(pev1->name, pev2->name) && pev1->count == pev2->count && pev1->unit_mask == pev2->unit_mask && pev1->kernel == pev2->kernel && pev1->user == pev2->user) { fprintf(stderr, "All events must be distinct.\n"); exit(EXIT_FAILURE); } } } for (i = 0; i < count; ++i) { struct parsed_event * pev = &parsed_events[i]; selected_events[i] = find_event_by_name(pev->name); check_event(pev, selected_events[i]); } counter_map = map_event_to_counter(selected_events, count, cpu_type); if (!counter_map) { fprintf(stderr, "Couldn't allocate hardware counters for the selected events.\n"); exit(EXIT_FAILURE); } for (i = 0; i < count; ++i) { printf("%d ", (unsigned int) counter_map[i]); } printf("\n"); free(counter_map); }
static void check_event(struct parsed_event * pev, struct op_event const * event) { int ret; int min_count; int const callgraph_min_count_scale = 15; if (!event) { event = find_event_by_name(pev->name, 0, 0); if (event) fprintf(stderr, "Invalid unit mask %x for event %s\n", pev->unit_mask, pev->name); else fprintf(stderr, "No event named %s is available.\n", pev->name); exit(EXIT_FAILURE); } op_resolve_unit_mask(pev, NULL); // If a named UM is passed, op_resolve_unit_mask will resolve that into a // valid unit mask, so we don't need to call op_check_events. if (pev->unit_mask_name) ret = 0; else ret = op_check_events(0, event->val, pev->unit_mask, cpu_type); if (ret & OP_INVALID_UM) { fprintf(stderr, "Invalid unit mask 0x%x for event %s\n", pev->unit_mask, pev->name); exit(EXIT_FAILURE); } min_count = event->min_count; if (callgraph_depth) min_count *= callgraph_min_count_scale; if (!ignore_count && pev->count < min_count) { fprintf(stderr, "Count %d for event %s is below the " "minimum %d\n", pev->count, pev->name, min_count); exit(EXIT_FAILURE); } }
static void show_unit_mask(void) { struct op_event * event; size_t count; size_t nr_counter = op_get_nr_counters(cpu_type); count = parse_events(parsed_events, nr_counter, chosen_events); if (count > 1) { fprintf(stderr, "More than one event specified.\n"); exit(EXIT_FAILURE); } event = find_event_by_name(parsed_events[0].name); if (!event) { fprintf(stderr, "No such event found.\n"); exit(EXIT_FAILURE); } printf("%d\n", event->unit->default_mask); }
static void resolve_events(void) { size_t count, count_events; size_t i, j; size_t * counter_map; size_t nr_counters = op_get_nr_counters(cpu_type); struct op_event const * selected_events[num_chosen_events]; count = parse_events(parsed_events, num_chosen_events, chosen_events, ignore_count ? 0 : 1); for (i = 0; i < count; ++i) { op_resolve_unit_mask(&parsed_events[i], NULL); for (j = i + 1; j < count; ++j) { struct parsed_event * pev1 = &parsed_events[i]; struct parsed_event * pev2 = &parsed_events[j]; if (!strcmp(pev1->name, pev2->name) && pev1->count == pev2->count && pev1->unit_mask == pev2->unit_mask && pev1->kernel == pev2->kernel && pev1->user == pev2->user) { fprintf(stderr, "All events must be distinct.\n"); exit(EXIT_FAILURE); } } } for (i = 0, count_events = 0; i < count; ++i) { struct parsed_event * pev = &parsed_events[i]; /* For 0 unit mask always do wild card match */ selected_events[i] = find_event_by_name(pev->name, pev->unit_mask, pev->unit_mask ? pev->unit_mask_valid : 0); check_event(pev, selected_events[i]); if (selected_events[i]->ext == NULL) { count_events++; } } if (count_events > nr_counters) { fprintf(stderr, "Not enough hardware counters. " "Need %lu counters but only has %lu.\n", (unsigned long) count_events, (unsigned long) nr_counters); exit(EXIT_FAILURE); } counter_map = map_event_to_counter(selected_events, count, cpu_type); if (!counter_map) { fprintf(stderr, "Couldn't allocate hardware counters for the selected events.\n"); exit(EXIT_FAILURE); } for (i = 0; i < count; ++i) if(counter_map[i] == (size_t)-1) if (selected_events[i]->ext != NULL) printf("%s ", (char*) selected_events[i]->ext); else printf("N/A "); else if (strcmp(selected_events[i]->name, TIMER_EVENT_NAME) == 0) printf("timer "); else printf("%d ", (unsigned int) counter_map[i]); printf("\n"); free(counter_map); }