이 코드는 어떤 문제를 푸나요?
할 일이 없는 CPU를 일정 간격으로 계속 깨우면 전력을 쓰고 깊은 유휴 상태에 머물기 어렵습니다. NOHZ는 필요한 시각에 깨우는 방식으로 불필요한 tick을 줄입니다. tick_nohz_idle_enter는 그중 idle 진입 상태를 기록하는 준비 함수이며 이 짧은 함수에 모든 tick 중지 판단이 들어 있지는 않습니다.
읽을 범위: v6.18.37 · kernel/time/tick-sched.c · tick_nohz_idle_enter 1250–1266행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.
먼저 알아둘 개념
주기 tick과 다음 이벤트
매번 일정 간격으로 깨우는 방식과 가장 가까운 실제 기한에 맞춰 깨우는 방식을 구분합니다. tick을 줄여도 타이머나 장치 인터럽트가 모두 사라지는 것은 아닙니다.
CPU별 tick_sched
각 CPU의 idle·tick 상태를 담은 구조체입니다. 한 CPU가 idle에 들어갔다고 다른 CPU의 시간 관리도 똑같이 멈추지 않습니다.
로컬 인터럽트 차단
현재 CPU의 인터럽트를 막아 상태 전환 중 같은 CPU의 인터럽트 처리와 엇갈리지 않도록 합니다. 전 시스템의 인터럽트를 모두 끄는 명령은 아닙니다.
처음 읽을 때
알람이 100 ms 뒤에 하나만 있는데 매 1 ms마다 확인하러 깨는 상황을 떠올려 보세요. NOHZ는 필요한 기한과 다른 시스템 요구를 고려해 중간 깨움을 줄입니다. 숫자는 원리를 보여 주는 예시입니다.
더 깊이 살펴볼 때
idle_enter, 실제 tick 중지 판단과 idle_exit을 분리해서 읽으세요. RCU, timer, balancing 등 다음 이벤트의 요구가 tick 중지 가능 여부에 영향을 줍니다.
그림으로 보는 변화

1. idle 진입 조건 확인
진입 시 로컬 IRQ가 허용되어야 함
화살표는 이 함수의 호출 순서입니다. IRQ를 처음부터 꺼 놓고 호출하는 사용법과 다릅니다.
2. 상태 변경 보호
IRQ 차단 후 this_cpu tick_sched 선택
현재 CPU의 tick 상태를 일관되게 바꿉니다.
3. idle 상태 기록
INIDLE 설정, 유휴 계상 시작, IRQ 재허용
이 화살표는 상태 변경을 뜻합니다. 실제 다음 tick을 무조건 취소한다는 뜻은 아닙니다.
tick_nohz_idle_enter를 한 줄씩 읽기
줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.
void tick_nohz_idle_enter(void)
{
struct tick_sched *ts;
lockdep_assert_irqs_enabled();
local_irq_disable();
ts = this_cpu_ptr(&tick_cpu_sched);
WARN_ON_ONCE(ts->timer_expires_base);
tick_sched_flag_set(ts, TS_FLAG_INIDLE);
tick_nohz_start_idle(ts);
local_irq_enable();
}void tick_nohz_idle_enter(void)현재 CPU가 idle 경로에 들어갈 때 호출하는 NOHZ 준비 함수입니다.
struct tick_sched *ts;현재 CPU의 tick_sched를 가리킬 포인터를 준비합니다.
lockdep_assert_irqs_enabled();진입 시 로컬 인터럽트가 허용되어야 한다는 조건을 검증합니다. 뒤의 무조건 재허용과 연결된 사용 조건입니다.
local_irq_disable();현재 CPU의 인터럽트를 잠시 차단해 tick 상태를 일관되게 변경합니다.
ts = this_cpu_ptr(&tick_cpu_sched);per-CPU 변수에서 지금 CPU에 해당하는 tick_sched 주소를 얻습니다. 모든 CPU가 하나의 ts를 공유하지 않습니다.
WARN_ON_ONCE(ts->timer_expires_base);timer_expires_base가 아직 설정된 비정상적인 idle 진입 상태인지 한 번 경고합니다. 정상적인 전환 순서 확인입니다.
tick_sched_flag_set(ts, TS_FLAG_INIDLE);현재 CPU가 idle 경로 안에 있음을 flag로 표시합니다.
tick_nohz_start_idle(ts);idle 시작 시점과 관련 계상을 준비합니다. 이 호출을 모든 타이머를 끄는 명령으로 읽지 않습니다.
local_irq_enable();함수 진입 조건에 맞춰 로컬 인터럽트를 다시 허용합니다. 다른 CPU의 IRQ 상태를 변경하지 않습니다.
함께 생각해 볼 질문
NOHZ면 CPU가 어떤 인터럽트도 받지 않나요?
아닙니다. 불필요한 주기 tick을 줄이는 것이며 필요한 타이머 만료나 장치 이벤트는 여전히 처리합니다.
이 함수만 호출하면 tick이 반드시 중지되나요?
아닙니다. idle 진입 기록과 계상 준비를 담당하며 실제 중지 가능 여부는 관련 경로의 추가 판단에 달려 있습니다.
왜 irqsave 대신 disable/enable을 쓰나요?
함수 진입 시 IRQ가 허용되어야 한다는 전제를 먼저 검사합니다. 그 전제 안에서 차단과 재허용을 짝지어 사용합니다.
출처와 읽은 범위
Linux stable v6.18.37 · kernel/time/tick-sched.c
해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고
