balance.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* balance.c
  2. * Balance IRQs.
  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. static int move_irq_to_cpu(irq_t *irq, cpu_t *cpu)
  15. {
  16. if (!irq || !cpu)
  17. return -1;
  18. if (irq->cpu) {
  19. cpu_t *old_cpu = irq->cpu;
  20. lub_list_node_t *node;
  21. node = lub_list_search(old_cpu->irqs, irq);
  22. if (node) {
  23. lub_list_del(old_cpu->irqs, node);
  24. lub_list_node_free(node);
  25. }
  26. }
  27. lub_list_add(cpu->irqs, irq);
  28. irq->cpu = cpu;
  29. return 0;
  30. }
  31. static cpu_t *choose_cpu(lub_list_t *cpus, cpumask_t cpumask, float threshold)
  32. {
  33. lub_list_node_t *iter;
  34. lub_list_t * min_cpus = NULL;
  35. float min_load = 100.00;
  36. lub_list_node_t *node;
  37. cpu_t *cpu = NULL;
  38. for (iter = lub_list_iterator_init(cpus); iter;
  39. iter = lub_list_iterator_next(iter)) {
  40. cpu = (cpu_t *)lub_list_node__get_data(iter);
  41. if (!cpu_isset(cpu->id, cpumask))
  42. continue;
  43. if (cpu->load >= threshold)
  44. continue;
  45. if ((!min_cpus) || (cpu->load < min_load)) {
  46. min_load = cpu->load;
  47. if (!min_cpus)
  48. min_cpus = lub_list_new(cpu_list_compare_len);
  49. while ((node = lub_list__get_tail(min_cpus))) {
  50. lub_list_del(min_cpus, node);
  51. lub_list_node_free(node);
  52. }
  53. lub_list_add(min_cpus, cpu);
  54. }
  55. if (cpu->load == min_load)
  56. lub_list_add(min_cpus, cpu);
  57. }
  58. if (!min_cpus)
  59. return NULL;
  60. node = lub_list__get_head(min_cpus);
  61. cpu = (cpu_t *)lub_list_node__get_data(node);
  62. while ((node = lub_list__get_tail(min_cpus))) {
  63. lub_list_del(min_cpus, node);
  64. lub_list_node_free(node);
  65. }
  66. lub_list_free(min_cpus);
  67. return cpu;
  68. }
  69. int balance(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold)
  70. {
  71. lub_list_node_t *iter;
  72. for (iter = lub_list_iterator_init(balance_irqs); iter;
  73. iter = lub_list_iterator_next(iter)) {
  74. irq_t *irq;
  75. cpu_t *cpu;
  76. irq = (irq_t *)lub_list_node__get_data(iter);
  77. /* Try to find local CPU to move IRQ to.
  78. The local CPU is CPU with native NUMA node. */
  79. cpu = choose_cpu(cpus, irq->local_cpus, threshold);
  80. /* If local CPU is not found then try to use
  81. CPU from another NUMA node. It's better then
  82. overloaded CPUs. */
  83. if (!cpu) {
  84. cpumask_t complement;
  85. cpus_complement(complement, irq->local_cpus);
  86. cpu = choose_cpu(cpus, complement, threshold);
  87. }
  88. if (cpu) {
  89. move_irq_to_cpu(irq, cpu);
  90. printf("Move IRQ %u to CPU%u\n", irq->irq, cpu->id);
  91. }
  92. }
  93. return 0;
  94. }
  95. int apply_affinity(lub_list_t *balance_irqs)
  96. {
  97. lub_list_node_t *iter;
  98. for (iter = lub_list_iterator_init(balance_irqs); iter;
  99. iter = lub_list_iterator_next(iter)) {
  100. irq_t *irq;
  101. irq = (irq_t *)lub_list_node__get_data(iter);
  102. if (!irq->cpu)
  103. continue;
  104. irq_set_affinity(irq, irq->cpu->cpumask);
  105. }
  106. return 0;
  107. }
  108. int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold)
  109. {
  110. lub_list_node_t *iter;
  111. cpu_t *overloaded_cpu = NULL;
  112. irq_t *irq_to_move = NULL;
  113. float max_load = 0.0;
  114. unsigned long long max_intr = 0;
  115. /* Search for the most overloaded CPU.
  116. The load must be greater than threshold. */
  117. for (iter = lub_list_iterator_init(cpus); iter;
  118. iter = lub_list_iterator_next(iter)) {
  119. cpu_t *cpu = (cpu_t *)lub_list_node__get_data(iter);
  120. if (cpu->load < threshold)
  121. continue;
  122. if (cpu->load > max_load) {
  123. max_load = cpu->load;
  124. overloaded_cpu = cpu;
  125. }
  126. }
  127. /* Can't find overloaded CPUs */
  128. if (!overloaded_cpu)
  129. return 0;
  130. /* Search for the IRQ (owned by overloaded CPU) with
  131. maximum number of interrupts. */
  132. if (lub_list_len(overloaded_cpu->irqs) <= 1)
  133. return 0;
  134. for (iter = lub_list_iterator_init(overloaded_cpu->irqs); iter;
  135. iter = lub_list_iterator_next(iter)) {
  136. irq_t *irq = (irq_t *)lub_list_node__get_data(iter);
  137. if (irq->intr >= max_intr) {
  138. max_intr = irq->intr;
  139. irq_to_move = irq;
  140. }
  141. }
  142. if (irq_to_move)
  143. lub_list_add(balance_irqs, irq_to_move);
  144. return 0;
  145. }