mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-25 04:43:31 +01:00
Merge branch 'iocp_option'
This commit is contained in:
commit
3efaa30727
@ -6,4 +6,7 @@
|
|||||||
flag. Using this feature will make our networking code more flexible,
|
flag. Using this feature will make our networking code more flexible,
|
||||||
lets us stack layers on each other, and let us use more efficient
|
lets us stack layers on each other, and let us use more efficient
|
||||||
zero-copy transports where available.
|
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.
|
||||||
|
|
||||||
|
3
changes/cpudetect
Normal file
3
changes/cpudetect
Normal file
@ -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.
|
@ -226,7 +226,7 @@ dnl -------------------------------------------------------------------
|
|||||||
dnl Check for functions before libevent, since libevent-1.2 apparently
|
dnl Check for functions before libevent, since libevent-1.2 apparently
|
||||||
dnl exports strlcpy without defining it in a header.
|
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
|
using_custom_malloc=no
|
||||||
if test x$enable_openbsd_malloc = xyes ; then
|
if test x$enable_openbsd_malloc = xyes ; then
|
||||||
|
@ -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
|
networkstatus. This is an advanced option; you generally shouldn't have
|
||||||
to mess with it. (Default: not set.)
|
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
|
CLIENT OPTIONS
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -855,7 +860,9 @@ is non-zero):
|
|||||||
characters inclusive, and must contain only the characters [a-zA-Z0-9].
|
characters inclusive, and must contain only the characters [a-zA-Z0-9].
|
||||||
|
|
||||||
**NumCPUs** __num__::
|
**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__::
|
**ORPort** __PORT__::
|
||||||
Advertise this port to listen for connections from Tor clients and servers.
|
Advertise this port to listen for connections from Tor clients and servers.
|
||||||
|
@ -1898,6 +1898,52 @@ spawn_exit(void)
|
|||||||
#endif
|
#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.
|
/** Set *timeval to the current time of day. On error, log and terminate.
|
||||||
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
|
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
|
||||||
*/
|
*/
|
||||||
|
@ -522,6 +522,8 @@ void spawn_exit(void) ATTR_NORETURN;
|
|||||||
#undef TOR_IS_MULTITHREADED
|
#undef TOR_IS_MULTITHREADED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int compute_num_cpus(void);
|
||||||
|
|
||||||
/* Because we use threads instead of processes on most platforms (Windows,
|
/* Because we use threads instead of processes on most platforms (Windows,
|
||||||
* Linux, etc), we need locking for them. On platforms with poor thread
|
* Linux, etc), we need locking for them. On platforms with poor thread
|
||||||
* support or broken gethostbyname_r, these functions are no-ops. */
|
* support or broken gethostbyname_r, these functions are no-ops. */
|
||||||
|
@ -159,7 +159,7 @@ struct event_base *the_event_base = NULL;
|
|||||||
|
|
||||||
/** Initialize the Libevent library and set up the event base. */
|
/** Initialize the Libevent library and set up the event base. */
|
||||||
void
|
void
|
||||||
tor_libevent_initialize(void)
|
tor_libevent_initialize(tor_libevent_cfg *torcfg)
|
||||||
{
|
{
|
||||||
tor_assert(the_event_base == NULL);
|
tor_assert(the_event_base == NULL);
|
||||||
|
|
||||||
@ -171,7 +171,21 @@ tor_libevent_initialize(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_EVENT2_EVENT_H
|
#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
|
#else
|
||||||
the_event_base = event_init();
|
the_event_base = event_init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,7 +56,12 @@ struct timeval;
|
|||||||
int tor_event_base_loopexit(struct event_base *base, struct timeval *tv);
|
int tor_event_base_loopexit(struct event_base *base, struct timeval *tv);
|
||||||
#endif
|
#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);
|
struct event_base *tor_libevent_get_base(void);
|
||||||
const char *tor_libevent_get_method(void);
|
const char *tor_libevent_get_method(void);
|
||||||
void tor_check_libevent_version(const char *m, int server,
|
void tor_check_libevent_version(const char *m, int server,
|
||||||
|
@ -224,6 +224,7 @@ static config_var_t _option_vars[] = {
|
|||||||
V(DirReqStatistics, BOOL, "0"),
|
V(DirReqStatistics, BOOL, "0"),
|
||||||
VAR("DirServer", LINELIST, DirServers, NULL),
|
VAR("DirServer", LINELIST, DirServers, NULL),
|
||||||
V(DisableAllSwap, BOOL, "0"),
|
V(DisableAllSwap, BOOL, "0"),
|
||||||
|
V(DisableIOCP, BOOL, "1"),
|
||||||
V(DNSPort, UINT, "0"),
|
V(DNSPort, UINT, "0"),
|
||||||
V(DNSListenAddress, LINELIST, NULL),
|
V(DNSListenAddress, LINELIST, NULL),
|
||||||
V(DownloadExtraInfo, BOOL, "0"),
|
V(DownloadExtraInfo, BOOL, "0"),
|
||||||
@ -306,7 +307,7 @@ static config_var_t _option_vars[] = {
|
|||||||
V(WarnUnsafeSocks, BOOL, "1"),
|
V(WarnUnsafeSocks, BOOL, "1"),
|
||||||
V(NoPublish, BOOL, "0"),
|
V(NoPublish, BOOL, "0"),
|
||||||
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
|
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
|
||||||
V(NumCpus, UINT, "1"),
|
V(NumCpus, UINT, "0"),
|
||||||
V(NumEntryGuards, UINT, "3"),
|
V(NumEntryGuards, UINT, "3"),
|
||||||
V(ORListenAddress, LINELIST, NULL),
|
V(ORListenAddress, LINELIST, NULL),
|
||||||
V(ORPort, UINT, "0"),
|
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 uint64_t config_parse_memunit(const char *s, int *ok);
|
||||||
static int config_parse_interval(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);
|
static int opt_streq(const char *s1, const char *s2);
|
||||||
|
|
||||||
/** Magic value for or_options_t. */
|
/** 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
|
/* Set up libevent. (We need to do this before we can register the
|
||||||
* listeners as listeners.) */
|
* listeners as listeners.) */
|
||||||
if (running_tor && !libevent_initialized) {
|
if (running_tor && !libevent_initialized) {
|
||||||
init_libevent();
|
init_libevent(options);
|
||||||
libevent_initialized = 1;
|
libevent_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4891,13 +4892,29 @@ config_parse_interval(const char *s, int *ok)
|
|||||||
return (int)r;
|
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.
|
* Initialize the libevent library.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
init_libevent(void)
|
init_libevent(const or_options_t *options)
|
||||||
{
|
{
|
||||||
const char *badness=NULL;
|
const char *badness=NULL;
|
||||||
|
tor_libevent_cfg cfg;
|
||||||
|
|
||||||
|
tor_assert(options);
|
||||||
|
|
||||||
configure_libevent_logging();
|
configure_libevent_logging();
|
||||||
/* If the kernel complains that some method (say, epoll) doesn't
|
/* If the kernel complains that some method (say, epoll) doesn't
|
||||||
@ -4907,7 +4924,11 @@ init_libevent(void)
|
|||||||
|
|
||||||
tor_check_libevent_header_compatibility();
|
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);
|
suppress_libevent_log_msg(NULL);
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
|
|||||||
#define get_datadir_fname_suffix(sub1, suffix) \
|
#define get_datadir_fname_suffix(sub1, suffix) \
|
||||||
get_datadir_fname2_suffix((sub1), NULL, (suffix))
|
get_datadir_fname2_suffix((sub1), NULL, (suffix))
|
||||||
|
|
||||||
|
int get_num_cpus(const or_options_t *options);
|
||||||
|
|
||||||
or_state_t *get_or_state(void);
|
or_state_t *get_or_state(void);
|
||||||
int or_state_save(time_t now);
|
int or_state_save(time_t now);
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ spawn_cpuworker(void)
|
|||||||
static void
|
static void
|
||||||
spawn_enough_cpuworkers(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)
|
if (num_cpuworkers_needed < MIN_CPUWORKERS)
|
||||||
num_cpuworkers_needed = MIN_CPUWORKERS;
|
num_cpuworkers_needed = MIN_CPUWORKERS;
|
||||||
|
@ -2892,6 +2892,10 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
double CircuitPriorityHalflife;
|
double CircuitPriorityHalflife;
|
||||||
|
|
||||||
|
/** If true, do not enable IOCP on windows with bufferevents, even if
|
||||||
|
* we think we could. */
|
||||||
|
int DisableIOCP;
|
||||||
|
|
||||||
} or_options_t;
|
} or_options_t;
|
||||||
|
|
||||||
/** Persistent state for an onion router, as saved to disk. */
|
/** Persistent state for an onion router, as saved to disk. */
|
||||||
|
Loading…
Reference in New Issue
Block a user