Affinity.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. htop - Affinity.c
  3. (C) 2004-2011 Hisham H. Muhammad
  4. (C) 2020 Red Hat, Inc. All Rights Reserved.
  5. Released under the GNU GPLv2+, see the COPYING file
  6. in the source distribution for its full text.
  7. */
  8. #include "config.h" // IWYU pragma: keep
  9. #include "Affinity.h"
  10. #include <assert.h>
  11. #include <stdlib.h>
  12. #include "Process.h"
  13. #include "XUtils.h"
  14. #if defined(HAVE_LIBHWLOC)
  15. #include <hwloc.h>
  16. #include <hwloc/bitmap.h>
  17. #ifdef __linux__
  18. #define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_THREAD
  19. #else
  20. #define HTOP_HWLOC_CPUBIND_FLAG HWLOC_CPUBIND_PROCESS
  21. #endif
  22. #elif defined(HAVE_AFFINITY)
  23. #include <sched.h>
  24. #endif
  25. Affinity* Affinity_new(Machine* host) {
  26. Affinity* this = xCalloc(1, sizeof(Affinity));
  27. this->size = 8;
  28. this->cpus = xCalloc(this->size, sizeof(unsigned int));
  29. this->host = host;
  30. return this;
  31. }
  32. void Affinity_delete(Affinity* this) {
  33. free(this->cpus);
  34. free(this);
  35. }
  36. void Affinity_add(Affinity* this, unsigned int id) {
  37. if (this->used == this->size) {
  38. this->size *= 2;
  39. this->cpus = xRealloc(this->cpus, sizeof(unsigned int) * this->size);
  40. }
  41. this->cpus[this->used] = id;
  42. this->used++;
  43. }
  44. #if defined(HAVE_LIBHWLOC)
  45. static Affinity* Affinity_get(const Process* p, Machine* host) {
  46. hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
  47. bool ok = (hwloc_get_proc_cpubind(host->topology, Process_getPid(p), cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
  48. Affinity* affinity = NULL;
  49. if (ok) {
  50. affinity = Affinity_new(host);
  51. if (hwloc_bitmap_last(cpuset) == -1) {
  52. for (unsigned int i = 0; i < host->existingCPUs; i++) {
  53. Affinity_add(affinity, i);
  54. }
  55. } else {
  56. int id;
  57. hwloc_bitmap_foreach_begin(id, cpuset)
  58. Affinity_add(affinity, (unsigned)id);
  59. hwloc_bitmap_foreach_end();
  60. }
  61. }
  62. hwloc_bitmap_free(cpuset);
  63. return affinity;
  64. }
  65. static bool Affinity_set(Process* p, Arg arg) {
  66. Affinity* this = arg.v;
  67. hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
  68. for (unsigned int i = 0; i < this->used; i++) {
  69. hwloc_bitmap_set(cpuset, this->cpus[i]);
  70. }
  71. bool ok = (hwloc_set_proc_cpubind(this->host->topology, Process_getPid(p), cpuset, HTOP_HWLOC_CPUBIND_FLAG) == 0);
  72. hwloc_bitmap_free(cpuset);
  73. return ok;
  74. }
  75. #elif defined(HAVE_AFFINITY)
  76. static Affinity* Affinity_get(const Process* p, Machine* host) {
  77. cpu_set_t cpuset;
  78. bool ok = (sched_getaffinity(Process_getPid(p), sizeof(cpu_set_t), &cpuset) == 0);
  79. if (!ok)
  80. return NULL;
  81. Affinity* affinity = Affinity_new(host);
  82. for (unsigned int i = 0; i < host->existingCPUs; i++) {
  83. if (CPU_ISSET(i, &cpuset)) {
  84. Affinity_add(affinity, i);
  85. }
  86. }
  87. return affinity;
  88. }
  89. static bool Affinity_set(Process* p, Arg arg) {
  90. Affinity* this = arg.v;
  91. cpu_set_t cpuset;
  92. CPU_ZERO(&cpuset);
  93. for (unsigned int i = 0; i < this->used; i++) {
  94. CPU_SET(this->cpus[i], &cpuset);
  95. }
  96. bool ok = (sched_setaffinity(Process_getPid(p), sizeof(unsigned long), &cpuset) == 0);
  97. return ok;
  98. }
  99. #endif
  100. #if defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY)
  101. bool Affinity_rowSet(Row* row, Arg arg) {
  102. Process* p = (Process*) row;
  103. assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));
  104. return Affinity_set(p, arg);
  105. }
  106. Affinity* Affinity_rowGet(const Row* row, Machine* host) {
  107. const Process* p = (const Process*) row;
  108. assert(Object_isA((const Object*) p, (const ObjectClass*) &Process_class));
  109. return Affinity_get(p, host);
  110. }
  111. #endif /* HAVE_LIBHWLOC || HAVE_AFFINITY */