mirror of https://github.com/torvalds/linux.git
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>
This commit is contained in:
parent
f5a538c07d
commit
2614069c59
|
|
@ -1595,6 +1595,200 @@ void dl_server_update(struct sched_dl_entity *dl_se, s64 delta_exec)
|
|||
update_curr_dl_se(dl_se->rq, dl_se, delta_exec);
|
||||
}
|
||||
|
||||
/*
|
||||
* dl_server && dl_defer:
|
||||
*
|
||||
* 6
|
||||
* +--------------------+
|
||||
* v |
|
||||
* +-------------+ 4 +-----------+ 5 +------------------+
|
||||
* +-> | A:init | <--- | D:running | -----> | E:replenish-wait |
|
||||
* | +-------------+ +-----------+ +------------------+
|
||||
* | | | 1 ^ ^ |
|
||||
* | | 1 +----------+ | 3 |
|
||||
* | v | |
|
||||
* | +--------------------------------+ 2 |
|
||||
* | | | ----+ |
|
||||
* | 8 | B:zero_laxity-wait | | |
|
||||
* | | | <---+ |
|
||||
* | +--------------------------------+ |
|
||||
* | | ^ ^ 2 |
|
||||
* | | 7 | 2 +--------------------+
|
||||
* | v |
|
||||
* | +-------------+ |
|
||||
* +-- | C:idle-wait | -+
|
||||
* +-------------+
|
||||
* ^ 7 |
|
||||
* +---------+
|
||||
*
|
||||
*
|
||||
* [A] - init
|
||||
* dl_server_active = 0
|
||||
* dl_throttled = 0
|
||||
* dl_defer_armed = 0
|
||||
* dl_defer_running = 0/1
|
||||
* dl_defer_idle = 0
|
||||
*
|
||||
* [B] - zero_laxity-wait
|
||||
* dl_server_active = 1
|
||||
* dl_throttled = 1
|
||||
* dl_defer_armed = 1
|
||||
* dl_defer_running = 0
|
||||
* dl_defer_idle = 0
|
||||
*
|
||||
* [C] - idle-wait
|
||||
* dl_server_active = 1
|
||||
* dl_throttled = 1
|
||||
* dl_defer_armed = 1
|
||||
* dl_defer_running = 0
|
||||
* dl_defer_idle = 1
|
||||
*
|
||||
* [D] - running
|
||||
* dl_server_active = 1
|
||||
* dl_throttled = 0
|
||||
* dl_defer_armed = 0
|
||||
* dl_defer_running = 1
|
||||
* dl_defer_idle = 0
|
||||
*
|
||||
* [E] - replenish-wait
|
||||
* dl_server_active = 1
|
||||
* dl_throttled = 1
|
||||
* dl_defer_armed = 0
|
||||
* dl_defer_running = 1
|
||||
* dl_defer_idle = 0
|
||||
*
|
||||
*
|
||||
* [1] A->B, A->D
|
||||
* dl_server_start()
|
||||
* dl_server_active = 1;
|
||||
* enqueue_dl_entity()
|
||||
* update_dl_entity(WAKEUP)
|
||||
* if (!dl_defer_running)
|
||||
* dl_defer_armed = 1;
|
||||
* dl_throttled = 1;
|
||||
* if (dl_throttled && start_dl_timer())
|
||||
* return; // [B]
|
||||
* __enqueue_dl_entity();
|
||||
* // [D]
|
||||
*
|
||||
* // deplete server runtime from client-class
|
||||
* [2] B->B, C->B, E->B
|
||||
* dl_server_update()
|
||||
* update_curr_dl_se() // idle = false
|
||||
* if (dl_defer_idle)
|
||||
* dl_defer_idle = 0;
|
||||
* if (dl_defer && dl_throttled && dl_runtime_exceeded())
|
||||
* dl_defer_running = 0;
|
||||
* hrtimer_try_to_cancel(); // stop timer
|
||||
* replenish_dl_new_period()
|
||||
* // fwd period
|
||||
* dl_throttled = 1;
|
||||
* dl_defer_armed = 1;
|
||||
* start_dl_timer(); // restart timer
|
||||
* // [B]
|
||||
*
|
||||
* // timer actually fires means we have runtime
|
||||
* [3] B->D
|
||||
* dl_server_timer()
|
||||
* if (dl_defer_armed)
|
||||
* dl_defer_running = 1;
|
||||
* enqueue_dl_entity(REPLENISH)
|
||||
* replenish_dl_entity()
|
||||
* // fwd period
|
||||
* if (dl_throttled)
|
||||
* dl_throttled = 0;
|
||||
* if (dl_defer_armed)
|
||||
* dl_defer_armed = 0;
|
||||
* __enqueue_dl_entity();
|
||||
* // [D]
|
||||
*
|
||||
* // schedule server
|
||||
* [4] D->A
|
||||
* pick_task_dl()
|
||||
* p = server_pick_task();
|
||||
* if (!p)
|
||||
* dl_server_stop()
|
||||
* dequeue_dl_entity();
|
||||
* hrtimer_try_to_cancel();
|
||||
* dl_defer_armed = 0;
|
||||
* dl_throttled = 0;
|
||||
* dl_server_active = 0;
|
||||
* // [A]
|
||||
* return p;
|
||||
*
|
||||
* // server running
|
||||
* [5] D->E
|
||||
* update_curr_dl_se()
|
||||
* if (dl_runtime_exceeded())
|
||||
* dl_throttled = 1;
|
||||
* dequeue_dl_entity();
|
||||
* start_dl_timer();
|
||||
* // [E]
|
||||
*
|
||||
* // server replenished
|
||||
* [6] E->D
|
||||
* dl_server_timer()
|
||||
* enqueue_dl_entity(REPLENISH)
|
||||
* replenish_dl_entity()
|
||||
* fwd-period
|
||||
* if (dl_throttled)
|
||||
* dl_throttled = 0;
|
||||
* __enqueue_dl_entity();
|
||||
* // [D]
|
||||
*
|
||||
* // deplete server runtime from idle
|
||||
* [7] B->C, C->C
|
||||
* dl_server_update_idle()
|
||||
* update_curr_dl_se() // idle = true
|
||||
* if (dl_defer && dl_throttled && dl_runtime_exceeded())
|
||||
* if (dl_defer_idle)
|
||||
* return;
|
||||
* dl_defer_running = 0;
|
||||
* hrtimer_try_to_cancel();
|
||||
* replenish_dl_new_period()
|
||||
* // fwd period
|
||||
* dl_throttled = 1;
|
||||
* dl_defer_armed = 1;
|
||||
* dl_defer_idle = 1;
|
||||
* start_dl_timer(); // restart timer
|
||||
* // [C]
|
||||
*
|
||||
* // stop idle server
|
||||
* [8] C->A
|
||||
* dl_server_timer()
|
||||
* if (dl_defer_idle)
|
||||
* dl_server_stop();
|
||||
* // [A]
|
||||
*
|
||||
*
|
||||
* digraph dl_server {
|
||||
* "A:init" -> "B:zero_laxity-wait" [label="1:dl_server_start"]
|
||||
* "A:init" -> "D:running" [label="1:dl_server_start"]
|
||||
* "B:zero_laxity-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
|
||||
* "B:zero_laxity-wait" -> "C:idle-wait" [label="7:dl_server_update_idle"]
|
||||
* "B:zero_laxity-wait" -> "D:running" [label="3:dl_server_timer"]
|
||||
* "C:idle-wait" -> "A:init" [label="8:dl_server_timer"]
|
||||
* "C:idle-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
|
||||
* "C:idle-wait" -> "C:idle-wait" [label="7:dl_server_update_idle"]
|
||||
* "D:running" -> "A:init" [label="4:pick_task_dl"]
|
||||
* "D:running" -> "E:replenish-wait" [label="5:update_curr_dl_se"]
|
||||
* "E:replenish-wait" -> "B:zero_laxity-wait" [label="2:dl_server_update"]
|
||||
* "E:replenish-wait" -> "D:running" [label="6:dl_server_timer"]
|
||||
* }
|
||||
*
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* - When there are fair tasks running the most likely loop is [2]->[2].
|
||||
* the dl_server never actually runs, the timer never fires.
|
||||
*
|
||||
* - When there is actual fair starvation; the timer fires and starts the
|
||||
* dl_server. This will then throttle and replenish like a normal DL
|
||||
* task. Notably it will not 'defer' again.
|
||||
*
|
||||
* - When idle it will push the actication forward once, and then wait
|
||||
* for the timer to hit or a non-idle update to restart things.
|
||||
*/
|
||||
void dl_server_start(struct sched_dl_entity *dl_se)
|
||||
{
|
||||
struct rq *rq = dl_se->rq;
|
||||
|
|
|
|||
Loading…
Reference in New Issue