← Documents Documentation/scheduler/sched-arch.rst GitHub 원문 ↗

Linux 6.18.37 · Scheduler

Architecture별 scheduler hook

Context switch, CPU idle와 architecture-specific scheduler 구현이 지켜야 할 ordering과 low-level contract를 설명합니다.

Source pathDocumentation/scheduler/sched-arch.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

Context switch의 architecture 책임

sched-arch.rst:7-21

Architecture switch_to path는 callee-saved register, stack, thread-local CPU state와 address space를 다음 task 기준으로 전환합니다. Scheduler core가 rq lock과 task state를 관리하더라도 lazy state와 TLB, speculation mitigation은 architecture code의 책임입니다.

prev와 next publication, membarrier, migration과 task_struct lifetime ordering을 깨뜨리지 않아야 합니다. Context switch 중 sleep하거나 일반 scheduler path로 재진입할 수 없습니다.

CPU idle 진입과 wakeup

sched-arch.rst:22-65

Idle loop는 runnable task가 없음을 확인한 뒤 tick broadcast와 idle governor가 선택한 power state로 들어갑니다. Interrupt enable과 need_resched 확인 순서가 잘못되면 wakeup을 놓치고 CPU가 runnable task가 있는데도 sleep할 수 있습니다.

Architecture의 idle instruction은 interrupt 또는 platform event로 확실히 빠져나와야 하며, local timer가 멈추는 state에서는 broadcast clockevent와 협력해야 합니다. Polling idle flag는 remote wakeup이 IPI를 생략할 수 있는지 판단하는 계약입니다.

Port에서 흔한 문제

sched-arch.rst:66-73
  • Idle 진입 직전 need_resched 재검사가 없어 wakeup을 놓침
  • Per-CPU clock 또는 sched_clock이 migration 전후 단조성을 잃음
  • switch_mm/TLB ordering이 membarrier 요구를 충족하지 않음
  • CPU hotplug 중 clockevent와 runqueue 상태 전환 순서 오류

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =================================================================
2 CPU Scheduler implementation hints for architecture specific code
3 =================================================================
4
5 Nick Piggin, 2005
6
7 Context switch
8 ==============
9 1. Runqueue locking
10 By default, the switch_to arch function is called with the runqueue
11 locked. This is usually not a problem unless switch_to may need to
12 take the runqueue lock. This is usually due to a wake up operation in
13 the context switch.
14
15 To request the scheduler call switch_to with the runqueue unlocked,
16 you must `#define __ARCH_WANT_UNLOCKED_CTXSW` in a header file
17 (typically the one where switch_to is defined).
18
19 Unlocked context switches introduce only a very minor performance
20 penalty to the core scheduler implementation in the CONFIG_SMP case.
21
22 CPU idle
23 ========
24 Your cpu_idle routines need to obey the following rules:
25
26 1. Preempt should now disabled over idle routines. Should only
27 be enabled to call schedule() then disabled again.
28
29 2. need_resched/TIF_NEED_RESCHED is only ever set, and will never
30 be cleared until the running task has called schedule(). Idle
31 threads need only ever query need_resched, and may never set or
32 clear it.
33
34 3. When cpu_idle finds (need_resched() == 'true'), it should call
35 schedule(). It should not call schedule() otherwise.
36
37 4. The only time interrupts need to be disabled when checking
38 need_resched is if we are about to sleep the processor until
39 the next interrupt (this doesn't provide any protection of
40 need_resched, it prevents losing an interrupt):
41
42 4a. Common problem with this type of sleep appears to be::
43
44 local_irq_disable();
45 if (!need_resched()) {
46 local_irq_enable();
47 *** resched interrupt arrives here ***
48 __asm__("sleep until next interrupt");
49 }
50
51 5. TIF_POLLING_NRFLAG can be set by idle routines that do not
52 need an interrupt to wake them up when need_resched goes high.
53 In other words, they must be periodically polling need_resched,
54 although it may be reasonable to do some background work or enter
55 a low CPU priority.
56
57 - 5a. If TIF_POLLING_NRFLAG is set, and we do decide to enter
58 an interrupt sleep, it needs to be cleared then a memory
59 barrier issued (followed by a test of need_resched with
60 interrupts disabled, as explained in 3).
61
62 arch/x86/kernel/process.c has examples of both polling and
63 sleeping idle functions.
64
65
66 Possible arch/ problems
67 =======================
68
69 Possible arch problems I found (and either tried to fix or didn't):
70
71 sparc - IRQs on at this point(?), change local_irq_save to _disable.
72 - TODO: needs secondary CPUs to disable preempt (See #1)
73

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Architecture code를 위한 CPU scheduler 구현 지침

1-20

기본적으로 architecture의 switch_to function은 runqueue가 lock된 상태에서 호출된다. Switch_to가 runqueue lock을 다시 획득해야 하는 경우가 아니라면 보통 문제가 되지 않는다. 이러한 상황은 대개 context switch 도중 wakeup operation이 발생할 때 생긴다.

Scheduler가 runqueue를 unlock한 상태에서 switch_to를 호출하도록 요청하려면 header file, 보통 switch_to가 정의된 header에서 __ARCH_WANT_UNLOCKED_CTXSW를 define해야 한다. Unlocked context switch가 CONFIG_SMP의 core scheduler 구현에 추가하는 성능 비용은 매우 작다.

CPU idle routine 규칙

22-63
  • Idle routine을 실행하는 동안 preemption은 disable되어야 한다. schedule()을 호출할 때만 enable하고 그 뒤 다시 disable해야 한다.
  • need_resched 또는 TIF_NEED_RESCHED는 set되기만 하며, 실행 중인 task가 schedule()을 호출하기 전에는 clear되지 않는다. Idle thread는 need_resched를 조회하기만 해야 하고 set하거나 clear해서는 안 된다.
  • cpu_idle이 need_resched() == true를 발견하면 schedule()을 호출해야 한다. 그 밖의 경우에는 schedule()을 호출해서는 안 된다.
  • Need_resched를 확인할 때 interrupt를 disable해야 하는 경우는 processor를 다음 interrupt까지 sleep시키려는 때뿐이다. 이는 need_resched를 보호하기 위한 것이 아니라 interrupt를 놓치지 않기 위한 조치다.

다음 코드는 interrupt를 다시 enable한 직후 reschedule interrupt가 도착하고, 그 뒤 processor가 sleep instruction에 들어가 wakeup을 놓칠 수 있는 흔한 문제를 보여 준다.

local_irq_disable();
if (!need_resched()) {
        local_irq_enable();
        /* resched interrupt arrives here */
        __asm__("sleep until next interrupt");
}

need_resched가 set될 때 interrupt 없이도 깨어날 수 있는 idle routine은 TIF_POLLING_NRFLAG를 set할 수 있다. 즉 need_resched를 주기적으로 polling해야 하지만, 그 사이 background work를 수행하거나 낮은 CPU priority로 실행하는 것은 가능하다.

TIF_POLLING_NRFLAG가 set된 상태에서 interrupt sleep에 들어가기로 했다면 flag를 clear한 뒤 memory barrier를 수행해야 한다. 이어서 interrupt를 disable한 상태로 need_resched를 다시 검사해야 한다.

예제와 architecture 문제

65-72

arch/x86/kernel/process.c에는 polling 방식과 sleeping 방식 idle function의 예제가 모두 있다.

문서 작성자가 확인한 sparc 관련 가능성으로는 이 지점에서 IRQ가 켜져 있을 수 있어 local_irq_save를 local_irq_disable로 바꾸는 문제와, secondary CPU에서 preemption을 disable해야 한다는 TODO가 있다.