Loading kernel/sched/deadline.c +194 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
kernel/sched/deadline.c +194 −0 Original line number Diff line number Diff line Loading @@ -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