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