pxm.c 4.0 KB

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