hrtimers_init()

 

HRTimer 초기화

hrtimers_init()

kernel/time/hrtimer.c

void __init hrtimers_init(void)
{
        hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
                          (void *)(long)smp_processor_id());
        register_cpu_notifier(&hrtimers_nb);
#ifdef CONFIG_HIGH_RES_TIMERS
        open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
#endif
}

현재 cpu에 대한 hrtimer를 초기화하고 cpu notifier chain에 hrtimer 초기화 함수를 등록한다. 그리고 hrtimer용 softirq로 run_hrtimer_softirq() 함수를 등록한다.

  • 코드 라인 3~4에서 현재 cpu에 대해 CPU_UP_PRPARE 상태로 전역 hrtimers_nb라는 이름의 notifier_block에 등록된 hrtimer_cpu_notify() 함수를 직접 호출한다.
    • bootup cpu는 이미 on되어 있는 상황이므로 여기서 hrtimer 초기화 루틴을 수행하도록 호출한다. 이 때 실제 hrimer의 초기화 함수 init_hrtimers_cpu()가 호출 된다.
  • 코드 라인 5에서 cpu들 상태가 바뀔 때마다 호출되도록 cpu notifier chain에 등록한다.
    • cpu가 on될 때마다 hrtimer framework의 초기화를 수행한다.
    • armv7 아키텍처는 각 cpu마다 hrtimer가 4개씩 내장되어 있다.
  • 코드 라인 6~8에서 CONFIG_HIGH_RES_TIMERS 커널 옵션을 사용하는 경우 run_hrtimer_softirq() 함수를 softirq에 등록한다.
    • 커널 v4.2-rc1에서는 hrtimer용 softirq를 사용하지 않는다.

 

kernel/time/hrtimer.c

static struct notifier_block hrtimers_nb = {
        .notifier_call = hrtimer_cpu_notify,
};

cpu 상태 변화에 따라 호출될 hrtimer의 notifier block이다.

 

hrtimer_cpu_notify()

kernel/time/hrtimer.c”

static int hrtimer_cpu_notify(struct notifier_block *self,
                                        unsigned long action, void *hcpu)
{
        int scpu = (long)hcpu;

        switch (action) {

        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
                init_hrtimers_cpu(scpu);
                break;

#ifdef CONFIG_HOTPLUG_CPU
        case CPU_DYING:
        case CPU_DYING_FROZEN:
                clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
                break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
        {
                clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu);
                migrate_hrtimers(scpu);
                break;
        }
#endif

        default:
                break;
        }

        return NOTIFY_OK;
}

cpu 상태가 변화함에 따라 통지되어 hrtimer가 처리해야 할 일들을 수행한다.

  • 코드 라인 6~11에서 cpu가 up이 되면 해당 cpu에 대한 hrtimer 프레임워크를 초기화한다.
  • 코드 라인 13~17에서 cpu가 dying 상태가 되면 해당 cpu를 사용하는 클럭이벤트들에 대해 dying 상태를 통지한다.
  • 코드 라인 18~24에서 cpu가 dead 상태가 되면 해당 cpu를 사용하는 클럭이벤트들에 대해 dead 상태를 통지하고 해당 cpu의 hrtimer를 사용하는 요청들을 현재 cpu로 migration 한다.

 

init_hrtimers_cpu()

kernel/time/hrtimer.c

/*
 * Functions related to boot-time initialization:
 */
static void init_hrtimers_cpu(int cpu)
{
        struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
        int i;

        for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
                cpu_base->clock_base[i].cpu_base = cpu_base;
                timerqueue_init_head(&cpu_base->clock_base[i].active);
        }

        cpu_base->cpu = cpu;
        hrtimer_init_hres(cpu_base);
}

요청  cpu에 대한 hritimer의 cpu_base와 clock_base를 초기화한다.

  • 코드 라인 6에서 요청 cpu의 hrtimer_bases를 알아와서 cpu_base에 대입한다.
  • 코드 라인 9~12에서 HRTIMER_MAX_CLOCK_BASES(4)개 까지 루프를 돌며 멤버 cpu_base를 지정하게 하고 active 타이머큐를 초기화한다.
  • 코드 라인 15에서 요청 cpu에 대해 동작중인 hrtimer를 0개로 초기화한다.

 

다음 그림은 0번 cpu에 대한 hrtimer 구조를 초기화한 모습을 보여준다.

 

 

timerqueue_init_head()

include/linux/timerqueue.h

static inline void timerqueue_init_head(struct timerqueue_head *head)
{
        head->head = RB_ROOT;
        head->next = NULL;
}

hrtimer 큐를 초기화한다.

 

 hrtimer_init_hres()

kernel/time/hrtimer.c

/*
 * Initialize the high resolution related parts of cpu_base
 */
static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) 
{
        base->expires_next.tv64 = KTIME_MAX;
        base->hres_active = 0;
}

동작 중인 hrtimer를 0으로 초기화한다.

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.