aboutsummaryrefslogtreecommitdiff
path: root/src/core/or/scheduler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/or/scheduler.c')
-rw-r--r--src/core/or/scheduler.c77
1 files changed, 40 insertions, 37 deletions
diff --git a/src/core/or/scheduler.c b/src/core/or/scheduler.c
index a3869c7ae3..072d78128b 100644
--- a/src/core/or/scheduler.c
+++ b/src/core/or/scheduler.c
@@ -42,7 +42,7 @@
* circuit scheduler. It was supposed to prioritize circuits across many
* channels, but wasn't effective. It is preserved in scheduler_vanilla.c.
*
- * [0]: http://www.robgjansen.com/publications/kist-sec2014.pdf
+ * [0]: https://www.robgjansen.com/publications/kist-sec2014.pdf
*
* Then we actually got around to implementing KIST for real. We decided to
* modularize the scheduler so new ones can be implemented. You can find KIST
@@ -502,7 +502,12 @@ scheduler_free_all(void)
the_scheduler = NULL;
}
-/** Mark a channel as no longer ready to accept writes. */
+/** Mark a channel as no longer ready to accept writes.
+ *
+ * Possible state changes:
+ * - SCHED_CHAN_PENDING -> SCHED_CHAN_WAITING_TO_WRITE
+ * - SCHED_CHAN_WAITING_FOR_CELLS -> SCHED_CHAN_IDLE
+ */
MOCK_IMPL(void,
scheduler_channel_doesnt_want_writes,(channel_t *chan))
{
@@ -513,31 +518,32 @@ scheduler_channel_doesnt_want_writes,(channel_t *chan))
return;
}
- /* If it's already in pending, we can put it in waiting_to_write */
if (chan->scheduler_state == SCHED_CHAN_PENDING) {
/*
- * It's in channels_pending, so it shouldn't be in any of
- * the other lists. It can't write any more, so it goes to
- * channels_waiting_to_write.
+ * It has cells but no longer can write, so it becomes
+ * SCHED_CHAN_WAITING_TO_WRITE. It's in channels_pending, so we
+ * should remove it from the list.
*/
smartlist_pqueue_remove(channels_pending,
scheduler_compare_channels,
offsetof(channel_t, sched_heap_idx),
chan);
scheduler_set_channel_state(chan, SCHED_CHAN_WAITING_TO_WRITE);
- } else {
+ } else if (chan->scheduler_state == SCHED_CHAN_WAITING_FOR_CELLS) {
/*
- * It's not in pending, so it can't become waiting_to_write; it's
- * either not in any of the lists (nothing to do) or it's already in
- * waiting_for_cells (remove it, can't write any more).
+ * It does not have cells and no longer can write, so it becomes
+ * SCHED_CHAN_IDLE.
*/
- if (chan->scheduler_state == SCHED_CHAN_WAITING_FOR_CELLS) {
- scheduler_set_channel_state(chan, SCHED_CHAN_IDLE);
- }
+ scheduler_set_channel_state(chan, SCHED_CHAN_IDLE);
}
}
-/** Mark a channel as having waiting cells. */
+/** Mark a channel as having waiting cells.
+ *
+ * Possible state changes:
+ * - SCHED_CHAN_WAITING_FOR_CELLS -> SCHED_CHAN_PENDING
+ * - SCHED_CHAN_IDLE -> SCHED_CHAN_WAITING_TO_WRITE
+ */
MOCK_IMPL(void,
scheduler_channel_has_waiting_cells,(channel_t *chan))
{
@@ -548,12 +554,11 @@ scheduler_channel_has_waiting_cells,(channel_t *chan))
return;
}
- /* First, check if it's also writeable */
if (chan->scheduler_state == SCHED_CHAN_WAITING_FOR_CELLS) {
/*
- * It's in channels_waiting_for_cells, so it shouldn't be in any of
- * the other lists. It has waiting cells now, so it goes to
- * channels_pending.
+ * It is able to write and now has cells, so it becomes
+ * SCHED_CHAN_PENDING. It must be added to the channels_pending
+ * list.
*/
scheduler_set_channel_state(chan, SCHED_CHAN_PENDING);
if (!SCHED_BUG(chan->sched_heap_idx != -1, chan)) {
@@ -565,16 +570,12 @@ scheduler_channel_has_waiting_cells,(channel_t *chan))
/* If we made a channel pending, we potentially have scheduling work to
* do. */
the_scheduler->schedule();
- } else {
+ } else if (chan->scheduler_state == SCHED_CHAN_IDLE) {
/*
- * It's not in waiting_for_cells, so it can't become pending; it's
- * either not in any of the lists (we add it to waiting_to_write)
- * or it's already in waiting_to_write or pending (we do nothing)
+ * It is not able to write but now has cells, so it becomes
+ * SCHED_CHAN_WAITING_TO_WRITE.
*/
- if (!(chan->scheduler_state == SCHED_CHAN_WAITING_TO_WRITE ||
- chan->scheduler_state == SCHED_CHAN_PENDING)) {
- scheduler_set_channel_state(chan, SCHED_CHAN_WAITING_TO_WRITE);
- }
+ scheduler_set_channel_state(chan, SCHED_CHAN_WAITING_TO_WRITE);
}
}
@@ -662,8 +663,12 @@ scheduler_release_channel,(channel_t *chan))
scheduler_set_channel_state(chan, SCHED_CHAN_IDLE);
}
-/** Mark a channel as ready to accept writes */
-
+/** Mark a channel as ready to accept writes.
+ * Possible state changes:
+ *
+ * - SCHED_CHAN_WAITING_TO_WRITE -> SCHED_CHAN_PENDING
+ * - SCHED_CHAN_IDLE -> SCHED_CHAN_WAITING_FOR_CELLS
+ */
void
scheduler_channel_wants_writes(channel_t *chan)
{
@@ -674,10 +679,11 @@ scheduler_channel_wants_writes(channel_t *chan)
return;
}
- /* If it's already in waiting_to_write, we can put it in pending */
if (chan->scheduler_state == SCHED_CHAN_WAITING_TO_WRITE) {
/*
- * It can write now, so it goes to channels_pending.
+ * It has cells and can now write, so it becomes
+ * SCHED_CHAN_PENDING. It must be added to the channels_pending
+ * list.
*/
scheduler_set_channel_state(chan, SCHED_CHAN_PENDING);
if (!SCHED_BUG(chan->sched_heap_idx != -1, chan)) {
@@ -688,15 +694,12 @@ scheduler_channel_wants_writes(channel_t *chan)
}
/* We just made a channel pending, we have scheduling work to do. */
the_scheduler->schedule();
- } else {
+ } else if (chan->scheduler_state == SCHED_CHAN_IDLE) {
/*
- * It's not in SCHED_CHAN_WAITING_TO_WRITE, so it can't become pending;
- * it's either idle and goes to WAITING_FOR_CELLS, or it's a no-op.
+ * It does not have cells but can now write, so it becomes
+ * SCHED_CHAN_WAITING_FOR_CELLS.
*/
- if (!(chan->scheduler_state == SCHED_CHAN_WAITING_FOR_CELLS ||
- chan->scheduler_state == SCHED_CHAN_PENDING)) {
- scheduler_set_channel_state(chan, SCHED_CHAN_WAITING_FOR_CELLS);
- }
+ scheduler_set_channel_state(chan, SCHED_CHAN_WAITING_FOR_CELLS);
}
}