numcpus.c 2.5 KB

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