History

sched/deadline: Fix dl_server runtime calculation formula

In our testing with 6.12 based kernel on a big.LITTLE system, we were seeing instances of RT tasks being blocked from running on the LITTLE cpus for multiple seconds of time, apparently by the dl_server. This far exceeds the default configured 50ms per second runtime. This is due to the fair dl_server runtime calculation being scaled for frequency & capacity of the cpu. Consider the following case under a Big.LITTLE architecture: Assume the runtime is: 50,000,000 ns, and Frequency/capacity scale-invariance defined as below: Frequency scale-invariance: 100 Capacity scale-invariance: 50 First by Frequency scale-invariance, the runtime is scaled to 50,000,000 * 100 >> 10 = 4,882,812 Then by capacity scale-invariance, it is further scaled to 4,882,812 * 50 >> 10 = 238,418. So it will scaled to 238,418 ns. This smaller "accounted runtime" value is what ends up being subtracted against the fair-server's runtime for the current period. Thus after 50ms of real time, we've only accounted ~238us against the fair servers runtime. This 209:1 ratio in this example means that on the smaller cpu the fair server is allowed to continue running, blocking RT tasks, for over 10 seconds before it exhausts its supposed 50ms of runtime. And on other hardware configurations it can be even worse. For the fair deadline_server, to prevent realtime tasks from being unexpectedly delayed, we really do want to use fixed time, and not scaled time for smaller capacity/frequency cpus. So remove the scaling from the fair server's accounting to fix this.

kuyo chang committed 1 year ago

Commit fc975cf1 parent 009836b1 file · +5 −5Browse files

Unified · Split

kernel/sched/deadline.c+5−5
@@ -1504,7 +1504,9 @@ static void update_curr_dl_se(struct rq *rq, struct sched_dl_entity *dl_se, s64 · 1503 unmodified lines
1504 if (dl_entity_is_special(dl_se))1504 if (dl_entity_is_special(dl_se))
1505 return;1505 return;
1506 1506
1507 scaled_delta_exec = dl_scaled_delta_exec(rq, dl_se, delta_exec);1507 scaled_delta_exec = delta_exec;
1508 if (!dl_server(dl_se))
1509 scaled_delta_exec = dl_scaled_delta_exec(rq, dl_se, delta_exec);
1508 1510
1509 dl_se->runtime -= scaled_delta_exec;1511 dl_se->runtime -= scaled_delta_exec;
1510 1512
@@ -1611,7 +1613,7 @@ throttle: · 100 unmodified lines
1611 */1613 */
1612void dl_server_update_idle_time(struct rq *rq, struct task_struct *p)1614void dl_server_update_idle_time(struct rq *rq, struct task_struct *p)
1613{1615{
1614 s64 delta_exec, scaled_delta_exec;1616 s64 delta_exec;
1615 1617
1616 if (!rq->fair_server.dl_defer)1618 if (!rq->fair_server.dl_defer)
1617 return;1619 return;
@@ -1624,9 +1626,7 @@ void dl_server_update_idle_time(struct rq *rq, struct task_struct *p) · 6 unmodified lines
1624 if (delta_exec < 0)1626 if (delta_exec < 0)
1625 return;1627 return;
1626 1628
1627 scaled_delta_exec = dl_scaled_delta_exec(rq, &rq->fair_server, delta_exec);1629 rq->fair_server.runtime -= delta_exec;
1628
1629 rq->fair_server.runtime -= scaled_delta_exec;
1630 1630
1631 if (rq->fair_server.runtime < 0) {1631 if (rq->fair_server.runtime < 0) {
1632 rq->fair_server.dl_defer_running = 0;1632 rq->fair_server.dl_defer_running = 0;