pxm.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* pxm.c
  2. * Parse manual proximity config.
  3. */
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <strings.h>
  8. #include <sys/types.h>
  9. #include <dirent.h>
  10. #include <limits.h>
  11. #include <ctype.h>
  12. #include "lub/list.h"
  13. #include "numa.h"
  14. #include "pxm.h"
  15. static pxm_t * pxm_new(const char *addr)
  16. {
  17. pxm_t *new;
  18. if (!(new = malloc(sizeof(*new))))
  19. return NULL;
  20. new->addr = strdup(addr);
  21. cpus_clear(new->cpumask);
  22. return new;
  23. }
  24. static void pxm_free(pxm_t *pxm)
  25. {
  26. if (!pxm)
  27. return;
  28. if (pxm->addr)
  29. free(pxm->addr);
  30. free(pxm);
  31. }
  32. static pxm_t * pxm_list_add(lub_list_t *pxms, pxm_t *pxm)
  33. {
  34. lub_list_add(pxms, pxm);
  35. return pxm;
  36. }
  37. int pxm_list_free(lub_list_t *pxms)
  38. {
  39. lub_list_node_t *iter;
  40. while ((iter = lub_list__get_head(pxms))) {
  41. pxm_t *pxm;
  42. pxm = (pxm_t *)lub_list_node__get_data(iter);
  43. pxm_free(pxm);
  44. lub_list_del(pxms, iter);
  45. lub_list_node_free(iter);
  46. }
  47. lub_list_free(pxms);
  48. return 0;
  49. }
  50. /* Show proximity information */
  51. static void show_pxm_info(pxm_t *pxm)
  52. {
  53. char buf[NR_CPUS + 1];
  54. if (cpus_full(pxm->cpumask))
  55. snprintf(buf, sizeof(buf), "*");
  56. else
  57. cpumask_scnprintf(buf, sizeof(buf), pxm->cpumask);
  58. printf("PXM: %s cpumask %s\n", pxm->addr, buf);
  59. }
  60. /* Show PXM list */
  61. int show_pxms(lub_list_t *pxms)
  62. {
  63. lub_list_node_t *iter;
  64. for (iter = lub_list_iterator_init(pxms); iter;
  65. iter = lub_list_iterator_next(iter)) {
  66. pxm_t *pxm;
  67. pxm = (pxm_t *)lub_list_node__get_data(iter);
  68. show_pxm_info(pxm);
  69. }
  70. return 0;
  71. }
  72. int pxm_search(lub_list_t *pxms, const char *addr, cpumask_t *cpumask)
  73. {
  74. lub_list_node_t *iter;
  75. size_t maxaddr = 0;
  76. for (iter = lub_list_iterator_init(pxms); iter;
  77. iter = lub_list_iterator_next(iter)) {
  78. pxm_t *pxm;
  79. char *tmp = NULL;
  80. size_t len;
  81. pxm = (pxm_t *)lub_list_node__get_data(iter);
  82. tmp = strstr(addr, pxm->addr);
  83. if (!tmp)
  84. continue;
  85. len = strlen(pxm->addr);
  86. if (maxaddr >= len)
  87. continue;
  88. maxaddr = len;
  89. *cpumask = pxm->cpumask;
  90. }
  91. if (!maxaddr)
  92. return -1;
  93. return 0;
  94. }
  95. int parse_pxm_config(const char *fname, lub_list_t *pxms, lub_list_t *numas)
  96. {
  97. FILE *file;
  98. char *line = NULL;
  99. size_t size = 0;
  100. char *saveptr;
  101. unsigned int ln = 0; /* Line number */
  102. pxm_t *pxm;
  103. if (!fname)
  104. return -1;
  105. file = fopen(fname, "r");
  106. if (!file)
  107. return -1;
  108. while (!feof(file)) {
  109. char *str = NULL;
  110. char *pci_addr = NULL;
  111. char *pxm_cmd = NULL;
  112. char *pxm_pxm = NULL;
  113. cpumask_t cpumask;
  114. ln++; /* Next line */
  115. if (getline(&line, &size, file) <= 0)
  116. continue;
  117. /* Find comments */
  118. str = strchr(line, '#');
  119. if (str)
  120. *str = '\0';
  121. /* Find \n */
  122. str = strchr(line, '\n');
  123. if (str)
  124. *str = '\0';
  125. /* Get PCI address */
  126. pci_addr = strtok_r(line, " ", &saveptr);
  127. if (!pci_addr)
  128. continue;
  129. /* Get PXM command */
  130. pxm_cmd = strtok_r(NULL, " ", &saveptr);
  131. if (!pxm_cmd) {
  132. fprintf(stderr, "Warning: Illegal line %u in %s\n",
  133. ln, fname);
  134. continue;
  135. }
  136. /* Get PXM string (mask or node) */
  137. pxm_pxm = strtok_r(NULL, " ", &saveptr);
  138. if (!pxm_pxm) {
  139. fprintf(stderr, "Warning: Illegal line %u in %s\n",
  140. ln, fname);
  141. continue;
  142. }
  143. if (!strcasecmp(pxm_cmd, "cpumask")) {
  144. cpumask_parse_user(pxm_pxm, strlen(pxm_pxm),
  145. cpumask);
  146. } else if (!strcasecmp(pxm_cmd, "node")) {
  147. char *endptr;
  148. int noden = -1;
  149. noden = strtol(pxm_pxm, &endptr, 10);
  150. if (endptr == pxm_pxm) {
  151. fprintf(stderr, "Warning: Wrong NUMA node in "
  152. "line %u in %s\n", ln, fname);
  153. continue;
  154. }
  155. if (noden == -1) /* Non-NUMA = all CPUs */
  156. cpus_setall(cpumask);
  157. else {
  158. numa_t *numa;
  159. numa = numa_list_search(numas, noden);
  160. if (!numa) {
  161. fprintf(stderr, "Warning: Wrong NUMA node. Line %u in %s\n",
  162. ln, fname);
  163. continue;
  164. }
  165. cpus_clear(cpumask);
  166. cpus_or(cpumask, cpumask, numa->cpumap);
  167. }
  168. } else {
  169. fprintf(stderr, "Warning: Illegal command %u in %s\n",
  170. ln, fname);
  171. continue;
  172. }
  173. /* Add new entry to PXM list */
  174. pxm = pxm_new(pci_addr);
  175. cpus_clear(pxm->cpumask);
  176. cpus_or(pxm->cpumask, pxm->cpumask, cpumask);
  177. pxm_list_add(pxms, pxm);
  178. }
  179. fclose(file);
  180. free(line);
  181. return 0;
  182. }