blob: 6f9db64fd5b0b9b9475d4973469c2139b40dff54 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/console.h>
#include <lib/counters.h>
#include <lib/load_balancer.h>
#include <lib/system-topology.h>
#include <trace.h>
#include <ktl/atomic.h>
#include <lk/init.h>
#define LOCAL_TRACE 0
namespace {
#if !DISABLE_PERIODIC_LOAD_BALANCER
// This value is a tradeoff between how long the cycle takes to run and how fresh the
// resulting data is. At the time of implementation the cycle takes 1.5us to run, so we
// want the period to be sufficiently high that it is predominantly sleeping. However
// this generates information that guides thread placement and the more recent that
// information is the more efficient our thread placement will be.
constexpr zx_duration_t kPeriod = ZX_MSEC(20);
ktl::atomic<bool> print_state = false;
int load_balancer_thread(void*) {
LTRACEF("Load Balancer Thread running.\n");
load_balancer::LoadBalancer<> balancer;
while (true) {
const zx_time_t start = current_time();
balancer.Cycle();
if (print_state) {
balancer.PrintState();
print_state = false;
}
const zx_duration_t cycle_duration = zx_time_sub_time(current_time(), start);
// In practice the cycle_duration is fairly small but we compensate for it to
// keep to our period.
Thread::Current::SleepRelative(zx_time_sub_duration(kPeriod, cycle_duration));
}
// This thread should never exit.
ASSERT(false);
return 0;
}
void load_balancer_init(uint) {
Thread::Create("load-balancer-thread", load_balancer_thread, nullptr, DEFAULT_PRIORITY)
->DetachAndResume();
LTRACEF("Load Balancer Thread detached.\n");
}
// We want to run before the system goes fully threaded to set the initial
// values for early core load shedding. If we don't threads won't move cores and
// we will lose out potential parrallelism in early boot.
LK_INIT_HOOK(load_balancer_init, &load_balancer_init, LK_INIT_LEVEL_TOPOLOGY)
static int cmd_lb(int argc, const cmd_args* argv, uint32_t flags) {
if (argc < 2) {
printf("not enough arguments\n");
printf("usage:\n");
printf("%s state - print state to console\n", argv[0].str);
return ZX_ERR_INTERNAL;
}
if (strcmp(argv[1].str, "state") == 0) {
print_state.store(true);
}
return ZX_OK;
}
STATIC_COMMAND_START
STATIC_COMMAND("lb",
"Thread Load balancer commands, responsible for balacing processing "
"load across processors.",
&cmd_lb)
STATIC_COMMAND_END(lb)
#endif
} // namespace