static u64 calc_weight_factor(struct task_struct *p, task_ctx *taskc)
{
u64 weight_boost = 1;
if (test_task_flag(taskc, LAVD_FLAG_IS_WAKEUP))
weight_boost += LAVD_LC_WEIGHT_BOOST;
if (test_task_flag(taskc, LAVD_FLAG_IS_SYNC_WAKEUP))
weight_boost += LAVD_LC_WEIGHT_BOOST;
if (is_kernel_task(p))
weight_boost += 2 * LAVD_LC_WEIGHT_BOOST;
if (test_task_flag(taskc, LAVD_FLAG_KSOFTIRQD))
weight_boost += 4 * LAVD_LC_WEIGHT_BOOST;
if (is_kernel_worker(p))
weight_boost += LAVD_LC_WEIGHT_BOOST;
if (test_task_flag(taskc, LAVD_FLAG_IS_AFFINITIZED))
weight_boost += LAVD_LC_WEIGHT_BOOST;
if (is_pinned(p) || is_migration_disabled(p))
weight_boost += 2 * LAVD_LC_WEIGHT_BOOST;
if (test_task_flag(taskc, LAVD_FLAG_NEED_LOCK_BOOST)) {
reset_task_flag(taskc, LAVD_FLAG_NEED_LOCK_BOOST);
weight_boost += LAVD_LC_WEIGHT_BOOST;
}
return p->scx.weight * weight_boost + 1;
}
static u64 calc_wait_factor(task_ctx *taskc)
{
u64 freq = min(taskc->wait_freq, LAVD_LC_FREQ_MAX);
return freq + 1;
}
static u64 calc_wake_factor(task_ctx *taskc)
{
u64 freq = min(taskc->wake_freq, LAVD_LC_FREQ_MAX);
return freq + 1;
}
static inline u64 calc_reverse_runtime_factor(task_ctx *taskc)
{
if (LAVD_LC_RUNTIME_MAX > taskc->avg_runtime) {
u64 delta = LAVD_LC_RUNTIME_MAX - taskc->avg_runtime;
return delta / LAVD_SLICE_MIN_NS_DFL;
}
return 1;
}
static u64 calc_sum_runtime_factor(struct task_struct *p, task_ctx *taskc)
{
u64 runtime = max(taskc->avg_runtime, taskc->acc_runtime);
u64 sum = max(taskc->run_freq, 1) * max(runtime, 1);
return (sum >> LAVD_SHIFT) * p->scx.weight;
}
u32 __attribute__ ((noinline)) log2x(u64 v)
{
return log2_u64(v);
}
static void calc_lat_cri(struct task_struct *p, task_ctx *taskc)
{
u64 weight_ft, wait_ft, wake_ft, runtime_ft, sum_runtime_ft;
u64 log_wwf, lat_cri, perf_cri = LAVD_SCALE;
wait_ft = calc_wait_factor(taskc);
wake_ft = calc_wake_factor(taskc);
runtime_ft = calc_reverse_runtime_factor(taskc);
weight_ft = calc_weight_factor(p, taskc);
log_wwf = log2x(wait_ft * wake_ft);
lat_cri = log_wwf + log2x(runtime_ft * weight_ft);
lat_cri = lat_cri * lat_cri;
if (taskc->lat_cri_waker > lat_cri) {
u64 waker_inh = (taskc->lat_cri_waker - lat_cri) >>
LAVD_LC_INH_WAKER_SHIFT;
u64 wakee_max = lat_cri >> LAVD_LC_INH_WAKEE_SHIFT;
lat_cri += min(waker_inh, wakee_max);
}
taskc->lat_cri = lat_cri;
if (have_little_core) {
sum_runtime_ft = calc_sum_runtime_factor(p, taskc);
perf_cri = log_wwf + log2x(sum_runtime_ft);
}
taskc->perf_cri = perf_cri;
}
static u64 calc_greedy_penalty(task_ctx *taskc)
{
u64 ratio, penalty;
ratio = (taskc->svc_time << LAVD_SHIFT) / sys_stat.avg_svc_time;
if (ratio > LAVD_SCALE) {
penalty = LAVD_SCALE + ((ratio - LAVD_SCALE) >> LAVD_LC_GREEDY_SHIFT);
set_task_flag(taskc, LAVD_FLAG_IS_GREEDY);
} else {
penalty = LAVD_SCALE;
reset_task_flag(taskc, LAVD_FLAG_IS_GREEDY);
}
return penalty;
}
static u64 calc_adjusted_runtime(task_ctx *taskc)
{
u64 runtime;
runtime = LAVD_ACC_RUNTIME_MAX +
min(taskc->acc_runtime, LAVD_ACC_RUNTIME_MAX);
return runtime;
}
static u64 calc_virtual_deadline_delta(struct task_struct *p,
task_ctx *taskc)
{
u64 deadline, adjusted_runtime;
u32 greedy_penalty;
calc_lat_cri(p, taskc);
greedy_penalty = calc_greedy_penalty(taskc);
adjusted_runtime = calc_adjusted_runtime(taskc);
deadline = (adjusted_runtime * greedy_penalty) / taskc->lat_cri;
return deadline >> LAVD_SHIFT;
}
static u64 calc_when_to_run(struct task_struct *p, task_ctx *taskc)
{
u64 dl_delta, clc;
dl_delta = calc_virtual_deadline_delta(p, taskc);
clc = READ_ONCE(cur_logical_clk) - LAVD_DL_COMPETE_WINDOW;
return clc + dl_delta;
}