aboutsummaryrefslogtreecommitdiff
path: root/src/or/scheduler.c
diff options
context:
space:
mode:
authorAndrea Shepard <andrea@torproject.org>2013-12-02 01:05:28 -0800
committerAndrea Shepard <andrea@torproject.org>2014-09-30 22:49:36 -0700
commit55907da28dd933a7724935a8a4676aec1b54059d (patch)
treef6de0d9af2f85b07b6023ac626725d7583a2400d /src/or/scheduler.c
parent700d6e75258fb94819df3da686482dd8565e3691 (diff)
downloadtor-55907da28dd933a7724935a8a4676aec1b54059d.tar.gz
tor-55907da28dd933a7724935a8a4676aec1b54059d.zip
Sort the scheduler's channel list by cmux comparisons
Diffstat (limited to 'src/or/scheduler.c')
-rw-r--r--src/or/scheduler.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/src/or/scheduler.c b/src/or/scheduler.c
index 1baf3750d6..b45df3ebfc 100644
--- a/src/or/scheduler.c
+++ b/src/or/scheduler.c
@@ -139,6 +139,7 @@ static time_t queue_heuristic_timestamp = 0;
/* Scheduler static function declarations */
+static int scheduler_compare_channels(const void **c1_v, const void **c2_v);
static void scheduler_evt_callback(evutil_socket_t fd,
short events, void *arg);
static int scheduler_more_work(void);
@@ -180,6 +181,52 @@ scheduler_free_all(void)
}
}
+/**
+ * Comparison function to use when sorting pending channels
+ */
+
+static int
+scheduler_compare_channels(const void **c1_v, const void **c2_v)
+{
+ channel_t *c1 = NULL, *c2 = NULL;
+ /* These are a workaround for -Wbad-function-cast throwing a fit */
+ const circuitmux_policy_t *p1, *p2;
+ uintptr_t p1_i, p2_i;
+
+ tor_assert(c1_v);
+ tor_assert(c2_v);
+
+ c1 = (channel_t *)(*c1_v);
+ c2 = (channel_t *)(*c2_v);
+
+ tor_assert(c1);
+ tor_assert(c2);
+
+ if (c1 != c2) {
+ if (circuitmux_get_policy(c1->cmux) ==
+ circuitmux_get_policy(c2->cmux)) {
+ /* Same cmux policy, so use the mux comparison */
+ return circuitmux_compare_muxes(c1->cmux, c2->cmux);
+ } else {
+ /*
+ * Different policies; not important to get this edge case perfect
+ * because the current code never actually gives different channels
+ * different cmux policies anyway. Just use this arbitrary but
+ * definite choice.
+ */
+ p1 = circuitmux_get_policy(c1->cmux);
+ p2 = circuitmux_get_policy(c2->cmux);
+ p1_i = (uintptr_t)p1;
+ p2_i = (uintptr_t)p2;
+
+ return (p1_i < p2_i) ? -1 : 1;
+ }
+ } else {
+ /* c1 == c2, so always equal */
+ return 0;
+ }
+}
+
/*
* Scheduler event callback; this should get triggered once per event loop
* if any scheduling work was created during the event loop.
@@ -362,9 +409,11 @@ scheduler_run(void)
channels_pending = smartlist_new();
/*
- * For now, just run the old scheduler on all the chans in the list, until
- * we hit the high-water mark. TODO real channel priority API
+ * UGLY HACK: sort the list on each invocation
+ *
+ * TODO smarter data structures
*/
+ smartlist_sort(tmp, scheduler_compare_channels);
SMARTLIST_FOREACH_BEGIN(tmp, channel_t *, chan) {
if (scheduler_get_queue_heuristic() <= SCHED_Q_HIGH_WATER) {