Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'sched-urgent-2025-09-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull scheduler fixes from Ingo Molnar:
"Fix two dl_server regressions: a race that can end up leaving the
dl_server stuck, and a dl_server throttling bug causing lag to fair
tasks"

* tag 'sched-urgent-2025-09-26' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
sched/deadline: Fix dl_server behaviour
sched/deadline: Fix dl_server getting stuck

+35 -46
-2
include/linux/sched.h
··· 706 706 unsigned int dl_defer : 1; 707 707 unsigned int dl_defer_armed : 1; 708 708 unsigned int dl_defer_running : 1; 709 - unsigned int dl_server_idle : 1; 710 709 711 710 /* 712 711 * Bandwidth enforcement timer. Each -deadline task has its ··· 732 733 * runnable task. 733 734 */ 734 735 struct rq *rq; 735 - dl_server_has_tasks_f server_has_tasks; 736 736 dl_server_pick_f server_pick_task; 737 737 738 738 #ifdef CONFIG_RT_MUTEXES
+3 -32
kernel/sched/deadline.c
··· 875 875 */ 876 876 if (dl_se->dl_defer && !dl_se->dl_defer_running && 877 877 dl_time_before(rq_clock(dl_se->rq), dl_se->deadline - dl_se->runtime)) { 878 - if (!is_dl_boosted(dl_se) && dl_se->server_has_tasks(dl_se)) { 878 + if (!is_dl_boosted(dl_se)) { 879 879 880 880 /* 881 881 * Set dl_se->dl_defer_armed and dl_throttled variables to ··· 1152 1152 /* a defer timer will not be reset if the runtime consumed was < dl_server_min_res */ 1153 1153 static const u64 dl_server_min_res = 1 * NSEC_PER_MSEC; 1154 1154 1155 - static bool dl_server_stopped(struct sched_dl_entity *dl_se); 1156 - 1157 1155 static enum hrtimer_restart dl_server_timer(struct hrtimer *timer, struct sched_dl_entity *dl_se) 1158 1156 { 1159 1157 struct rq *rq = rq_of_dl_se(dl_se); ··· 1168 1170 1169 1171 if (!dl_se->dl_runtime) 1170 1172 return HRTIMER_NORESTART; 1171 - 1172 - if (!dl_se->server_has_tasks(dl_se)) { 1173 - replenish_dl_entity(dl_se); 1174 - dl_server_stopped(dl_se); 1175 - return HRTIMER_NORESTART; 1176 - } 1177 1173 1178 1174 if (dl_se->dl_defer_armed) { 1179 1175 /* ··· 1571 1579 void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec) 1572 1580 { 1573 1581 /* 0 runtime = fair server disabled */ 1574 - if (dl_se->dl_runtime) { 1575 - dl_se->dl_server_idle = 0; 1582 + if (dl_se->dl_runtime) 1576 1583 update_curr_dl_se(dl_se->rq, dl_se, delta_exec); 1577 - } 1578 1584 } 1579 1585 1580 1586 void dl_server_start(struct sched_dl_entity *dl_se) ··· 1600 1610 dl_se->dl_server_active = 0; 1601 1611 } 1602 1612 1603 - static bool dl_server_stopped(struct sched_dl_entity *dl_se) 1604 - { 1605 - if (!dl_se->dl_server_active) 1606 - return true; 1607 - 1608 - if (dl_se->dl_server_idle) { 1609 - dl_server_stop(dl_se); 1610 - return true; 1611 - } 1612 - 1613 - dl_se->dl_server_idle = 1; 1614 - return false; 1615 - } 1616 - 1617 1613 void dl_server_init(struct sched_dl_entity *dl_se, struct rq *rq, 1618 - dl_server_has_tasks_f has_tasks, 1619 1614 dl_server_pick_f pick_task) 1620 1615 { 1621 1616 dl_se->rq = rq; 1622 - dl_se->server_has_tasks = has_tasks; 1623 1617 dl_se->server_pick_task = pick_task; 1624 1618 } 1625 1619 ··· 2368 2394 if (dl_server(dl_se)) { 2369 2395 p = dl_se->server_pick_task(dl_se); 2370 2396 if (!p) { 2371 - if (!dl_server_stopped(dl_se)) { 2372 - dl_se->dl_yielded = 1; 2373 - update_curr_dl_se(rq, dl_se, 0); 2374 - } 2397 + dl_server_stop(dl_se); 2375 2398 goto again; 2376 2399 } 2377 2400 rq->dl_server = dl_se;
+1 -6
kernel/sched/fair.c
··· 8859 8859 return pick_next_task_fair(rq, prev, NULL); 8860 8860 } 8861 8861 8862 - static bool fair_server_has_tasks(struct sched_dl_entity *dl_se) 8863 - { 8864 - return !!dl_se->rq->cfs.nr_queued; 8865 - } 8866 - 8867 8862 static struct task_struct *fair_server_pick_task(struct sched_dl_entity *dl_se) 8868 8863 { 8869 8864 return pick_task_fair(dl_se->rq); ··· 8870 8875 8871 8876 init_dl_entity(dl_se); 8872 8877 8873 - dl_server_init(dl_se, rq, fair_server_has_tasks, fair_server_pick_task); 8878 + dl_server_init(dl_se, rq, fair_server_pick_task); 8874 8879 } 8875 8880 8876 8881 /*
+31 -6
kernel/sched/sched.h
··· 365 365 * 366 366 * dl_se::rq -- runqueue we belong to. 367 367 * 368 - * dl_se::server_has_tasks() -- used on bandwidth enforcement; we 'stop' the 369 - * server when it runs out of tasks to run. 370 - * 371 368 * dl_se::server_pick() -- nested pick_next_task(); we yield the period if this 372 369 * returns NULL. 373 370 * 374 371 * dl_server_update() -- called from update_curr_common(), propagates runtime 375 372 * to the server. 376 373 * 377 - * dl_server_start() 378 - * dl_server_stop() -- start/stop the server when it has (no) tasks. 374 + * dl_server_start() -- start the server when it has tasks; it will stop 375 + * automatically when there are no more tasks, per 376 + * dl_se::server_pick() returning NULL. 377 + * 378 + * dl_server_stop() -- (force) stop the server; use when updating 379 + * parameters. 379 380 * 380 381 * dl_server_init() -- initializes the server. 382 + * 383 + * When started the dl_server will (per dl_defer) schedule a timer for its 384 + * zero-laxity point -- that is, unlike regular EDF tasks which run ASAP, a 385 + * server will run at the very end of its period. 386 + * 387 + * This is done such that any runtime from the target class can be accounted 388 + * against the server -- through dl_server_update() above -- such that when it 389 + * becomes time to run, it might already be out of runtime and get deferred 390 + * until the next period. In this case dl_server_timer() will alternate 391 + * between defer and replenish but never actually enqueue the server. 392 + * 393 + * Only when the target class does not manage to exhaust the server's runtime 394 + * (there's actualy starvation in the given period), will the dl_server get on 395 + * the runqueue. Once queued it will pick tasks from the target class and run 396 + * them until either its runtime is exhaused, at which point its back to 397 + * dl_server_timer, or until there are no more tasks to run, at which point 398 + * the dl_server stops itself. 399 + * 400 + * By stopping at this point the dl_server retains bandwidth, which, if a new 401 + * task wakes up imminently (starting the server again), can be used -- 402 + * subject to CBS wakeup rules -- without having to wait for the next period. 403 + * 404 + * Additionally, because of the dl_defer behaviour the start/stop behaviour is 405 + * naturally thottled to once per period, avoiding high context switch 406 + * workloads from spamming the hrtimer program/cancel paths. 381 407 */ 382 408 extern void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec); 383 409 extern void dl_server_start(struct sched_dl_entity *dl_se); 384 410 extern void dl_server_stop(struct sched_dl_entity *dl_se); 385 411 extern void dl_server_init(struct sched_dl_entity *dl_se, struct rq *rq, 386 - dl_server_has_tasks_f has_tasks, 387 412 dl_server_pick_f pick_task); 388 413 extern void sched_init_dl_servers(void); 389 414