From: Li Hua hucool.lihua@huawei.com
hulk inclusion category: bugfix bugzilla: 185759 https://gitee.com/openeuler/kernel/issues/I4DDEL
---------------------------
When rt_runtime is modified from -1 to a valid control value, it may cause the task to be throttled all the time. Operations like the following will trigger the bug. E.g: 1. echo -1 > /proc/sys/kernel/sched_rt_runtime_us 2. Run a FIFO task named A that executes while(1) 3. echo 950000 > /proc/sys/kernel/sched_rt_runtime_us
When rt_runtime is -1, The rt period timer will not be activated when task A enqueued. And then the task will be throttled after setting rt_runtime to 950,000. The task will always be throttled because the rt period timer is not activated.
Signed-off-by: Li Hua hucool.lihua@huawei.com Reviewed-by: Chen Hui judy.chenhui@huawei.com Reviewed-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Chen Jun chenjun102@huawei.com --- kernel/sched/rt.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index ad9bec90fb7a..dae1e8eaa983 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -944,6 +944,18 @@ static inline int rt_se_prio(struct sched_rt_entity *rt_se) return rt_task_of(rt_se)->prio; }
+static inline void try_start_rt_bandwidth(struct rt_bandwidth *rt_b) +{ + raw_spin_lock(&rt_b->rt_runtime_lock); + if (!rt_b->rt_period_active) { + rt_b->rt_period_active = 1; + hrtimer_forward_now(&rt_b->rt_period_timer, rt_b->rt_period); + hrtimer_start_expires(&rt_b->rt_period_timer, + HRTIMER_MODE_ABS_PINNED_HARD); + } + raw_spin_unlock(&rt_b->rt_runtime_lock); +} + static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) { u64 runtime = sched_rt_runtime(rt_rq); @@ -1020,13 +1032,17 @@ static void update_curr_rt(struct rq *rq)
for_each_sched_rt_entity(rt_se) { struct rt_rq *rt_rq = rt_rq_of_se(rt_se); + int exceeded;
if (sched_rt_runtime(rt_rq) != RUNTIME_INF) { raw_spin_lock(&rt_rq->rt_runtime_lock); rt_rq->rt_time += delta_exec; - if (sched_rt_runtime_exceeded(rt_rq)) + exceeded = sched_rt_runtime_exceeded(rt_rq); + if (exceeded) resched_curr(rq); raw_spin_unlock(&rt_rq->rt_runtime_lock); + if (exceeded) + try_start_rt_bandwidth(sched_rt_bandwidth(rt_rq)); } } } @@ -2721,8 +2737,10 @@ static int sched_rt_global_validate(void)
static void sched_rt_do_global(void) { + raw_spin_lock(&def_rt_bandwidth.rt_runtime_lock); def_rt_bandwidth.rt_runtime = global_rt_runtime(); def_rt_bandwidth.rt_period = ns_to_ktime(global_rt_period()); + raw_spin_unlock(&def_rt_bandwidth.rt_runtime_lock); }
int sched_rt_handler(struct ctl_table *table, int write, void *buffer,