From 3072fd1ace691948570a46d2bd0d305330bf949e Mon Sep 17 00:00:00 2001 From: Derek Bruening Date: Wed, 23 Oct 2024 15:19:09 -0400 Subject: [PATCH] i#6938 sched migrate: Add missing check for work stealing (#7052) Add a missing check that we're doing a dynamic schedule before trying to steal work when idle. There don't seem to be any consequences from the missing check but it is best to have it for clarity. Issue: #6938 --- clients/drcachesim/scheduler/scheduler.cpp | 47 ++++++++++++---------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/clients/drcachesim/scheduler/scheduler.cpp b/clients/drcachesim/scheduler/scheduler.cpp index d22d94e29a3..73f66590a28 100644 --- a/clients/drcachesim/scheduler/scheduler.cpp +++ b/clients/drcachesim/scheduler/scheduler.cpp @@ -4374,29 +4374,34 @@ scheduler_tmpl_t::eof_or_idle(output_ordinal_t output, live_inputs); return sched_type_t::STATUS_EOF; } - // Before going idle, try to steal work from another output. - // We start with us+1 to avoid everyone stealing from the low-numbered outputs. - // We only try when we first transition to idle; we rely on rebalancing after that, - // to avoid repeatededly grabbing other output's locks over and over. - if (!outputs_[output].tried_to_steal_on_idle) { - outputs_[output].tried_to_steal_on_idle = true; - for (unsigned int i = 1; i < outputs_.size(); ++i) { - output_ordinal_t target = (output + i) % outputs_.size(); - assert(target != output); // Sanity check (we won't reach "output"). - input_info_t *queue_next = nullptr; - sched_type_t::stream_status_t status = - pop_from_ready_queue(target, output, queue_next); - if (status == STATUS_OK && queue_next != nullptr) { - set_cur_input(output, queue_next->index); - ++outputs_[output].stats[memtrace_stream_t::SCHED_STAT_RUNQUEUE_STEALS]; - VPRINT(this, 2, - "eof_or_idle: output %d stole input %d from %d's ready_queue\n", - output, queue_next->index, target); - return STATUS_STOLE; + if (options_.mapping == MAP_TO_ANY_OUTPUT) { + // Before going idle, try to steal work from another output. + // We start with us+1 to avoid everyone stealing from the low-numbered outputs. + // We only try when we first transition to idle; we rely on rebalancing after + // that, to avoid repeatededly grabbing other output's locks over and over. + if (!outputs_[output].tried_to_steal_on_idle) { + outputs_[output].tried_to_steal_on_idle = true; + for (unsigned int i = 1; i < outputs_.size(); ++i) { + output_ordinal_t target = (output + i) % outputs_.size(); + assert(target != output); // Sanity check (we won't reach "output"). + input_info_t *queue_next = nullptr; + sched_type_t::stream_status_t status = + pop_from_ready_queue(target, output, queue_next); + if (status == STATUS_OK && queue_next != nullptr) { + set_cur_input(output, queue_next->index); + ++outputs_[output] + .stats[memtrace_stream_t::SCHED_STAT_RUNQUEUE_STEALS]; + VPRINT( + this, 2, + "eof_or_idle: output %d stole input %d from %d's ready_queue\n", + output, queue_next->index, target); + return STATUS_STOLE; + } + // We didn't find anything; loop and check another output. } - // We didn't find anything; loop and check another output. + VPRINT(this, 3, "eof_or_idle: output %d failed to steal from anyone\n", + output); } - VPRINT(this, 3, "eof_or_idle: output %d failed to steal from anyone\n", output); } // We rely on rebalancing to handle the case of every input being unscheduled. outputs_[output].waiting = true;