aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-09-28 14:42:52 -0400
committerNick Mathewson <nickm@torproject.org>2010-09-28 14:42:52 -0400
commit3efaa30727f23f316941b6ac861a7027f8204769 (patch)
treed671760bb22f7010a2c2695f0a2891fc7393a9c2 /src
parentc58b7a109559a609f642d1fb7eb2e55b0d566ba5 (diff)
parent73d93c033d3f4b9c95e8f3a5cc7e4a255d523b84 (diff)
downloadtor-3efaa30727f23f316941b6ac861a7027f8204769.tar
tor-3efaa30727f23f316941b6ac861a7027f8204769.tar.gz
Merge branch 'iocp_option'
Diffstat (limited to 'src')
-rw-r--r--src/common/compat.c46
-rw-r--r--src/common/compat.h2
-rw-r--r--src/common/compat_libevent.c18
-rw-r--r--src/common/compat_libevent.h7
-rw-r--r--src/or/config.c31
-rw-r--r--src/or/config.h2
-rw-r--r--src/or/cpuworker.c2
-rw-r--r--src/or/or.h4
8 files changed, 103 insertions, 9 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 20394b4c5..b7f4f17ca 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 7d59501e2..5b6cfc40b 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/common/compat_libevent.c b/src/common/compat_libevent.c
index bbab06e8d..6afd3c1d2 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -159,7 +159,7 @@ struct event_base *the_event_base = NULL;
/** Initialize the Libevent library and set up the event base. */
void
-tor_libevent_initialize(void)
+tor_libevent_initialize(tor_libevent_cfg *torcfg)
{
tor_assert(the_event_base == NULL);
@@ -171,7 +171,21 @@ tor_libevent_initialize(void)
#endif
#ifdef HAVE_EVENT2_EVENT_H
- the_event_base = event_base_new();
+ {
+ struct event_config *cfg = event_config_new();
+
+#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS)
+ if (! torcfg->disable_iocp)
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
+#endif
+
+#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
+ if (torcfg->num_cpus > 0)
+ event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
+#endif
+
+ the_event_base = event_base_new_with_config(cfg);
+ }
#else
the_event_base = event_init();
#endif
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index f483d6ee6..ecf25806d 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -56,7 +56,12 @@ struct timeval;
int tor_event_base_loopexit(struct event_base *base, struct timeval *tv);
#endif
-void tor_libevent_initialize(void);
+typedef struct tor_libevent_cfg {
+ int disable_iocp;
+ int num_cpus;
+} tor_libevent_cfg;
+
+void tor_libevent_initialize(tor_libevent_cfg *cfg);
struct event_base *tor_libevent_get_base(void);
const char *tor_libevent_get_method(void);
void tor_check_libevent_version(const char *m, int server,
diff --git a/src/or/config.c b/src/or/config.c
index 6d8addeb2..23cad9268 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -224,6 +224,7 @@ static config_var_t _option_vars[] = {
V(DirReqStatistics, BOOL, "0"),
VAR("DirServer", LINELIST, DirServers, NULL),
V(DisableAllSwap, BOOL, "0"),
+ V(DisableIOCP, BOOL, "1"),
V(DNSPort, UINT, "0"),
V(DNSListenAddress, LINELIST, NULL),
V(DownloadExtraInfo, BOOL, "0"),
@@ -306,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"),
@@ -554,7 +555,7 @@ static int is_listening_on_low_port(uint16_t port_option,
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
-static void init_libevent(void);
+static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
/** Magic value for or_options_t. */
@@ -955,7 +956,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Set up libevent. (We need to do this before we can register the
* listeners as listeners.) */
if (running_tor && !libevent_initialized) {
- init_libevent();
+ init_libevent(options);
libevent_initialized = 1;
}
@@ -4891,13 +4892,29 @@ 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.
*/
static void
-init_libevent(void)
+init_libevent(const or_options_t *options)
{
const char *badness=NULL;
+ tor_libevent_cfg cfg;
+
+ tor_assert(options);
configure_libevent_logging();
/* If the kernel complains that some method (say, epoll) doesn't
@@ -4907,7 +4924,11 @@ init_libevent(void)
tor_check_libevent_header_compatibility();
- tor_libevent_initialize();
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.disable_iocp = options->DisableIOCP;
+ cfg.num_cpus = get_num_cpus(options);
+
+ tor_libevent_initialize(&cfg);
suppress_libevent_log_msg(NULL);
diff --git a/src/or/config.h b/src/or/config.h
index 7a4ba5c60..bd5827b4e 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 e5b2c7102..cfe9f3af9 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;
diff --git a/src/or/or.h b/src/or/or.h
index 4741cc341..d2a7714db 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2892,6 +2892,10 @@ typedef struct {
*/
double CircuitPriorityHalflife;
+ /** If true, do not enable IOCP on windows with bufferevents, even if
+ * we think we could. */
+ int DisableIOCP;
+
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */