You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
3.3 KiB

  1. /*
  2. ISC License
  3. Copyright (c) 2024, Antonio SJ Musumeci <trapexit@spawn.link>
  4. Permission to use, copy, modify, and/or distribute this software for any
  5. purpose with or without fee is hereby granted, provided that the above
  6. copyright notice and this permission notice appear in all copies.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. */
  15. #include "cpu.hpp"
  16. #include "ghc/filesystem.hpp"
  17. #include "fmt/core.h"
  18. #include <pthread.h>
  19. #include <sched.h>
  20. #include <fstream>
  21. int
  22. CPU::getaffinity(cpu_set_t *cpuset_)
  23. {
  24. const pid_t pid = 0;
  25. CPU_ZERO(cpuset_);
  26. return sched_getaffinity(pid,
  27. sizeof(cpu_set_t),
  28. cpuset_);
  29. }
  30. int
  31. CPU::setaffinity(const pthread_t thread_id_,
  32. cpu_set_t *cpuset_)
  33. {
  34. return pthread_setaffinity_np(thread_id_,
  35. sizeof(cpu_set_t),
  36. cpuset_);
  37. }
  38. int
  39. CPU::setaffinity(const pthread_t thread_id_,
  40. const int cpu_)
  41. {
  42. cpu_set_t cpuset;
  43. CPU_ZERO(&cpuset);
  44. CPU_SET(cpu_,&cpuset);
  45. return CPU::setaffinity(thread_id_,&cpuset);
  46. }
  47. int
  48. CPU::setaffinity(const pthread_t thread_id_,
  49. const std::set<int> cpus_)
  50. {
  51. cpu_set_t cpuset;
  52. CPU_ZERO(&cpuset);
  53. for(auto const cpu : cpus_)
  54. CPU_SET(cpu,&cpuset);
  55. return CPU::setaffinity(thread_id_,&cpuset);
  56. }
  57. static
  58. ghc::filesystem::path
  59. generate_cpu_core_id_path(const int cpu_id_)
  60. {
  61. const ghc::filesystem::path basepath{"/sys/devices/system/cpu"};
  62. return basepath / fmt::format("cpu{}",cpu_id_) / "topology" / "core_id";
  63. }
  64. int
  65. CPU::count()
  66. {
  67. int rv;
  68. cpu_set_t cpuset;
  69. rv = CPU::getaffinity(&cpuset);
  70. if(rv < 0)
  71. return rv;
  72. return CPU_COUNT(&cpuset);
  73. }
  74. CPU::CPUVec
  75. CPU::cpus()
  76. {
  77. cpu_set_t cpuset;
  78. CPU::CPUVec cpuvec;
  79. CPU::getaffinity(&cpuset);
  80. for(int i = 0; i < CPU_SETSIZE; i++)
  81. {
  82. if(!CPU_ISSET(i,&cpuset))
  83. continue;
  84. cpuvec.push_back(i);
  85. }
  86. return cpuvec;
  87. }
  88. CPU::CPU2CoreMap
  89. CPU::cpu2core()
  90. {
  91. cpu_set_t cpuset;
  92. CPU::CPU2CoreMap c2c;
  93. CPU::getaffinity(&cpuset);
  94. for(int i = 0; i < CPU_SETSIZE; i++)
  95. {
  96. int core_id;
  97. std::ifstream ifs;
  98. ghc::filesystem::path path;
  99. if(!CPU_ISSET(i,&cpuset))
  100. continue;
  101. path = ::generate_cpu_core_id_path(i);
  102. ifs.open(path);
  103. if(!ifs)
  104. break;
  105. ifs >> core_id;
  106. c2c[i] = core_id;
  107. ifs.close();
  108. }
  109. return c2c;
  110. }
  111. CPU::Core2CPUsMap
  112. CPU::core2cpus()
  113. {
  114. cpu_set_t cpuset;
  115. CPU::Core2CPUsMap c2c;
  116. CPU::getaffinity(&cpuset);
  117. for(int i = 0; i < CPU_SETSIZE; i++)
  118. {
  119. int core_id;
  120. std::ifstream ifs;
  121. ghc::filesystem::path path;
  122. if(!CPU_ISSET(i,&cpuset))
  123. continue;
  124. path = ::generate_cpu_core_id_path(i);
  125. ifs.open(path);
  126. if(!ifs)
  127. break;
  128. ifs >> core_id;
  129. c2c[core_id].insert(i);
  130. ifs.close();
  131. }
  132. return c2c;
  133. }