110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @file op_alloc_counter.c
310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * hardware counter allocation
410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * You can have silliness here.
610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Copyright 2002 OProfile authors
810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @remark Read the file COPYING
910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
1010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @author John Levon
1110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @author Philippe Elie
1210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
1310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <stdlib.h>
1510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <ctype.h>
1610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include <dirent.h>
1710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_events.h"
1910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project#include "op_libiberty.h"
2010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projecttypedef struct counter_arc_head {
2310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/** the head of allowed counter for this event */
2410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct list_head next;
2510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project} counter_arc_head;
2610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projecttypedef struct counter_arc {
2910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/** counter nr */
3010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int counter;
3110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/** the next counter allowed for this event */
3210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct list_head next;
3310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project} counter_arc;
3410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
3610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
3710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param pev  an array of event
3810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param nr_events  number of entry in pev
3910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
4010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * build an array of counter list allowed for each events
4110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *  counter_arc_head[i] is the list of allowed counter for pev[i] events
4210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * The returned pointer is an array of nr_events entry
4310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
4410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic counter_arc_head *
4510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectbuild_counter_arc(struct op_event const * pev[], int nr_events)
4610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
4710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	counter_arc_head * ctr_arc;
4810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int i;
4910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	ctr_arc = xmalloc(nr_events * sizeof(*ctr_arc));
5110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_events; ++i) {
5310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		int j;
5410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		u32 mask = pev[i]->counter_mask;
5510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
5610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		list_init(&ctr_arc[i].next);
5710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		for (j = 0; mask; ++j) {
5810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			if (mask & (1 << j)) {
5910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				counter_arc * arc =
6010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project					xmalloc(sizeof(counter_arc));
6110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				arc->counter = j;
6210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				/* we are looping by increasing counter number,
6310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				 * allocation use a left to right tree walking
6410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				 * so we add at end to ensure counter will
6510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				 * be allocated by increasing number: it's not
6610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				 * required but a bit less surprising when
6710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				 * debugging code
6810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				 */
6910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				list_add_tail(&arc->next, &ctr_arc[i].next);
7010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project				mask &= ~(1 << j);
7110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			}
7210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
7310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
7410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return ctr_arc;
7610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
7710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
7910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
8010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param ctr_arc  the array to deallocate
8110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param nr_events  number of entry in array
8210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
8310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *  deallocate all previously allocated resource by build_counter_arc()
8410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
8510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic void delete_counter_arc(counter_arc_head * ctr_arc, int nr_events)
8610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
8710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int i;
8810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i = 0; i < nr_events; ++i) {
8910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		struct list_head * pos, * pos2;
9010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		list_for_each_safe(pos, pos2, &ctr_arc[i].next) {
9110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			counter_arc * arc = list_entry(pos, counter_arc, next);
9210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			list_del(&arc->next);
9310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			free(arc);
9410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		}
9510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
9610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	free(ctr_arc);
9710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
9810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
9910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
10010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
10110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param ctr_arc  tree description, ctr_arc[i] is the i-th level of tree.
10210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param max_depth  number of entry in array ctr_arc == depth of tree
10310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param depth  current level we are exploring
10410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param allocated_mask  current counter already allocated mask
10510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param counter_map  array of counter number mapping, returned results go
10610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *   here
10710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
10810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * return non zero on succees, in this case counter_map is set to the counter
10910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * mapping number.
11010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
11110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Solution is searched through a simple backtracking exploring recursively all
11210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * possible solution until one is found, prunning is done in O(1) by tracking
11310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * a bitmask of already allocated counter. Walking through node is done in
11410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * preorder left to right.
11510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
1165a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng * In case of extended events (required no phisical counters), the associated
1175a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng * counter_map entry will be -1.
1185a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng *
11910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * Possible improvment if neccessary: partition counters in class of counter,
12010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * two counter belong to the same class if they allow exactly the same set of
12110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * event. Now using a variant of the backtrack algo can works on class of
12210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * counter rather on counter (this is not an improvment if each counter goes
12310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * in it's own class)
12410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
12510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic int
12610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectallocate_counter(counter_arc_head const * ctr_arc, int max_depth, int depth,
12710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		 u32 allocated_mask, size_t * counter_map)
12810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
12910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct list_head * pos;
13010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
13110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (depth == max_depth)
13210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return 1;
13310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1345a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	/* If ctr_arc is not available, counter_map is -1 */
1355a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	if((&ctr_arc[depth].next)->next == &ctr_arc[depth].next) {
1365a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		counter_map[depth] = -1;
13710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		if (allocate_counter(ctr_arc, max_depth, depth + 1,
1385a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		                     allocated_mask,
13910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		                     counter_map))
14010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			return 1;
1415a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	} else {
1425a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		list_for_each(pos, &ctr_arc[depth].next) {
1435a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			counter_arc const * arc = list_entry(pos, counter_arc, next);
1445a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng
1455a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			if (allocated_mask & (1 << arc->counter))
1465a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng				continue;
1475a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng
1485a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			counter_map[depth] = arc->counter;
1495a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng
1505a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			if (allocate_counter(ctr_arc, max_depth, depth + 1,
1515a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng					     allocated_mask | (1 << arc->counter),
1525a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng					     counter_map))
1535a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng				return 1;
1545a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		}
15510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
15610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
15710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return 0;
15810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
15910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/* determine which directories are counter directories
16110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
16210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic int perfcounterdir(const struct dirent * entry)
16310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
16410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return (isdigit(entry->d_name[0]));
16510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
16610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
16810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project/**
16910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * @param mask pointer where to place bit mask of unavailable counters
17010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
17110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project * return >= 0 number of counters that are available
17210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *        < 0  could not determine number of counters
17310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project *
17410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project */
17510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectstatic int op_get_counter_mask(u32 * mask)
17610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
17710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	struct dirent **counterlist;
17810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	int count, i;
17910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* assume nothing is available */
18010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	u32 available=0;
18110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
1825a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	count = scandir("/dev/oprofile", &counterlist, perfcounterdir,
1835a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			alphasort);
18410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (count < 0)
18510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		/* unable to determine bit mask */
18610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		return -1;
18710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* convert to bit map (0 where counter exists) */
18810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	for (i=0; i<count; ++i) {
18910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		available |= 1 << atoi(counterlist[i]->d_name);
19010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		free(counterlist[i]);
19110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
19210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	*mask=~available;
19310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	free(counterlist);
19410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return count;
19510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
19610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
19710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Projectsize_t * map_event_to_counter(struct op_event const * pev[], int nr_events,
19810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project                              op_cpu cpu_type)
19910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project{
20010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	counter_arc_head * ctr_arc;
20110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	size_t * counter_map;
2025a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	int i, nr_counters, nr_pmc_events;
2035a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	op_cpu curr_cpu_type;
20410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	u32 unavailable_counters = 0;
20510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2065a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	/* Either ophelp or one of the libop tests may invoke this
2075a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * function with a non-native cpu_type.  If so, we should not
2085a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * call op_get_counter_mask because that will look for real counter
2095a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 * information in oprofilefs.
2105a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	 */
2115a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	curr_cpu_type = op_get_cpu_type();
2125a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	if (cpu_type != curr_cpu_type)
2135a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		nr_counters = op_get_nr_counters(cpu_type);
2145a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	else
2155a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		nr_counters = op_get_counter_mask(&unavailable_counters);
2165a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng
21710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	/* no counters then probably perfmon managing perfmon hw */
21810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (nr_counters <= 0) {
21910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		nr_counters = op_get_nr_counters(cpu_type);
22010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		unavailable_counters = (~0) << nr_counters;
22110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
2225a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng
2235a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	/* Check to see if we have enough physical counters to map events*/
2245a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	for (i = 0, nr_pmc_events = 0; i < nr_events; i++)
2255a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng		if(pev[i]->ext == NULL)
2265a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng			if (++nr_pmc_events > nr_counters)
2275a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng				return 0;
22810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
22910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	ctr_arc = build_counter_arc(pev, nr_events);
23010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
2315a4eb4eb367eccd4b976d1feae96cea96d2c50f2Ben Cheng	counter_map = xmalloc(nr_events * sizeof(size_t));
23210e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23310e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	if (!allocate_counter(ctr_arc, nr_events, 0, unavailable_counters,
23410e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project			      counter_map)) {
23510e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		free(counter_map);
23610e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project		counter_map = 0;
23710e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	}
23810e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project
23910e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	delete_counter_arc(ctr_arc, nr_events);
24010e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project	return counter_map;
24110e23eebca4175a8dfe3a788b2bebacb1fcfce54The Android Open Source Project}
242