/*
* MIGRATION
*
* dequeue
* update_curr()
* update_min_vruntime()
* vruntime -= min_vruntime
*
* enqueue
* update_curr()
* update_min_vruntime()
* vruntime += min_vruntime
*
* this way the vruntime transition(過渡) between RQs is done when both
* min_vruntime are up-to-date.
*
* WAKEUP (remote)
*
* ->migrate_task_rq_fair() (p->state == TASK_WAKING)
* vruntime -= min_vruntime
*
* enqueue
* update_curr()
* update_min_vruntime()
* vruntime += min_vruntime
*
* this way we don't have the most up-to-date min_vruntime on the originating
* CPU and an up-to-date min_vruntime on the destination CPU.
*/
static void
enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
{
bool renorm = !(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_MIGRATED);
bool curr = cfs_rq->curr == se;
/*
* If we're the current task, we must renormalise(重新規範化) before calling
* update_curr().
*/
/* (4.1) 在enqueue時給se->vruntime重新加上cfs_rq->min_vruntime */
if (renorm && curr)
se->vruntime += cfs_rq->min_vruntime;
/*更新cfs_rq調度實體的vruntime和相關調度的統計信息*/
//更新runtime和vruntime
update_curr(cfs_rq);
/*
* Otherwise, renormalise after, such that we're placed at the current
* moment in time, instead of some random moment in the past. Being
* placed in the past could significantly(顯著的) boost this task to the
* fairness detriment(有害的) of existing tasks.
*/
if (renorm && !curr)
se->vruntime += cfs_rq->min_vruntime;
/*
* When enqueuing a sched_entity, we must:
* - Update loads to have both entity and cfs_rq synced with now.
* - Add its load to cfs_rq->runnable_avg
* - For group_entity, update its weight to reflect the new share of
* its group cfs_rq
* - Add its new weight to cfs_rq->load.weight
*/
/*對新進程的調度實體進行util/load進行衰減,根據PELT算法*/
update_load_avg(se, UPDATE_TG);
/*更新cfs_rqrunnable_load_sum/avg負載信息已經struct sched_entity →
struct sched_avg成員變量數值累加到整個struct cfs_rq-->struct sched_avg上去並
觸發頻率的調整.*/
enqueue_entity_load_avg(cfs_rq, se);
update_cfs_shares(se);
/* 更新cfs_rq隊列總權重(就是在原有基礎上加上se的權重) */
account_entity_enqueue(cfs_rq, se);
/* 新建的進程flags爲0,不會執行這裏 */
if (flags & ENQUEUE_WAKEUP)
place_entity(cfs_rq, se, 0); //確定進程正確的虛擬時間
check_schedstat_required();
/*更新調度相關狀態和統計信息*/
update_stats_enqueue(cfs_rq, se, flags);
check_spread(cfs_rq, se);
/*如果當前調度實體不是cfs_rq當前的調度實體,則將新進程的調度實體插入rb tree中,根據
vruntime的大小加入rb tree*/
if (!curr)
//將進程置於紅黑樹中。使用內核的標準方法將進程排序到紅黑樹中
__enqueue_entity(cfs_rq, se);
/*新進程在rq中*/
se->on_rq = 1;
if (cfs_rq->nr_running == 1) {
list_add_leaf_cfs_rq(cfs_rq);
check_enqueue_throttle(cfs_rq);
}
}
【內核調度】【enqueue_entity】
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.