cpu_affinity.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "stdafx.h"
  2. #include "cpu_affinity.h"
  3. #if defined(__FreeBSD__) && (__FreeBSD__ >= 7)
  4. #include <sys/param.h>
  5. #include <sys/cpuset.h>
  6. #elif defined(_linux_)
  7. #include <pthread.h>
  8. #include <util/stream/file.h>
  9. #include <util/string/printf.h>
  10. #endif
  11. namespace NNetliba {
  12. class TCPUSet {
  13. public:
  14. static constexpr int MAX_SIZE = 128;
  15. private:
  16. #if defined(__FreeBSD__) && (__FreeBSD__ >= 7)
  17. #define NUMCPU ((CPU_MAXSIZE > MAX_SIZE) ? 1 : (MAX_SIZE / CPU_MAXSIZE))
  18. cpuset_t CpuInfo[NUMCPU];
  19. public:
  20. bool GetAffinity() {
  21. int error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(CpuInfo), CpuInfo);
  22. return error == 0;
  23. }
  24. bool SetAffinity() {
  25. int error = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(CpuInfo), CpuInfo);
  26. return error == 0;
  27. }
  28. bool IsSet(size_t i) {
  29. return CPU_ISSET(i, CpuInfo);
  30. }
  31. void Set(size_t i) {
  32. CPU_SET(i, CpuInfo);
  33. }
  34. #elif defined(_linux_) && !defined(__ANDROID__)
  35. public:
  36. #define NUMCPU ((CPU_SETSIZE > MAX_SIZE) ? 1 : (MAX_SIZE / CPU_SETSIZE))
  37. cpu_set_t CpuInfo[NUMCPU];
  38. public:
  39. bool GetAffinity() {
  40. int error = pthread_getaffinity_np(pthread_self(), sizeof(CpuInfo), CpuInfo);
  41. return error == 0;
  42. }
  43. bool SetAffinity() {
  44. int error = pthread_setaffinity_np(pthread_self(), sizeof(CpuInfo), CpuInfo);
  45. return error == 0;
  46. }
  47. bool IsSet(size_t i) {
  48. return CPU_ISSET(i, CpuInfo);
  49. }
  50. void Set(size_t i) {
  51. CPU_SET(i, CpuInfo);
  52. }
  53. #else
  54. public:
  55. bool GetAffinity() {
  56. return true;
  57. }
  58. bool SetAffinity() {
  59. return true;
  60. }
  61. bool IsSet(size_t i) {
  62. Y_UNUSED(i);
  63. return true;
  64. }
  65. void Set(size_t i) {
  66. Y_UNUSED(i);
  67. }
  68. #endif
  69. TCPUSet() {
  70. Clear();
  71. }
  72. void Clear() {
  73. memset(this, 0, sizeof(*this));
  74. }
  75. };
  76. static TMutex CPUSetsLock;
  77. struct TCPUSetInfo {
  78. TCPUSet CPUSet;
  79. bool IsOk;
  80. TCPUSetInfo()
  81. : IsOk(false)
  82. {
  83. }
  84. };
  85. static THashMap<int, TCPUSetInfo> CPUSets;
  86. void BindToSocket(int n) {
  87. TGuard<TMutex> gg(CPUSetsLock);
  88. if (CPUSets.find(n) == CPUSets.end()) {
  89. TCPUSetInfo& res = CPUSets[n];
  90. bool foundCPU = false;
  91. #ifdef _linux_
  92. for (int cpuId = 0; cpuId < TCPUSet::MAX_SIZE; ++cpuId) {
  93. try { // I just wanna check if file exists, I don't want your stinking exceptions :/
  94. TIFStream f(Sprintf("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpuId).c_str());
  95. TString s;
  96. if (f.ReadLine(s) && !s.empty()) {
  97. //printf("cpu%d - %s\n", cpuId, s.c_str());
  98. int physCPU = atoi(s.c_str());
  99. if (physCPU == 0) {
  100. res.IsOk = true;
  101. res.CPUSet.Set(cpuId);
  102. foundCPU = true;
  103. }
  104. } else {
  105. break;
  106. }
  107. } catch (const TFileError&) {
  108. break;
  109. }
  110. }
  111. #endif
  112. if (!foundCPU && n == 0) {
  113. for (int i = 0; i < 6; ++i) {
  114. res.CPUSet.Set(i);
  115. }
  116. res.IsOk = true;
  117. foundCPU = true;
  118. }
  119. }
  120. {
  121. TCPUSetInfo& cc = CPUSets[n];
  122. if (cc.IsOk) {
  123. cc.CPUSet.SetAffinity();
  124. }
  125. }
  126. }
  127. }