cpumap.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. static struct cpu_map *cpu_map__read_all_cpu_map(void)
  33. {
  34. struct cpu_map *cpus = NULL;
  35. FILE *onlnf;
  36. int nr_cpus = 0;
  37. int *tmp_cpus = NULL, *tmp;
  38. int max_entries = 0;
  39. int n, cpu, prev;
  40. char sep;
  41. onlnf = fopen("/sys/devices/system/cpu/online", "r");
  42. if (!onlnf)
  43. return cpu_map__default_new();
  44. sep = 0;
  45. prev = -1;
  46. for (;;) {
  47. n = fscanf(onlnf, "%u%c", &cpu, &sep);
  48. if (n <= 0)
  49. break;
  50. if (prev >= 0) {
  51. int new_max = nr_cpus + cpu - prev - 1;
  52. if (new_max >= max_entries) {
  53. max_entries = new_max + MAX_NR_CPUS / 2;
  54. tmp = realloc(tmp_cpus, max_entries * sizeof(int));
  55. if (tmp == NULL)
  56. goto out_free_tmp;
  57. tmp_cpus = tmp;
  58. }
  59. while (++prev < cpu)
  60. tmp_cpus[nr_cpus++] = prev;
  61. }
  62. if (nr_cpus == max_entries) {
  63. max_entries += MAX_NR_CPUS;
  64. tmp = realloc(tmp_cpus, max_entries * sizeof(int));
  65. if (tmp == NULL)
  66. goto out_free_tmp;
  67. tmp_cpus = tmp;
  68. }
  69. tmp_cpus[nr_cpus++] = cpu;
  70. if (n == 2 && sep == '-')
  71. prev = cpu;
  72. else
  73. prev = -1;
  74. if (n == 1 || sep == '\n')
  75. break;
  76. }
  77. if (nr_cpus > 0)
  78. cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
  79. else
  80. cpus = cpu_map__default_new();
  81. out_free_tmp:
  82. free(tmp_cpus);
  83. fclose(onlnf);
  84. return cpus;
  85. }
  86. struct cpu_map *cpu_map__new(const char *cpu_list)
  87. {
  88. struct cpu_map *cpus = NULL;
  89. unsigned long start_cpu, end_cpu = 0;
  90. char *p = NULL;
  91. int i, nr_cpus = 0;
  92. int *tmp_cpus = NULL, *tmp;
  93. int max_entries = 0;
  94. if (!cpu_list)
  95. return cpu_map__read_all_cpu_map();
  96. if (!isdigit(*cpu_list))
  97. goto out;
  98. while (isdigit(*cpu_list)) {
  99. p = NULL;
  100. start_cpu = strtoul(cpu_list, &p, 0);
  101. if (start_cpu >= INT_MAX
  102. || (*p != '\0' && *p != ',' && *p != '-'))
  103. goto invalid;
  104. if (*p == '-') {
  105. cpu_list = ++p;
  106. p = NULL;
  107. end_cpu = strtoul(cpu_list, &p, 0);
  108. if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
  109. goto invalid;
  110. if (end_cpu < start_cpu)
  111. goto invalid;
  112. } else {
  113. end_cpu = start_cpu;
  114. }
  115. for (; start_cpu <= end_cpu; start_cpu++) {
  116. /* check for duplicates */
  117. for (i = 0; i < nr_cpus; i++)
  118. if (tmp_cpus[i] == (int)start_cpu)
  119. goto invalid;
  120. if (nr_cpus == max_entries) {
  121. max_entries += MAX_NR_CPUS;
  122. tmp = realloc(tmp_cpus, max_entries * sizeof(int));
  123. if (tmp == NULL)
  124. goto invalid;
  125. tmp_cpus = tmp;
  126. }
  127. tmp_cpus[nr_cpus++] = (int)start_cpu;
  128. }
  129. if (*p)
  130. ++p;
  131. cpu_list = p;
  132. }
  133. if (nr_cpus > 0)
  134. cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
  135. else
  136. cpus = cpu_map__default_new();
  137. invalid:
  138. free(tmp_cpus);
  139. out:
  140. return cpus;
  141. }
  142. struct cpu_map *cpu_map__dummy_new(void)
  143. {
  144. struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
  145. if (cpus != NULL) {
  146. cpus->nr = 1;
  147. cpus->map[0] = -1;
  148. }
  149. return cpus;
  150. }
  151. void cpu_map__delete(struct cpu_map *map)
  152. {
  153. free(map);
  154. }