From a37a0c0e35cae9085460f70b02fa92bf9800028c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 11 Aug 2011 12:38:47 -0400 Subject: [PATCH] Make max_dispatch_interval able to apply only to low-priority events Suggested by Alexander Drozdov --- event-internal.h | 2 ++ event.c | 22 +++++++++++++++++----- include/event2/event.h | 16 +++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/event-internal.h b/event-internal.h index f495d6d2..a5f4afed 100644 --- a/event-internal.h +++ b/event-internal.h @@ -275,6 +275,7 @@ struct event_base { struct timeval max_dispatch_time; int max_dispatch_callbacks; + int limit_callbacks_after_prio; /* Notify main thread to wake up break, etc. */ /** True if the base already has a pending notify, and we don't need @@ -304,6 +305,7 @@ struct event_config { int n_cpus_hint; struct timeval max_dispatch_interval; int max_dispatch_callbacks; + int limit_callbacks_after_prio; enum event_method_feature require_features; enum event_base_config_flag flags; }; diff --git a/event.c b/event.c index baaef8cd..233e8897 100644 --- a/event.c +++ b/event.c @@ -587,16 +587,23 @@ event_base_new_with_config(const struct event_config *cfg) should_check_environment = !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV)); - if (cfg) + if (cfg) { memcpy(&base->max_dispatch_time, &cfg->max_dispatch_interval, sizeof(struct timeval)); - else + base->limit_callbacks_after_prio = + cfg->limit_callbacks_after_prio; + } else { base->max_dispatch_time.tv_sec = -1; + base->limit_callbacks_after_prio = 1; + } if (cfg && cfg->max_dispatch_callbacks >= 0) { base->max_dispatch_callbacks = cfg->max_dispatch_callbacks; } else { base->max_dispatch_callbacks = INT_MAX; } + if (base->max_dispatch_callbacks == INT_MAX && + base->max_dispatch_time.tv_sec == -1) + base->limit_callbacks_after_prio = INT_MAX; for (i = 0; eventops[i] && !base->evbase; i++) { if (cfg != NULL) { @@ -924,6 +931,7 @@ event_config_new(void) TAILQ_INIT(&cfg->entries); cfg->max_dispatch_interval.tv_sec = -1; cfg->max_dispatch_callbacks = INT_MAX; + cfg->limit_callbacks_after_prio = 1; return (cfg); } @@ -995,7 +1003,7 @@ event_config_set_num_cpus_hint(struct event_config *cfg, int cpus) int event_config_set_max_dispatch_interval(struct event_config *cfg, - const struct timeval *max_interval, int max_callbacks) + const struct timeval *max_interval, int max_callbacks, int min_priority) { if (max_interval) memcpy(&cfg->max_dispatch_interval, max_interval, @@ -1003,7 +1011,10 @@ event_config_set_max_dispatch_interval(struct event_config *cfg, else cfg->max_dispatch_interval.tv_sec = -1; cfg->max_dispatch_callbacks = - max_callbacks >= 0 ? max_callbacks : INT_MAX ; + max_callbacks >= 0 ? max_callbacks : INT_MAX; + if (min_priority <= 0) + min_priority = 1; + cfg->limit_callbacks_after_prio = min_priority; return (0); } @@ -1428,6 +1439,7 @@ event_process_active(struct event_base *base) const struct timeval *endtime; struct timeval tv; const int maxcb = base->max_dispatch_callbacks; + const int limit_after_prio = base->limit_callbacks_after_prio; if (base->max_dispatch_time.tv_sec >= 0) { evutil_gettimeofday(&tv, NULL); evutil_timeradd(&base->max_dispatch_time, &tv, &tv); @@ -1439,7 +1451,7 @@ event_process_active(struct event_base *base) for (i = 0; i < base->nactivequeues; ++i) { if (TAILQ_FIRST(&base->activequeues[i]) != NULL) { activeq = &base->activequeues[i]; - if (i == 0) + if (i < limit_after_prio) c = event_process_active_single_queue(base, activeq, INT_MAX, NULL); else diff --git a/include/event2/event.h b/include/event2/event.h index 7c2ab600..fae5bb87 100644 --- a/include/event2/event.h +++ b/include/event2/event.h @@ -550,9 +550,23 @@ int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus); * avoid priority inversions where multiple low-priority events keep us from * polling for high-priority events, but at the expense of slightly decreasing * the throughput. Use it with caution! + * + * @param cfg The event_base configuration object. + * @param max_interval An interval after which Libevent should stop running + * callbacks and check for more events, or NULL if there should be + * no such interval. + * @param max_callbacks A number of callbacks after which Libevent should + * stop running callbacks and check for more events, or -1 if there + * should be no such limit. + * @param min_priority A priority below which max_interval and max_callbacks + * should not be enforced. If this is set to 0, they are enforced + * for events of every priority; if it's set to 1, they're enforced + * for events of priority 1 and above, and so on. + * @return 0 on success, -1 on failure. **/ int event_config_set_max_dispatch_interval(struct event_config *cfg, - const struct timeval *max_interval, int max_callbacks); + const struct timeval *max_interval, int max_callbacks, + int min_priority); /** Initialize the event API.