diff options
Diffstat (limited to 'kernel/sched_fair.c')
| -rw-r--r-- | kernel/sched_fair.c | 45 | 
1 files changed, 29 insertions, 16 deletions
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index ba7fd6e9556..652e8bdef9a 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -266,6 +266,12 @@ static inline u64 min_vruntime(u64 min_vruntime, u64 vruntime)  	return min_vruntime;  } +static inline int entity_before(struct sched_entity *a, +				struct sched_entity *b) +{ +	return (s64)(a->vruntime - b->vruntime) < 0; +} +  static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se)  {  	return se->vruntime - cfs_rq->min_vruntime; @@ -605,9 +611,13 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)  static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)  {  #ifdef CONFIG_SCHEDSTATS +	struct task_struct *tsk = NULL; + +	if (entity_is_task(se)) +		tsk = task_of(se); +  	if (se->sleep_start) {  		u64 delta = rq_of(cfs_rq)->clock - se->sleep_start; -		struct task_struct *tsk = task_of(se);  		if ((s64)delta < 0)  			delta = 0; @@ -618,11 +628,11 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)  		se->sleep_start = 0;  		se->sum_sleep_runtime += delta; -		account_scheduler_latency(tsk, delta >> 10, 1); +		if (tsk) +			account_scheduler_latency(tsk, delta >> 10, 1);  	}  	if (se->block_start) {  		u64 delta = rq_of(cfs_rq)->clock - se->block_start; -		struct task_struct *tsk = task_of(se);  		if ((s64)delta < 0)  			delta = 0; @@ -633,17 +643,19 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)  		se->block_start = 0;  		se->sum_sleep_runtime += delta; -		/* -		 * Blocking time is in units of nanosecs, so shift by 20 to -		 * get a milliseconds-range estimation of the amount of -		 * time that the task spent sleeping: -		 */ -		if (unlikely(prof_on == SLEEP_PROFILING)) { - -			profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk), -				     delta >> 20); +		if (tsk) { +			/* +			 * Blocking time is in units of nanosecs, so shift by +			 * 20 to get a milliseconds-range estimation of the +			 * amount of time that the task spent sleeping: +			 */ +			if (unlikely(prof_on == SLEEP_PROFILING)) { +				profile_hits(SLEEP_PROFILING, +						(void *)get_wchan(tsk), +						delta >> 20); +			} +			account_scheduler_latency(tsk, delta >> 10, 0);  		} -		account_scheduler_latency(tsk, delta >> 10, 0);  	}  #endif  } @@ -687,7 +699,8 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)  			 * all of which have the same weight.  			 */  			if (sched_feat(NORMALIZED_SLEEPER) && -					task_of(se)->policy != SCHED_IDLE) +					(!entity_is_task(se) || +					 task_of(se)->policy != SCHED_IDLE))  				thresh = calc_delta_fair(thresh, se);  			vruntime -= thresh; @@ -1016,7 +1029,7 @@ static void yield_task_fair(struct rq *rq)  	/*  	 * Already in the rightmost position?  	 */ -	if (unlikely(!rightmost || rightmost->vruntime < se->vruntime)) +	if (unlikely(!rightmost || entity_before(rightmost, se)))  		return;  	/* @@ -1712,7 +1725,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)  	/* 'curr' will be NULL if the child belongs to a different group */  	if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) && -			curr && curr->vruntime < se->vruntime) { +			curr && entity_before(curr, se)) {  		/*  		 * Upon rescheduling, sched_class::put_prev_task() will place  		 * 'current' within the tree based on its new key value.  |