tuklib_cpucores.c 2.7 KB

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