aboutsummaryrefslogtreecommitdiff
path: root/src/common/compat_libevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/compat_libevent.c')
-rw-r--r--src/common/compat_libevent.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 3ad9be145..c338dd6c0 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -48,7 +48,7 @@ typedef uint32_t le_version_t;
* it is. */
#define LE_OLD V(0,0,0)
/** Represents a version of libevent so weird we can't figure out what version
- * it it. */
+ * it is. */
#define LE_OTHER V(0,0,99)
static le_version_t tor_get_libevent_version(const char **v_out);
@@ -165,9 +165,11 @@ 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);
+ /* some paths below don't use torcfg, so avoid unused variable warnings */
+ (void)torcfg;
#ifdef __APPLE__
if (MACOSX_KQUEUE_IS_BROKEN ||
@@ -177,7 +179,29 @@ 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
+
+#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
+ /* We can enable changelist support with epoll, since we don't give
+ * Libevent any dup'd fds. This lets us avoid some syscalls. */
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
+#endif
+
+ the_event_base = event_base_new_with_config(cfg);
+
+ event_config_free(cfg);
+ }
#else
the_event_base = event_init();
#endif
@@ -240,7 +264,7 @@ tor_decode_libevent_version(const char *v)
/* Try the new preferred "1.4.11-stable" format.
* Also accept "1.4.14b-stable". */
- fields = sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
+ fields = tor_sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
if (fields == 3 ||
((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
(fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
@@ -248,7 +272,7 @@ tor_decode_libevent_version(const char *v)
}
/* Try the old "1.3e" format. */
- fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
+ fields = tor_sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
if (fields == 3 && TOR_ISALPHA(c)) {
return V_OLD(major, minor, c);
} else if (fields == 2) {
@@ -552,3 +576,29 @@ periodic_timer_free(periodic_timer_t *timer)
tor_free(timer);
}
+#ifdef USE_BUFFEREVENTS
+static const struct timeval *one_tick = NULL;
+/**
+ * Return a special timeout to be passed whenever libevent's O(1) timeout
+ * implementation should be used. Only use this when the timer is supposed
+ * to fire after 1 / TOR_LIBEVENT_TICKS_PER_SECOND seconds have passed.
+*/
+const struct timeval *
+tor_libevent_get_one_tick_timeout(void)
+{
+ if (PREDICT_UNLIKELY(one_tick == NULL)) {
+ struct event_base *base = tor_libevent_get_base();
+ struct timeval tv;
+ if (TOR_LIBEVENT_TICKS_PER_SECOND == 1) {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000000 / TOR_LIBEVENT_TICKS_PER_SECOND;
+ }
+ one_tick = event_base_init_common_timeout(base, &tv);
+ }
+ return one_tick;
+}
+#endif
+