numcpus.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file numcpus.c
  7. * \brief Compute the number of CPUs configured on this system.
  8. **/
  9. #include "orconfig.h"
  10. #include "lib/thread/numcpus.h"
  11. #include "lib/log/log.h"
  12. #include "lib/log/util_bug.h"
  13. #ifdef HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #ifdef _WIN32
  17. #include <windows.h>
  18. #endif
  19. #include <stdlib.h>
  20. /** Implementation logic for compute_num_cpus(). */
  21. static int
  22. compute_num_cpus_impl(void)
  23. {
  24. #ifdef _WIN32
  25. SYSTEM_INFO info;
  26. memset(&info, 0, sizeof(info));
  27. GetSystemInfo(&info);
  28. if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
  29. return (int)info.dwNumberOfProcessors;
  30. else
  31. return -1;
  32. #elif defined(HAVE_SYSCONF)
  33. #ifdef _SC_NPROCESSORS_CONF
  34. long cpus_conf = sysconf(_SC_NPROCESSORS_CONF);
  35. #else
  36. long cpus_conf = -1;
  37. #endif
  38. #ifdef _SC_NPROCESSORS_ONLN
  39. long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN);
  40. #else
  41. long cpus_onln = -1;
  42. #endif
  43. long cpus = -1;
  44. if (cpus_conf > 0 && cpus_onln < 0) {
  45. cpus = cpus_conf;
  46. } else if (cpus_onln > 0 && cpus_conf < 0) {
  47. cpus = cpus_onln;
  48. } else if (cpus_onln > 0 && cpus_conf > 0) {
  49. if (cpus_onln < cpus_conf) {
  50. log_notice(LD_GENERAL, "I think we have %ld CPUS, but only %ld of them "
  51. "are available. Telling Tor to only use %ld. You can over"
  52. "ride this with the NumCPUs option",
  53. cpus_conf, cpus_onln, cpus_onln);
  54. }
  55. cpus = cpus_onln;
  56. }
  57. if (cpus >= 1 && cpus < INT_MAX)
  58. return (int)cpus;
  59. else
  60. return -1;
  61. #else
  62. return -1;
  63. #endif /* defined(_WIN32) || ... */
  64. }
  65. #define MAX_DETECTABLE_CPUS 16
  66. /** Return how many CPUs we are running with. We assume that nobody is
  67. * using hot-swappable CPUs, so we don't recompute this after the first
  68. * time. Return -1 if we don't know how to tell the number of CPUs on this
  69. * system.
  70. */
  71. int
  72. compute_num_cpus(void)
  73. {
  74. static int num_cpus = -2;
  75. if (num_cpus == -2) {
  76. num_cpus = compute_num_cpus_impl();
  77. tor_assert(num_cpus != -2);
  78. if (num_cpus > MAX_DETECTABLE_CPUS) {
  79. /* LCOV_EXCL_START */
  80. log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
  81. "will not autodetect any more than %d, though. If you "
  82. "want to configure more, set NumCPUs in your torrc",
  83. num_cpus, MAX_DETECTABLE_CPUS);
  84. num_cpus = MAX_DETECTABLE_CPUS;
  85. /* LCOV_EXCL_STOP */
  86. }
  87. }
  88. return num_cpus;
  89. }