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_for_v6.3_rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull scheduler fix from Borislav Petkov:

- Fix a corner case where vruntime of a task is not being sanitized

* tag 'sched_urgent_for_v6.3_rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
sched/fair: Sanitize vruntime of entity being migrated

+46 -10
+3
kernel/sched/core.c
··· 2084 2084 2085 2085 void activate_task(struct rq *rq, struct task_struct *p, int flags) 2086 2086 { 2087 + if (task_on_rq_migrating(p)) 2088 + flags |= ENQUEUE_MIGRATED; 2089 + 2087 2090 enqueue_task(rq, p, flags); 2088 2091 2089 2092 p->on_rq = TASK_ON_RQ_QUEUED;
+43 -10
kernel/sched/fair.c
··· 4648 4648 #endif 4649 4649 } 4650 4650 4651 + static inline bool entity_is_long_sleeper(struct sched_entity *se) 4652 + { 4653 + struct cfs_rq *cfs_rq; 4654 + u64 sleep_time; 4655 + 4656 + if (se->exec_start == 0) 4657 + return false; 4658 + 4659 + cfs_rq = cfs_rq_of(se); 4660 + 4661 + sleep_time = rq_clock_task(rq_of(cfs_rq)); 4662 + 4663 + /* Happen while migrating because of clock task divergence */ 4664 + if (sleep_time <= se->exec_start) 4665 + return false; 4666 + 4667 + sleep_time -= se->exec_start; 4668 + if (sleep_time > ((1ULL << 63) / scale_load_down(NICE_0_LOAD))) 4669 + return true; 4670 + 4671 + return false; 4672 + } 4673 + 4651 4674 static void 4652 4675 place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) 4653 4676 { 4654 4677 u64 vruntime = cfs_rq->min_vruntime; 4655 - u64 sleep_time; 4656 4678 4657 4679 /* 4658 4680 * The 'current' period is already promised to the current tasks, ··· 4706 4684 4707 4685 /* 4708 4686 * Pull vruntime of the entity being placed to the base level of 4709 - * cfs_rq, to prevent boosting it if placed backwards. If the entity 4710 - * slept for a long time, don't even try to compare its vruntime with 4711 - * the base as it may be too far off and the comparison may get 4712 - * inversed due to s64 overflow. 4687 + * cfs_rq, to prevent boosting it if placed backwards. 4688 + * However, min_vruntime can advance much faster than real time, with 4689 + * the extreme being when an entity with the minimal weight always runs 4690 + * on the cfs_rq. If the waking entity slept for a long time, its 4691 + * vruntime difference from min_vruntime may overflow s64 and their 4692 + * comparison may get inversed, so ignore the entity's original 4693 + * vruntime in that case. 4694 + * The maximal vruntime speedup is given by the ratio of normal to 4695 + * minimal weight: scale_load_down(NICE_0_LOAD) / MIN_SHARES. 4696 + * When placing a migrated waking entity, its exec_start has been set 4697 + * from a different rq. In order to take into account a possible 4698 + * divergence between new and prev rq's clocks task because of irq and 4699 + * stolen time, we take an additional margin. 4700 + * So, cutting off on the sleep time of 4701 + * 2^63 / scale_load_down(NICE_0_LOAD) ~ 104 days 4702 + * should be safe. 4713 4703 */ 4714 - sleep_time = rq_clock_task(rq_of(cfs_rq)) - se->exec_start; 4715 - if ((s64)sleep_time > 60LL * NSEC_PER_SEC) 4704 + if (entity_is_long_sleeper(se)) 4716 4705 se->vruntime = vruntime; 4717 4706 else 4718 4707 se->vruntime = max_vruntime(se->vruntime, vruntime); ··· 4803 4770 4804 4771 if (flags & ENQUEUE_WAKEUP) 4805 4772 place_entity(cfs_rq, se, 0); 4773 + /* Entity has migrated, no longer consider this task hot */ 4774 + if (flags & ENQUEUE_MIGRATED) 4775 + se->exec_start = 0; 4806 4776 4807 4777 check_schedstat_required(); 4808 4778 update_stats_enqueue_fair(cfs_rq, se, flags); ··· 7692 7656 7693 7657 /* Tell new CPU we are migrated */ 7694 7658 se->avg.last_update_time = 0; 7695 - 7696 - /* We have migrated, no longer consider this task hot */ 7697 - se->exec_start = 0; 7698 7659 7699 7660 update_scan_period(p, new_cpu); 7700 7661 }