tuklib_cpucores.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-License-Identifier: 0BSD
  2. ///////////////////////////////////////////////////////////////////////////////
  3. //
  4. /// \file tuklib_cpucores.c
  5. /// \brief Get the number of CPU cores online
  6. //
  7. // Author: Lasse Collin
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "tuklib_cpucores.h"
  11. #if defined(_WIN32) || defined(__CYGWIN__)
  12. # ifndef _WIN32_WINNT
  13. # define _WIN32_WINNT 0x0500
  14. # endif
  15. # include <windows.h>
  16. // glibc >= 2.9
  17. #elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
  18. # include <sched.h>
  19. // FreeBSD
  20. #elif defined(TUKLIB_CPUCORES_CPUSET)
  21. # include <sys/param.h>
  22. # include <sys/cpuset.h>
  23. #elif defined(TUKLIB_CPUCORES_SYSCTL)
  24. # ifdef HAVE_SYS_PARAM_H
  25. # include <sys/param.h>
  26. # endif
  27. # include <sys/sysctl.h>
  28. #elif defined(TUKLIB_CPUCORES_SYSCONF)
  29. # include <unistd.h>
  30. // HP-UX
  31. #elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
  32. # include <sys/param.h>
  33. # include <sys/pstat.h>
  34. #endif
  35. extern uint32_t
  36. tuklib_cpucores(void)
  37. {
  38. uint32_t ret = 0;
  39. #if defined(_WIN32) || defined(__CYGWIN__)
  40. SYSTEM_INFO sysinfo;
  41. GetSystemInfo(&sysinfo);
  42. ret = sysinfo.dwNumberOfProcessors;
  43. #elif defined(TUKLIB_CPUCORES_SCHED_GETAFFINITY)
  44. cpu_set_t cpu_mask;
  45. if (sched_getaffinity(0, sizeof(cpu_mask), &cpu_mask) == 0)
  46. ret = (uint32_t)CPU_COUNT(&cpu_mask);
  47. #elif defined(TUKLIB_CPUCORES_CPUSET)
  48. cpuset_t set;
  49. if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
  50. sizeof(set), &set) == 0) {
  51. # ifdef CPU_COUNT
  52. ret = (uint32_t)CPU_COUNT(&set);
  53. # else
  54. for (unsigned i = 0; i < CPU_SETSIZE; ++i)
  55. if (CPU_ISSET(i, &set))
  56. ++ret;
  57. # endif
  58. }
  59. #elif defined(TUKLIB_CPUCORES_SYSCTL)
  60. // On OpenBSD HW_NCPUONLINE tells the number of processor cores that
  61. // are online so it is preferred over HW_NCPU which also counts cores
  62. // that aren't currently available. The number of cores online is
  63. // often less than HW_NCPU because OpenBSD disables simultaneous
  64. // multi-threading (SMT) by default.
  65. # ifdef HW_NCPUONLINE
  66. int name[2] = { CTL_HW, HW_NCPUONLINE };
  67. # else
  68. int name[2] = { CTL_HW, HW_NCPU };
  69. # endif
  70. int cpus;
  71. size_t cpus_size = sizeof(cpus);
  72. if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
  73. && cpus_size == sizeof(cpus) && cpus > 0)
  74. ret = (uint32_t)cpus;
  75. #elif defined(TUKLIB_CPUCORES_SYSCONF)
  76. # ifdef _SC_NPROCESSORS_ONLN
  77. // Most systems
  78. const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
  79. # else
  80. // IRIX
  81. const long cpus = sysconf(_SC_NPROC_ONLN);
  82. # endif
  83. if (cpus > 0)
  84. ret = (uint32_t)cpus;
  85. #elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
  86. struct pst_dynamic pst;
  87. if (pstat_getdynamic(&pst, sizeof(pst), 1, 0) != -1)
  88. ret = (uint32_t)pst.psd_proc_cnt;
  89. #endif
  90. return ret;
  91. }