pxm.c 4.2 KB

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