강좌 & 팁
글 수 2,412
2011.08.08 18:22:28 (*.119.104.169)
41807
방갑습니다~ 이우영입니다.
오늘은 저번시간에 이어서 swapper를 분석해 보겠습니다.
arch/arm/kernel/process.c에 보면 cpu_idle 함수가 있습니다.
147void cpu_idle(void) 148{ 149 local_fiq_enable(); 150 151 /* endless idle loop with no priority at all */ 152 while (1) { 153 void (*idle)(void) = pm_idle; 154 155#ifdef CONFIG_HOTPLUG_CPU 156 if (cpu_is_offline(smp_processor_id())) { 157 leds_event(led_idle_start); 158 cpu_die(); 159 } 160#endif 161 162 if (!idle) 163 idle = default_idle; 164 leds_event(led_idle_start); 165 tick_nohz_stop_sched_tick(1); 166 while (!need_resched()) 167 idle(); 168 leds_event(led_idle_end); 169 tick_nohz_restart_sched_tick(); 170 preempt_enable_no_resched(); 171 schedule(); 172 preempt_disable(); 173 } 174}
cpu_idle이 시작하면 149 라인에서 fiq가 동작 할 수 있도록 arm의 cpsr의 값을 설정 해 줍니다.
(idle 상태에 빠져들면 fiq를 이용해 휴면상태에서 빠져나옵니다.)
그리고 무한 루프를 돌기 시작합니다.
(리눅스가 끝날때까지 멈추지 않습니다 ㅎㅎㅎ)
153 라인에서 매번 pm_idle 함수를 등록 해줍니다. 보통 pm_idle 함수에 전력을 낮춰 주는 부분이 들어있습니다.
162 라인을 보면 idle 에 등록된 함수의 주소가 없을 경우 default_idle 함수를 등록 합니다.
130static void default_idle(void)
131{
132 if (hlt_counter)
133 cpu_relax();
134 else {
135 local_irq_disable();
136 if (!need_resched())
137 arch_idle();
138 local_irq_enable();
139 }
140}
hit_counter가 0일 경우 wakeup call의 미스를 방지하기위해 irq를 금지하고 arch_idle을 실행합니다.
arch_idle같은 경우는 아키택처에 따라 달라지지만 s3c6410은 아무일도 처리 하지 않습니다.
다시 cpu_idle을 보면 164 라인에서 휴면상태에 들어가는걸 알리기위해 led를 제어해줍니다.
165 라인에서 idle tick을 중지 시키고 tickless모드로 들어갑니다.
166 라인부터 idle에 들어가게됩니다.
need_resched 함수에서 flag값을 확인해서 스케줄이 필요한지 확인하고 없으면 idle에 등록된 함수를
실행 합니다.
루프를 빠져나오면 타이머를 다시 실행시키고 led도 제어하고 스케줄러를 호출해서 idle 상태가 끝납니다.
(다시 idle 에 들어오면 위 상황을 반복 하겠죠?)
정리
정신이 없내요 ㅎㅎ 간단하게 정리를 해보겠습니다.
idle 모드에 들어오면 idle 에 pm_idle or default_idle 함수를 등록합니다.
led를 이용하여 idle 상태인것을 알리고 tickless 모드로 들어간다.
스케줄이 필요할 때 까지 idle 함수를 수행합니다.
스케줄이 필요해지만 루프를 빠져나와 타이머를 동작시키고, led를 제어해 idle이 끝났음을 알리고
스케줄러를 호출하여 다른 프로세스를 실행 합니다.
여기까지 cpu_idle 의 동작 흐름을 알아 봤습니다.
cpu_idle의 가장 핵심은 pm_idle 에서 어떻게 파워를 세이브 하는가 입니다.
이부분은 다음시간에 이어서 하도록 하겠습니다.