statistics.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* stat_parse.c
  2. * Parse statistics files.
  3. */
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <dirent.h>
  9. #include <limits.h>
  10. #include <ctype.h>
  11. #include "statistics.h"
  12. #include "cpu.h"
  13. #include "irq.h"
  14. #include "balance.h"
  15. /* The setting of smp affinity is not reliable due to problems with some
  16. * APIC hw/driver. So we need to relink IRQs to CPUs on each iteration.
  17. * The linkage is based on current smp affinity value.
  18. */
  19. void link_irqs_to_cpus(lub_list_t *cpus, lub_list_t *irqs)
  20. {
  21. lub_list_node_t *iter;
  22. /* Clear all CPU's irq lists. These lists are probably out of date. */
  23. for (iter = lub_list_iterator_init(cpus); iter;
  24. iter = lub_list_iterator_next(iter)) {
  25. cpu_t *cpu = (cpu_t *)lub_list_node__get_data(iter);
  26. lub_list_node_t *node;
  27. while ((node = lub_list__get_tail(cpu->irqs))) {
  28. lub_list_del(cpu->irqs, node);
  29. lub_list_node_free(node);
  30. }
  31. }
  32. /* Iterate through IRQ list */
  33. for (iter = lub_list_iterator_init(irqs); iter;
  34. iter = lub_list_iterator_next(iter)) {
  35. irq_t *irq = (irq_t *)lub_list_node__get_data(iter);
  36. int cpu_num;
  37. cpu_t *cpu;
  38. /* Ignore blacklisted IRQs */
  39. if (irq->blacklisted)
  40. continue;
  41. /* Ignore IRQs with multi-affinity. */
  42. if (cpus_weight(irq->affinity) > 1)
  43. continue;
  44. cpu_num = first_cpu(irq->affinity);
  45. if (NR_CPUS == cpu_num) /* Something went wrong. No bits set. */
  46. continue;
  47. if (!(cpu = cpu_list_search(cpus, cpu_num)))
  48. continue;
  49. move_irq_to_cpu(irq, cpu);
  50. }
  51. }
  52. /* Gather load statistics for CPUs and number of interrupts
  53. * for current iteration.
  54. */
  55. void gather_statistics(lub_list_t *cpus, lub_list_t *irqs)
  56. {
  57. FILE *file;
  58. char *line = NULL;
  59. size_t size = 0;
  60. int cpunr, rc, cpucount;
  61. unsigned long long l_user;
  62. unsigned long long l_nice;
  63. unsigned long long l_system;
  64. unsigned long long l_idle;
  65. unsigned long long l_iowait;
  66. unsigned long long l_irq;
  67. unsigned long long l_softirq;
  68. unsigned long long l_steal;
  69. unsigned long long l_guest;
  70. unsigned long long l_guest_nice;
  71. unsigned long long load_irq, load_all;
  72. char *intr_str;
  73. char *saveptr = NULL;
  74. unsigned int inum = 0;
  75. file = fopen("/proc/stat", "r");
  76. if (!file) {
  77. fprintf(stderr, "Warning: Can't open /proc/stat. Balacing is broken.\n");
  78. return;
  79. }
  80. /* Get statistics for CPUs */
  81. /* First line is the header. */
  82. if (getline(&line, &size, file) == 0) {
  83. free(line);
  84. fprintf(stderr, "Warning: Can't read /proc/stat. Balancing is broken.\n");
  85. fclose(file);
  86. return;
  87. }
  88. cpucount = 0;
  89. while (!feof(file)) {
  90. cpu_t *cpu;
  91. if (getline(&line, &size, file)==0)
  92. break;
  93. if (!strstr(line, "cpu"))
  94. break;
  95. cpunr = strtoul(&line[3], NULL, 10);
  96. cpu = cpu_list_search(cpus, cpunr);
  97. if (!cpu)
  98. continue;
  99. rc = sscanf(line, "%*s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
  100. &l_user, &l_nice, &l_system, &l_idle, &l_iowait,
  101. &l_irq, &l_softirq, &l_steal, &l_guest, &l_guest_nice);
  102. if (rc < 2)
  103. break;
  104. cpucount++;
  105. load_all = l_user + l_nice + l_system + l_idle + l_iowait +
  106. l_irq + l_softirq + l_steal + l_guest + l_guest_nice;
  107. load_irq = l_irq + l_softirq;
  108. cpu->old_load = cpu->load;
  109. if (cpu->old_load_all == 0) {
  110. /* When old_load_all = 0 - it's first iteration */
  111. cpu->load = 0;
  112. } else {
  113. float d_all = (float)(load_all - cpu->old_load_all);
  114. float d_irq = (float)(load_irq - cpu->old_load_irq);
  115. cpu->load = d_irq * 100 / d_all;
  116. }
  117. cpu->old_load_all = load_all;
  118. cpu->old_load_irq = load_irq;
  119. }
  120. /* Parse "intr" line. Get number of interrupts. */
  121. strtok_r(line, " ", &saveptr); /* String "intr" */
  122. strtok_r(NULL, " ", &saveptr); /* Total number of interrupts */
  123. for (intr_str = strtok_r(NULL, " ", &saveptr);
  124. intr_str; intr_str = strtok_r(NULL, " ", &saveptr)) {
  125. unsigned long long intr = 0;
  126. char *endptr;
  127. irq_t *irq;
  128. irq = irq_list_search(irqs, inum);
  129. inum++;
  130. if (!irq)
  131. continue;
  132. intr = strtoull(intr_str, &endptr, 10);
  133. if (endptr == intr_str)
  134. intr = 0;
  135. if (irq->old_intr == 0)
  136. irq->intr = 0;
  137. else
  138. irq->intr = intr - irq->old_intr;
  139. irq->old_intr = intr;
  140. }
  141. fclose(file);
  142. free(line);
  143. }
  144. void show_statistics(lub_list_t *cpus, int verbose)
  145. {
  146. lub_list_node_t *iter;
  147. for (iter = lub_list_iterator_init(cpus); iter;
  148. iter = lub_list_iterator_next(iter)) {
  149. cpu_t *cpu;
  150. lub_list_node_t *irq_iter;
  151. cpu = (cpu_t *)lub_list_node__get_data(iter);
  152. printf("CPU%u package %u, core %u, irqs %d, old %.2f%%, load %.2f%%\n",
  153. cpu->id, cpu->package_id, cpu->core_id,
  154. lub_list_len(cpu->irqs), cpu->old_load, cpu->load);
  155. if (!verbose)
  156. continue;
  157. for (irq_iter = lub_list_iterator_init(cpu->irqs); irq_iter;
  158. irq_iter = lub_list_iterator_next(irq_iter)) {
  159. char buf[NR_CPUS + 1];
  160. irq_t *irq = (irq_t *)lub_list_node__get_data(irq_iter);
  161. if (cpus_full(irq->affinity))
  162. snprintf(buf, sizeof(buf), "*");
  163. else
  164. cpumask_scnprintf(buf, sizeof(buf), irq->affinity);
  165. buf[sizeof(buf) - 1] = '\0';
  166. printf(" IRQ %3u, [%s], weight %d, intr %llu, %s\n", irq->irq, buf, irq->weight, irq->intr, irq->desc);
  167. }
  168. }
  169. }