# NOHZ: 쉬는 CPU에서 불필요한 주기 tick 줄이기

v6.6 / kernel/time/tick-sched.c

할 일이 없는 CPU를 일정 간격으로 계속 깨우면 전력을 쓰고 깊은 유휴 상태에 머물기 어렵습니다. NOHZ는 필요한 시각에 깨우는 방식으로 불필요한 tick을 줄입니다. tick_nohz_idle_enter는 그중 idle 진입 상태를 기록하는 준비 함수이며 이 짧은 함수에 모든 tick 중지 판단이 들어 있지는 않습니다.

## tick_nohz_idle_enter

```c

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);

	ts->inidle = 1;
	tick_nohz_start_idle(ts);

	local_irq_enable();
}

```

### 1159행

```c

void tick_nohz_idle_enter(void)

```

현재 CPU가 idle 경로에 들어갈 때 호출하는 NOHZ 준비 함수입니다.

### 1161행

```c

	struct tick_sched *ts;

```

현재 CPU의 tick_sched를 가리킬 포인터를 준비합니다.

### 1163행

```c

	lockdep_assert_irqs_enabled();

```

진입 시 로컬 인터럽트가 허용되어야 한다는 조건을 검증합니다. 뒤의 무조건 재허용과 연결된 사용 조건입니다.

### 1165행

```c

	local_irq_disable();

```

현재 CPU의 인터럽트를 잠시 차단해 tick 상태를 일관되게 변경합니다.

### 1167행

```c

	ts = this_cpu_ptr(&tick_cpu_sched);

```

per-CPU 변수에서 지금 CPU에 해당하는 tick_sched 주소를 얻습니다. 모든 CPU가 하나의 ts를 공유하지 않습니다.

### 1169행

```c

	WARN_ON_ONCE(ts->timer_expires_base);

```

timer_expires_base가 아직 설정된 비정상적인 idle 진입 상태인지 한 번 경고합니다. 정상적인 전환 순서 확인입니다.

### 1171행

```c

	ts->inidle = 1;

```

현재 CPU의 tick_sched에 inidle=1을 기록합니다. v6.6은 이 필드를 직접 설정하며 최신 버전의 TS_FLAG_INIDLE 매크로를 호출하지 않습니다.

### 1172행

```c

	tick_nohz_start_idle(ts);

```

idle 시작 시점과 관련 계상을 준비합니다. 이 호출을 모든 타이머를 끄는 명령으로 읽지 않습니다.

### 1174행

```c

	local_irq_enable();

```

함수 진입 조건에 맞춰 로컬 인터럽트를 다시 허용합니다. 다른 CPU의 IRQ 상태를 변경하지 않습니다.

