【内核调度】【enqueue_entity】

/*
 * 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);
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章