]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - tools/perf/util/cpumap.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / tools / perf / util / cpumap.c
index 0f9b8d7a7d7e7d62f38c48ec8846251beb532918..3ccaa10433830503325bb7625527839f4586b93e 100644 (file)
@@ -4,32 +4,53 @@
 #include <assert.h>
 #include <stdio.h>
 
-int cpumap[MAX_NR_CPUS];
-
-static int default_cpu_map(void)
+static struct cpu_map *cpu_map__default_new(void)
 {
-       int nr_cpus, i;
+       struct cpu_map *cpus;
+       int nr_cpus;
 
        nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
-       assert(nr_cpus <= MAX_NR_CPUS);
-       assert((int)nr_cpus >= 0);
+       if (nr_cpus < 0)
+               return NULL;
+
+       cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
+       if (cpus != NULL) {
+               int i;
+               for (i = 0; i < nr_cpus; ++i)
+                       cpus->map[i] = i;
 
-       for (i = 0; i < nr_cpus; ++i)
-               cpumap[i] = i;
+               cpus->nr = nr_cpus;
+       }
 
-       return nr_cpus;
+       return cpus;
 }
 
-static int read_all_cpu_map(void)
+static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 {
+       size_t payload_size = nr_cpus * sizeof(int);
+       struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
+
+       if (cpus != NULL) {
+               cpus->nr = nr_cpus;
+               memcpy(cpus->map, tmp_cpus, payload_size);
+       }
+
+       return cpus;
+}
+
+static struct cpu_map *cpu_map__read_all_cpu_map(void)
+{
+       struct cpu_map *cpus = NULL;
        FILE *onlnf;
        int nr_cpus = 0;
+       int *tmp_cpus = NULL, *tmp;
+       int max_entries = 0;
        int n, cpu, prev;
        char sep;
 
        onlnf = fopen("/sys/devices/system/cpu/online", "r");
        if (!onlnf)
-               return default_cpu_map();
+               return cpu_map__default_new();
 
        sep = 0;
        prev = -1;
@@ -38,12 +59,28 @@ static int read_all_cpu_map(void)
                if (n <= 0)
                        break;
                if (prev >= 0) {
-                       assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS);
+                       int new_max = nr_cpus + cpu - prev - 1;
+
+                       if (new_max >= max_entries) {
+                               max_entries = new_max + MAX_NR_CPUS / 2;
+                               tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+                               if (tmp == NULL)
+                                       goto out_free_tmp;
+                               tmp_cpus = tmp;
+                       }
+
                        while (++prev < cpu)
-                               cpumap[nr_cpus++] = prev;
+                               tmp_cpus[nr_cpus++] = prev;
+               }
+               if (nr_cpus == max_entries) {
+                       max_entries += MAX_NR_CPUS;
+                       tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+                       if (tmp == NULL)
+                               goto out_free_tmp;
+                       tmp_cpus = tmp;
                }
-               assert (nr_cpus < MAX_NR_CPUS);
-               cpumap[nr_cpus++] = cpu;
+
+               tmp_cpus[nr_cpus++] = cpu;
                if (n == 2 && sep == '-')
                        prev = cpu;
                else
@@ -51,24 +88,31 @@ static int read_all_cpu_map(void)
                if (n == 1 || sep == '\n')
                        break;
        }
-       fclose(onlnf);
-       if (nr_cpus > 0)
-               return nr_cpus;
 
-       return default_cpu_map();
+       if (nr_cpus > 0)
+               cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
+       else
+               cpus = cpu_map__default_new();
+out_free_tmp:
+       free(tmp_cpus);
+       fclose(onlnf);
+       return cpus;
 }
 
-int read_cpu_map(const char *cpu_list)
+struct cpu_map *cpu_map__new(const char *cpu_list)
 {
+       struct cpu_map *cpus = NULL;
        unsigned long start_cpu, end_cpu = 0;
        char *p = NULL;
        int i, nr_cpus = 0;
+       int *tmp_cpus = NULL, *tmp;
+       int max_entries = 0;
 
        if (!cpu_list)
-               return read_all_cpu_map();
+               return cpu_map__read_all_cpu_map();
 
        if (!isdigit(*cpu_list))
-               goto invalid;
+               goto out;
 
        while (isdigit(*cpu_list)) {
                p = NULL;
@@ -94,21 +138,42 @@ int read_cpu_map(const char *cpu_list)
                for (; start_cpu <= end_cpu; start_cpu++) {
                        /* check for duplicates */
                        for (i = 0; i < nr_cpus; i++)
-                               if (cpumap[i] == (int)start_cpu)
+                               if (tmp_cpus[i] == (int)start_cpu)
                                        goto invalid;
 
-                       assert(nr_cpus < MAX_NR_CPUS);
-                       cpumap[nr_cpus++] = (int)start_cpu;
+                       if (nr_cpus == max_entries) {
+                               max_entries += MAX_NR_CPUS;
+                               tmp = realloc(tmp_cpus, max_entries * sizeof(int));
+                               if (tmp == NULL)
+                                       goto invalid;
+                               tmp_cpus = tmp;
+                       }
+                       tmp_cpus[nr_cpus++] = (int)start_cpu;
                }
                if (*p)
                        ++p;
 
                cpu_list = p;
        }
-       if (nr_cpus > 0)
-               return nr_cpus;
 
-       return default_cpu_map();
+       if (nr_cpus > 0)
+               cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
+       else
+               cpus = cpu_map__default_new();
 invalid:
-       return -1;
+       free(tmp_cpus);
+out:
+       return cpus;
+}
+
+struct cpu_map *cpu_map__dummy_new(void)
+{
+       struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
+
+       if (cpus != NULL) {
+               cpus->nr = 1;
+               cpus->map[0] = -1;
+       }
+
+       return cpus;
 }