cpumap.c 3.8 KB

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