aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-09-28 14:36:28 -0400
committerNick Mathewson <nickm@torproject.org>2010-09-28 14:42:21 -0400
commit73d93c033d3f4b9c95e8f3a5cc7e4a255d523b84 (patch)
tree4a6ef543d04d0153134d973977b0e5bfce80425d
parentc612ddee17c2f6e70fde9f0bdd7116516f384ae8 (diff)
downloadtor-73d93c033d3f4b9c95e8f3a5cc7e4a255d523b84.tar.gz
tor-73d93c033d3f4b9c95e8f3a5cc7e4a255d523b84.zip
Autodetect the number of CPUs when possible if NumCPUs==0
This is needed for IOCP, since telling the IOCP backend about all your CPUs is a good idea. It'll also come in handy with asn's multithreaded crypto stuff, and for people who run servers without reading the manual.
-rw-r--r--changes/cpudetect3
-rw-r--r--configure.in2
-rw-r--r--doc/tor.1.txt4
-rw-r--r--src/common/compat.c46
-rw-r--r--src/common/compat.h2
-rw-r--r--src/or/config.c17
-rw-r--r--src/or/config.h2
-rw-r--r--src/or/cpuworker.c2
8 files changed, 73 insertions, 5 deletions
diff --git a/changes/cpudetect b/changes/cpudetect
new file mode 100644
index 0000000000..eeaa492f58
--- /dev/null
+++ b/changes/cpudetect
@@ -0,0 +1,3 @@
+ o Minor features
+ - If you set the NumCPUs option to 0, Tor will try to detect how many
+ CPUs you have. This is the new default behavior.
diff --git a/configure.in b/configure.in
index 511552d713..83eee4d348 100644
--- a/configure.in
+++ b/configure.in
@@ -226,7 +226,7 @@ dnl -------------------------------------------------------------------
dnl Check for functions before libevent, since libevent-1.2 apparently
dnl exports strlcpy without defining it in a header.
-AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull getaddrinfo localtime_r gmtime_r memmem strtok_r flock prctl vasprintf)
+AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull getaddrinfo localtime_r gmtime_r memmem strtok_r flock prctl vasprintf sysconf)
using_custom_malloc=no
if test x$enable_openbsd_malloc = xyes ; then
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index e9ef55166c..e670bdb6b7 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -860,7 +860,9 @@ is non-zero):
characters inclusive, and must contain only the characters [a-zA-Z0-9].
**NumCPUs** __num__::
- How many processes to use at once for decrypting onionskins. (Default: 1)
+ How many processes to use at once for decrypting onionskins and other
+ parallelizable operations. If this is set to 0, Tor will try to detect
+ how many CPUs you have, defaulting to 1 if it can't tell. (Default: 0)
**ORPort** __PORT__::
Advertise this port to listen for connections from Tor clients and servers.
diff --git a/src/common/compat.c b/src/common/compat.c
index 20394b4c5d..b7f4f17cae 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -1898,6 +1898,52 @@ spawn_exit(void)
#endif
}
+/** Implementation logic for compute_num_cpus(). */
+static int
+compute_num_cpus_impl(void)
+{
+#ifdef MS_WINDOWS
+ SYSTEM_INFO info;
+ memset(&info, 0, sizeof(info));
+ GetSystemInfo(&info);
+ if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
+ return (int)info.dwNumberOfProcessors;
+ else
+ return -1;
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+ long cpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (cpus >= 1 && cpus < INT_MAX)
+ return (int)cpus;
+ else
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+#define MAX_DETECTABLE_CPUS 16
+
+/** Return how many CPUs we are running with. We assume that nobody is
+ * using hot-swappable CPUs, so we don't recompute this after the first
+ * time. Return -1 if we don't know how to tell the number of CPUs on this
+ * system.
+ */
+int
+compute_num_cpus(void)
+{
+ static int num_cpus = -2;
+ if (num_cpus == -2) {
+ num_cpus = compute_num_cpus_impl();
+ tor_assert(num_cpus != -2);
+ if (num_cpus > MAX_DETECTABLE_CPUS)
+ log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
+ "will not autodetect any more than %d, though. If you "
+ "want to configure more, set NumCPUs in your torrc",
+ num_cpus, MAX_DETECTABLE_CPUS);
+ }
+ return num_cpus;
+}
+
/** Set *timeval to the current time of day. On error, log and terminate.
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
*/
diff --git a/src/common/compat.h b/src/common/compat.h
index 7d59501e2b..5b6cfc40b5 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -522,6 +522,8 @@ void spawn_exit(void) ATTR_NORETURN;
#undef TOR_IS_MULTITHREADED
#endif
+int compute_num_cpus(void);
+
/* Because we use threads instead of processes on most platforms (Windows,
* Linux, etc), we need locking for them. On platforms with poor thread
* support or broken gethostbyname_r, these functions are no-ops. */
diff --git a/src/or/config.c b/src/or/config.c
index c5b0ccf586..23cad9268b 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -307,7 +307,7 @@ static config_var_t _option_vars[] = {
V(WarnUnsafeSocks, BOOL, "1"),
V(NoPublish, BOOL, "0"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
- V(NumCpus, UINT, "1"),
+ V(NumCpus, UINT, "0"),
V(NumEntryGuards, UINT, "3"),
V(ORListenAddress, LINELIST, NULL),
V(ORPort, UINT, "0"),
@@ -4892,6 +4892,19 @@ config_parse_interval(const char *s, int *ok)
return (int)r;
}
+/** Return the number of cpus configured in <b>options</b>. If we are
+ * told to auto-detect the number of cpus, return the auto-detected number. */
+int
+get_num_cpus(const or_options_t *options)
+{
+ if (options->NumCpus == 0) {
+ int n = compute_num_cpus();
+ return (n >= 1) ? n : 1;
+ } else {
+ return options->NumCpus;
+ }
+}
+
/**
* Initialize the libevent library.
*/
@@ -4913,7 +4926,7 @@ init_libevent(const or_options_t *options)
memset(&cfg, 0, sizeof(cfg));
cfg.disable_iocp = options->DisableIOCP;
- cfg.num_cpus = options->NumCpus;
+ cfg.num_cpus = get_num_cpus(options);
tor_libevent_initialize(&cfg);
diff --git a/src/or/config.h b/src/or/config.h
index 7a4ba5c60f..bd5827b4e8 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -57,6 +57,8 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
#define get_datadir_fname_suffix(sub1, suffix) \
get_datadir_fname2_suffix((sub1), NULL, (suffix))
+int get_num_cpus(const or_options_t *options);
+
or_state_t *get_or_state(void);
int or_state_save(time_t now);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index e5b2c71025..cfe9f3af9c 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -366,7 +366,7 @@ spawn_cpuworker(void)
static void
spawn_enough_cpuworkers(void)
{
- int num_cpuworkers_needed = get_options()->NumCpus;
+ int num_cpuworkers_needed = get_num_cpus(get_options());
if (num_cpuworkers_needed < MIN_CPUWORKERS)
num_cpuworkers_needed = MIN_CPUWORKERS;