summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bufferevent-support3
-rw-r--r--doc/tor.1.txt5
-rw-r--r--src/common/compat_libevent.c18
-rw-r--r--src/common/compat_libevent.h7
-rw-r--r--src/or/config.c16
-rw-r--r--src/or/or.h4
6 files changed, 46 insertions, 7 deletions
diff --git a/changes/bufferevent-support b/changes/bufferevent-support
index 22ee50ebff..e39c36f13b 100644
--- a/changes/bufferevent-support
+++ b/changes/bufferevent-support
@@ -6,4 +6,7 @@
flag. Using this feature will make our networking code more flexible,
lets us stack layers on each other, and let us use more efficient
zero-copy transports where available.
+ - As an experimental feature, when using the "bufferevents" buffered
+ IO backend, Tor can try to use Windows's IOCP networking API. This
+ is off by default. To turn it on, add "DisableIOCP 0" to your torrc.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 620f938741..e9ef55166c 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -397,6 +397,11 @@ Other options can be specified either on the command-line (--option
networkstatus. This is an advanced option; you generally shouldn't have
to mess with it. (Default: not set.)
+**DisableIOCP** **0**|**1**::
+ If Tor was built to use the Libevent's "bufferevents" networking code
+ and you're running on Windows, setting this option to 1 will tell Libevent
+ not to use the Windows IOCP networking API. (Default: 1)
+
CLIENT OPTIONS
--------------
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index bbab06e8d4..6afd3c1d29 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 f483d6ee6d..ecf25806d5 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 6d8addeb2d..c5b0ccf586 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"),
@@ -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;
}
@@ -4895,9 +4896,12 @@ config_parse_interval(const char *s, int *ok)
* 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 +4911,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 = options->NumCpus;
+
+ tor_libevent_initialize(&cfg);
suppress_libevent_log_msg(NULL);
diff --git a/src/or/or.h b/src/or/or.h
index 4741cc341b..d2a7714db3 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. */