1 #include "util.h" 2 #include "../perf.h" 3 #include "cpumap.h" 4 #include <assert.h> 5 #include <stdio.h> 6 7 static struct cpu_map *cpu_map__default_new(void) 8 { 9 struct cpu_map *cpus; 10 int nr_cpus; 11 12 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 13 if (nr_cpus < 0) 14 return NULL; 15 16 cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int)); 17 if (cpus != NULL) { 18 int i; 19 for (i = 0; i < nr_cpus; ++i) 20 cpus->map[i] = i; 21 22 cpus->nr = nr_cpus; 23 } 24 25 return cpus; 26 } 27 28 static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) 29 { 30 size_t payload_size = nr_cpus * sizeof(int); 31 struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size); 32 33 if (cpus != NULL) { 34 cpus->nr = nr_cpus; 35 memcpy(cpus->map, tmp_cpus, payload_size); 36 } 37 38 return cpus; 39 } 40 41 struct cpu_map *cpu_map__read(FILE *file) 42 { 43 struct cpu_map *cpus = NULL; 44 int nr_cpus = 0; 45 int *tmp_cpus = NULL, *tmp; 46 int max_entries = 0; 47 int n, cpu, prev; 48 char sep; 49 50 sep = 0; 51 prev = -1; 52 for (;;) { 53 n = fscanf(file, "%u%c", &cpu, &sep); 54 if (n <= 0) 55 break; 56 if (prev >= 0) { 57 int new_max = nr_cpus + cpu - prev - 1; 58 59 if (new_max >= max_entries) { 60 max_entries = new_max + MAX_NR_CPUS / 2; 61 tmp = realloc(tmp_cpus, max_entries * sizeof(int)); 62 if (tmp == NULL) 63 goto out_free_tmp; 64 tmp_cpus = tmp; 65 } 66 67 while (++prev < cpu) 68 tmp_cpus[nr_cpus++] = prev; 69 } 70 if (nr_cpus == max_entries) { 71 max_entries += MAX_NR_CPUS; 72 tmp = realloc(tmp_cpus, max_entries * sizeof(int)); 73 if (tmp == NULL) 74 goto out_free_tmp; 75 tmp_cpus = tmp; 76 } 77 78 tmp_cpus[nr_cpus++] = cpu; 79 if (n == 2 && sep == '-') 80 prev = cpu; 81 else 82 prev = -1; 83 if (n == 1 || sep == '\n') 84 break; 85 } 86 87 if (nr_cpus > 0) 88 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); 89 else 90 cpus = cpu_map__default_new(); 91 out_free_tmp: 92 free(tmp_cpus); 93 return cpus; 94 } 95 96 static struct cpu_map *cpu_map__read_all_cpu_map(void) 97 { 98 struct cpu_map *cpus = NULL; 99 FILE *onlnf; 100 101 onlnf = fopen("/sys/devices/system/cpu/online", "r"); 102 if (!onlnf) 103 return cpu_map__default_new(); 104 105 cpus = cpu_map__read(onlnf); 106 fclose(onlnf); 107 return cpus; 108 } 109 110 struct cpu_map *cpu_map__new(const char *cpu_list) 111 { 112 struct cpu_map *cpus = NULL; 113 unsigned long start_cpu, end_cpu = 0; 114 char *p = NULL; 115 int i, nr_cpus = 0; 116 int *tmp_cpus = NULL, *tmp; 117 int max_entries = 0; 118 119 if (!cpu_list) 120 return cpu_map__read_all_cpu_map(); 121 122 if (!isdigit(*cpu_list)) 123 goto out; 124 125 while (isdigit(*cpu_list)) { 126 p = NULL; 127 start_cpu = strtoul(cpu_list, &p, 0); 128 if (start_cpu >= INT_MAX 129 || (*p != '\0' && *p != ',' && *p != '-')) 130 goto invalid; 131 132 if (*p == '-') { 133 cpu_list = ++p; 134 p = NULL; 135 end_cpu = strtoul(cpu_list, &p, 0); 136 137 if (end_cpu >= INT_MAX || (*p != '\0' && *p != ',')) 138 goto invalid; 139 140 if (end_cpu < start_cpu) 141 goto invalid; 142 } else { 143 end_cpu = start_cpu; 144 } 145 146 for (; start_cpu <= end_cpu; start_cpu++) { 147 /* check for duplicates */ 148 for (i = 0; i < nr_cpus; i++) 149 if (tmp_cpus[i] == (int)start_cpu) 150 goto invalid; 151 152 if (nr_cpus == max_entries) { 153 max_entries += MAX_NR_CPUS; 154 tmp = realloc(tmp_cpus, max_entries * sizeof(int)); 155 if (tmp == NULL) 156 goto invalid; 157 tmp_cpus = tmp; 158 } 159 tmp_cpus[nr_cpus++] = (int)start_cpu; 160 } 161 if (*p) 162 ++p; 163 164 cpu_list = p; 165 } 166 167 if (nr_cpus > 0) 168 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus); 169 else 170 cpus = cpu_map__default_new(); 171 invalid: 172 free(tmp_cpus); 173 out: 174 return cpus; 175 } 176 177 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) 178 { 179 int i; 180 size_t printed = fprintf(fp, "%d cpu%s: ", 181 map->nr, map->nr > 1 ? "s" : ""); 182 for (i = 0; i < map->nr; ++i) 183 printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]); 184 185 return printed + fprintf(fp, "\n"); 186 } 187 188 struct cpu_map *cpu_map__dummy_new(void) 189 { 190 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); 191 192 if (cpus != NULL) { 193 cpus->nr = 1; 194 cpus->map[0] = -1; 195 } 196 197 return cpus; 198 } 199 200 void cpu_map__delete(struct cpu_map *map) 201 { 202 free(map); 203 } 204