Skip to content

Commit 2614069

Browse files
author
Peter Zijlstra
committed
sched/deadline: Document dl_server
Place the notes that resulted from going through the dl_server code in a comment. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
1 parent f5a538c commit 2614069

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

kernel/sched/deadline.c

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,200 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
15951595
update_curr_dl_se(dl_se->rq, dl_se, delta_exec);
15961596
}
15971597

1598+
/*
1599+
* dl_server && dl_defer:
1600+
*
1601+
* 6
1602+
* +--------------------+
1603+
* v |
1604+
* +-------------+ 4 +-----------+ 5 +------------------+
1605+
* +-> | A:init | <--- | D:running | -----> | E:replenish-wait |
1606+
* | +-------------+ +-----------+ +------------------+
1607+
* | | | 1 ^ ^ |
1608+
* | | 1 +----------+ | 3 |
1609+
* | v | |
1610+
* | +--------------------------------+ 2 |
1611+
* | | | ----+ |
1612+
* | 8 | B:zero_laxity-wait | | |
1613+
* | | | <---+ |
1614+
* | +--------------------------------+ |
1615+
* | | ^ ^ 2 |
1616+
* | | 7 | 2 +--------------------+
1617+
* | v |
1618+
* | +-------------+ |
1619+
* +-- | C:idle-wait | -+
1620+
* +-------------+
1621+
* ^ 7 |
1622+
* +---------+
1623+
*
1624+
*
1625+
* [A] - init
1626+
* dl_server_active = 0
1627+
* dl_throttled = 0
1628+
* dl_defer_armed = 0
1629+
* dl_defer_running = 0/1
1630+
* dl_defer_idle = 0
1631+
*
1632+
* [B] - zero_laxity-wait
1633+
* dl_server_active = 1
1634+
* dl_throttled = 1
1635+
* dl_defer_armed = 1
1636+
* dl_defer_running = 0
1637+
* dl_defer_idle = 0
1638+
*
1639+
* [C] - idle-wait
1640+
* dl_server_active = 1
1641+
* dl_throttled = 1
1642+
* dl_defer_armed = 1
1643+
* dl_defer_running = 0
1644+
* dl_defer_idle = 1
1645+
*
1646+
* [D] - running
1647+
* dl_server_active = 1
1648+
* dl_throttled = 0
1649+
* dl_defer_armed = 0
1650+
* dl_defer_running = 1
1651+
* dl_defer_idle = 0
1652+
*
1653+
* [E] - replenish-wait
1654+
* dl_server_active = 1
1655+
* dl_throttled = 1
1656+
* dl_defer_armed = 0
1657+
* dl_defer_running = 1
1658+
* dl_defer_idle = 0
1659+
*
1660+
*
1661+
* [1] A->B, A->D
1662+
* dl_server_start()
1663+
* dl_server_active = 1;
1664+
* enqueue_dl_entity()
1665+
* update_dl_entity(WAKEUP)
1666+
* if (!dl_defer_running)
1667+
* dl_defer_armed = 1;
1668+
* dl_throttled = 1;
1669+
* if (dl_throttled && start_dl_timer())
1670+
* return; // [B]
1671+
* __enqueue_dl_entity();
1672+
* // [D]
1673+
*
1674+
* // deplete server runtime from client-class
1675+
* [2] B->B, C->B, E->B
1676+
* dl_server_update()
1677+
* update_curr_dl_se() // idle = false
1678+
* if (dl_defer_idle)
1679+
* dl_defer_idle = 0;
1680+
* if (dl_defer && dl_throttled && dl_runtime_exceeded())
1681+
* dl_defer_running = 0;
1682+
* hrtimer_try_to_cancel(); // stop timer
1683+
* replenish_dl_new_period()
1684+
* // fwd period
1685+
* dl_throttled = 1;
1686+
* dl_defer_armed = 1;
1687+
* start_dl_timer(); // restart timer
1688+
* // [B]
1689+
*
1690+
* // timer actually fires means we have runtime
1691+
* [3] B->D
1692+
* dl_server_timer()
1693+
* if (dl_defer_armed)
1694+
* dl_defer_running = 1;
1695+
* enqueue_dl_entity(REPLENISH)
1696+
* replenish_dl_entity()
1697+
* // fwd period
1698+
* if (dl_throttled)
1699+
* dl_throttled = 0;
1700+
* if (dl_defer_armed)
1701+
* dl_defer_armed = 0;
1702+
* __enqueue_dl_entity();
1703+
* // [D]
1704+
*
1705+
* // schedule server
1706+
* [4] D->A
1707+
* pick_task_dl()
1708+
* p = server_pick_task();
1709+
* if (!p)
1710+
* dl_server_stop()
1711+
* dequeue_dl_entity();
1712+
* hrtimer_try_to_cancel();
1713+
* dl_defer_armed = 0;
1714+
* dl_throttled = 0;
1715+
* dl_server_active = 0;
1716+
* // [A]
1717+
* return p;
1718+
*
1719+
* // server running
1720+
* [5] D->E
1721+
* update_curr_dl_se()
1722+
* if (dl_runtime_exceeded())
1723+
* dl_throttled = 1;
1724+
* dequeue_dl_entity();
1725+
* start_dl_timer();
1726+
* // [E]
1727+
*
1728+
* // server replenished
1729+
* [6] E->D
1730+
* dl_server_timer()
1731+
* enqueue_dl_entity(REPLENISH)
1732+
* replenish_dl_entity()
1733+
* fwd-period
1734+
* if (dl_throttled)
1735+
* dl_throttled = 0;
1736+
* __enqueue_dl_entity();
1737+
* // [D]
1738+
*
1739+
* // deplete server runtime from idle
1740+
* [7] B->C, C->C
1741+
* dl_server_update_idle()
1742+
* update_curr_dl_se() // idle = true
1743+
* if (dl_defer && dl_throttled && dl_runtime_exceeded())
1744+
* if (dl_defer_idle)
1745+
* return;
1746+
* dl_defer_running = 0;
1747+
* hrtimer_try_to_cancel();
1748+
* replenish_dl_new_period()
1749+
* // fwd period
1750+
* dl_throttled = 1;
1751+
* dl_defer_armed = 1;
1752+
* dl_defer_idle = 1;
1753+
* start_dl_timer(); // restart timer
1754+
* // [C]
1755+
*
1756+
* // stop idle server
1757+
* [8] C->A
1758+
* dl_server_timer()
1759+
* if (dl_defer_idle)
1760+
* dl_server_stop();
1761+
* // [A]
1762+
*
1763+
*
1764+
* digraph dl_server {
1765+
* "A:init" -> "B:zero_laxity-wait" [label="1:dl_server_start"]
1766+
* "A:init" -> "D:running" [label="1:dl_server_start"]
1767+
* "B:zero_laxity-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
1768+
* "B:zero_laxity-wait" -> "C:idle-wait" [label="7:dl_server_update_idle"]
1769+
* "B:zero_laxity-wait" -> "D:running" [label="3:dl_server_timer"]
1770+
* "C:idle-wait" -> "A:init" [label="8:dl_server_timer"]
1771+
* "C:idle-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
1772+
* "C:idle-wait" -> "C:idle-wait" [label="7:dl_server_update_idle"]
1773+
* "D:running" -> "A:init" [label="4:pick_task_dl"]
1774+
* "D:running" -> "E:replenish-wait" [label="5:update_curr_dl_se"]
1775+
* "E:replenish-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
1776+
* "E:replenish-wait" -> "D:running" [label="6:dl_server_timer"]
1777+
* }
1778+
*
1779+
*
1780+
* Notes:
1781+
*
1782+
* - When there are fair tasks running the most likely loop is [2]->[2].
1783+
* the dl_server never actually runs, the timer never fires.
1784+
*
1785+
* - When there is actual fair starvation; the timer fires and starts the
1786+
* dl_server. This will then throttle and replenish like a normal DL
1787+
* task. Notably it will not 'defer' again.
1788+
*
1789+
* - When idle it will push the actication forward once, and then wait
1790+
* for the timer to hit or a non-idle update to restart things.
1791+
*/
15981792
void dl_server_start(struct sched_dl_entity *dl_se)
15991793
{
16001794
struct rq *rq = dl_se->rq;

0 commit comments

Comments
 (0)