numcpus.c (2891B)
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 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 long cpus_conf = sysconf(_SC_NPROCESSORS_CONF); 40 #else 41 long cpus_conf = -1; 42 #endif 43 #ifdef _SC_NPROCESSORS_ONLN 44 long cpus_onln = sysconf(_SC_NPROCESSORS_ONLN); 45 #else 46 long cpus_onln = -1; 47 #endif 48 long cpus = -1; 49 50 if (cpus_conf > 0 && cpus_onln < 0) { 51 cpus = cpus_conf; 52 } else if (cpus_onln > 0 && cpus_conf < 0) { 53 cpus = cpus_onln; 54 } else if (cpus_onln > 0 && cpus_conf > 0) { 55 if (cpus_onln < cpus_conf) { 56 log_info(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 if (cpus >= 1 && cpus < INT_MAX) 65 return (int)cpus; 66 else 67 return -1; 68 #else 69 return -1; 70 #endif /* defined(_WIN32) || ... */ 71 } 72 73 /** This is an arbitrary number but at this point in time, it is not that 74 * uncommon to see servers up to that amount of CPUs. Most servers will likely 75 * be around 16 to 32 cores now. Lets take advantage of large machines! The 76 * "NumCPUs" torrc option overrides this maximum. */ 77 #define MAX_DETECTABLE_CPUS 128 78 79 /** Return how many CPUs we are running with. We assume that nobody is 80 * using hot-swappable CPUs, so we don't recompute this after the first 81 * time. Return -1 if we don't know how to tell the number of CPUs on this 82 * system. 83 */ 84 int 85 compute_num_cpus(void) 86 { 87 static int num_cpus = -2; 88 if (num_cpus == -2) { 89 num_cpus = compute_num_cpus_impl(); 90 tor_assert(num_cpus != -2); 91 if (num_cpus > MAX_DETECTABLE_CPUS) { 92 /* LCOV_EXCL_START */ 93 log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I " 94 "will not autodetect any more than %d, though. If you " 95 "want to configure more, set NumCPUs in your torrc", 96 num_cpus, MAX_DETECTABLE_CPUS); 97 num_cpus = MAX_DETECTABLE_CPUS; 98 /* LCOV_EXCL_STOP */ 99 } 100 } 101 return num_cpus; 102 }