본문 바로가기

Enginius/Linux

linux-2.6.24에서 linux-2.6.32로 porting하기 (dec_load(), )

linux-2.6.24에서 linux-2.6.32로 포팅을 하다보니
dec_load() 함수가 사라졌다. 

 24버젼에서 이 함수는  해당 rq의 load를 task의 weight 만큼 빼는 함수이다. 즉 rq에서 task를 뺀 후에 rq의 load를 update하기 위해서 불린다. 
static inline void dec_load(struct rq *rq, const struct task_struct *p)
{
	update_load_sub(&rq->load, p->se.load.weight);
}

static inline void update_load_sub(struct load_weight *lw, unsigned long dec)
{
	lw->weight -= dec;
}
linux-2.6.32 에서는 dec_load 대신에 dec_cpu_load()라는 함수가 쓰인다. 
static inline void dec_cpu_load(struct rq *rq, unsigned long load)
{
	update_load_sub(&rq->load, load);
}
결국 같은 일을 하는 함수인데 문제는 원래 dec_load()가 불리는 곳에서 dec_cpu_load()가 불리지 않는다는 점이다. 

24 버젼에서 dec_load()가 불리는 곳은 총 두 곳이다. 
 1.  dec_nr_running()
 2.  set_user_nice()에서 현재 rq에서 task p를 de-queue하고 나서이다. 

32 버젼에서 dec_cpu_load()가 불리는 곳은 단 한 곳이다. 
 1. account_entity_dequeue()
이 함수는 dequeue_entity()에서 불리고, 이 안에서 __dequeue_entity()를 불러서 해당 se를 rb트리에서 삭제한다. 
이 함수의 caller는 총 두 개이다. 
 1. dequeue_task_fair()
 2. __set_se_shares()  
 이 중에서 dequeue_task_fair()fair_sched_classdequeue_task()로 연결되어 있다. 
 이 클래스의 멤버 함수는 dequeue_task()에서 불린다. 
 
static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep)
{
	if (sleep) {
		if (p->se.last_wakeup) {
			update_avg(&p->se.avg_overlap,
				p->se.sum_exec_runtime - p->se.last_wakeup);
			p->se.last_wakeup = 0;
		} else {
			update_avg(&p->se.avg_wakeup,
				sysctl_sched_wakeup_granularity);
		}
	}

	sched_info_dequeued(p);
	p->sched_class->dequeue_task(rq, p, sleep);
	
	// DWRR_patch
	//p->se.on_rq = 0;
	p->se.on_rq = NULL;
}
정리하자면, linux-2.6.32 에서는 dequeue_task()에서 각 sched_class의 dequeue_task()를 부르고, fair_class의 경우, dequeue_task_fair()를 부른다. 그러면 이 안에서 account_entity_dequeue()를 부르고, dec_cpu_load()를 불러서 해당 런큐load를 빠지는 taskweight만큼 뺀다.