Priority Inversion 문제 — Mars Pathfinder 사례·Bounded vs Unbounded
#한 줄 요약
“고우선 task가 저우선 task 때문에 막힌다” — 이것이 Priority Inversion입니다.
Priority Inversion은 RTOS 설계에서 가장 악명 높은 함정 중 하나입니다. 우선순위 기반 스케줄링의 전제 자체를 흔드는 현상이라 정확히 이해해 두는 것이 좋습니다.
#Bounded vs Unbounded
#Bounded (정상)
T_high가 mutex를 기다림 (T_low가 보유, critical 짧음).T_low가 critical 종료 (수 µs) 후 mutex release.T_high가 즉시 진행.
대기 시간은 T_low의 critical 길이로 정해집니다. 짧으면 문제가 없습니다.
#Unbounded (위험)
T_high가 mutex 대기,T_low가 보유 중.T_med가 ready 상태가 되어T_low를 preempt.T_med가 계속 진행,T_low는 멈춤.T_high가T_med종료까지 무한 대기.
T_med가 길어지면 T_high도 무한히 대기합니다. 이렇게 되면 시스템이 실패합니다.
#Mars Pathfinder 1997
NASA Pathfinder는 화성 도착 후 지속적으로 reset하는 문제를 겪었습니다.
Task 구성
- 데이터 수집 task (
T_low) - 통신 task (
T_med, long-running) - bus 관리 task (
T_high)
시나리오 — T_low가 bus mutex 획득 → T_med가 T_low를 preempt → T_high가 mutex 대기하다 watchdog timeout으로 reset.
JPL은 Priority Inheritance를 활성화(VxWorks 설정)해 문제를 해결했습니다. 화성 현지의 탐사선을 지구에서 원격으로 디버그한 사례로 유명합니다.
#해결책 1 — Priority Inheritance Protocol (PIP)
T_low가 mutex 보유,T_high가 대기 시 →T_low의 priority를T_highlevel로 boost.T_low가 release하면 → priority를 원래대로 복원.
이렇게 되면 T_med가 T_low를 preempt하지 못합니다. boost된 priority가 더 높기 때문입니다.
configUSE_MUTEX_PI = 1 // FreeRTOS default#해결책 2 — Priority Ceiling Protocol (PCP)
각 mutex에 priority ceiling을 정적으로 부여하는 방식입니다.
- mutex
X의 ceiling을T_highpriority로 설정합니다. T_low가 take하는 즉시 priority가 ceiling level로 boost됩니다.- 결과적으로
T_med가 시작조차 못 합니다.
PCP는 take 즉시 boost합니다. 반면 PI는 wait가 발생해야 boost가 일어납니다.
장점은 deadlock 방지입니다. 단점은 priority를 사전에 결정해야 한다는 점입니다.
#Immediate PCP vs Original PCP
| Immediate | Original | |
|---|---|---|
| Boost 시점 | Take 즉시 | Conflict 시 |
| 구현 | 단순 | 복잡 |
| 채택 | VxWorks·Zephyr | 옛 academic |
#PIP vs PCP
| PIP | PCP | |
|---|---|---|
| 단순성 | ✓ | ✗ |
| Priority 사전 분석 | ✗ | ✓ |
| Deadlock 방지 | ✗ | ✓ |
| 채택 | FreeRTOS·Zephyr | VxWorks |
FreeRTOS의 기본 정책은 PIP입니다.
#PI의 한계 — Chained Inheritance
T_high가 mutex A 대기,T_med가 보유.T_med가 mutex B 대기,T_low가 보유.- →
T_med의 priority가 boost되고, 그 결과T_low도 boost됩니다.
체인이 길수록 boost 전파 비용이 커집니다. RTOS 구현체는 보통 깊이 제한을 둡니다.
#Linux PREEMPT_RT
Mainline mutex에는 PI가 없습니다. PREEMPT_RT의 rtmutex가 PI를 지원하며, 이것이 RT 보장의 핵심입니다.
#실전 — 회피 우선
- Critical section은 짧게 유지합니다(수 µs).
- Lock을 보유한 채로 long blocking 호출을 피합니다.
- Lock 획득 순서를 일관되게 유지합니다.
- 공유 자원을 최소화합니다.
#자주 하는 실수
⚠️ Semaphore로 critical 자원을 보호하면 PI가 적용되지 않습니다.
⚠️
configUSE_MUTEX_PI = 0으로 두면 Pathfinder 사례가 재현됩니다.
⚠️ PI를 믿고 critical section을 길게 두는 것은 위험합니다. bounded일 뿐 zero는 아닙니다.
⚠️ 여러 mutex를 lock order 없이 쓰면 chain inheritance와 deadlock이 함께 발생합니다.
#정리
- Priority Inversion은 고우선 task가 저우선 task에 막히는 현상입니다.
- Bounded(critical 길이로 한정)와 Unbounded(T_med preempt) 두 형태가 있습니다.
- Mars Pathfinder 1997 사건은 PI 활성화로 해결됐습니다.
- PIP(FreeRTOS)와 PCP(VxWorks)가 양대 해결책입니다.
- Semaphore는 PI를 지원하지 않으므로, critical 자원에는 mutex를 씁니다.
#관련 항목
Practical RTOS Internals · 26 of 53
- 1Practical RTOS Internals — 실시간 커널 내부 분석 시리즈 소개
- 2RTOS가 필요한 이유 — 일반 OS와의 결정적 차이
- 3Task와 Thread 개념 — TCB·상태 머신·생명 주기 분석
- 4실시간 스케줄링 알고리즘 비교 — RR·Priority·EDF·RMS
- 5Preemption과 Cooperation — 강제 전환 vs 자발 양보
- 6인터럽트와 RTOS — ISR Context·Deferred Processing·FromISR API
- 7동기화 기초 분석 — Critical Section·Mutual Exclusion·Race Condition
- 8Semaphore 개념 분해 — Counting·Binary·P/V 연산
- 9Mutex 개념 분해 — Ownership·Recursive·Priority Inheritance
- 10큐와 메시지 패싱 — Producer-Consumer·Ring Buffer·전달 의미
- 11실시간성 분석 — Latency·Jitter·Deadline·WCET·RMA
- 12Ready List 자료구조 분석 — Linked List·Bitmap·O(1) Scheduler
- 13Blocked List 자료구조 — Timeout 정렬·Delta List·Two-List Scheme
- 14Scheduler 알고리즘 구현 추적 — Next-Task Selection 로직
- 15Context Switch 원리 분석 — 레지스터 저장·복원·Stack Frame
- 16ARM Cortex-M Context Switch — PendSV·MSP/PSP 어셈블리 추적
- 17ARM Cortex-A Context Switch — Mode 전환·SVC·Banked Registers
- 18RISC-V Context Switch 분석 — ECALL·mret·CSR
- 19RTOS Tick과 타이머 — SysTick·Generic Timer·configTICK_RATE_HZ
- 20Tickless 모드 구현 — Idle Tick Suppression·Sleep·Wake 보정
- 21Scheduler Latency 측정 기법 — GPIO Toggle·DWT·ftrace·cyclictest
- 22RTOS Tracing과 Observability — Tracealyzer·SystemView·ITM/ETM
- 23Critical Section 구현 비교 — IRQ Disable·BASEPRI·Spinlock
- 24Semaphore 내부 구현 추적 — Counter·Wait List·ISR-Safe Variant
- 25Mutex 내부 구현 추적 — Owner·Recursion Count·ISR 금지
- 26Priority Inversion 문제 — Mars Pathfinder 사례·Bounded vs Unbounded
- 27Priority Inheritance 구현 — Inherit·Disinherit·Chain
- 28Priority Ceiling Protocol — Immediate vs Original 비교
- 29Queue 내부 구현 추적 — Ring Buffer·2 Wait Lists·Atomic Send/Receive
- 30Event Group 분석 — Bit Flag·AND/OR Wait·Sync Barrier
- 31ISR-Safe API 설계 — FromISR 패턴·Higher Priority Wake·Deferred Work
- 32Deadlock 분석 — 4 조건·Wait-for Graph·Lock Ordering·Timeout
- 33Stream Buffer와 Message Buffer — FreeRTOS 10의 Lock-Free SPSC
- 34실시간 메모리 요구사항 — Determinism·Fragmentation·WCET
- 35FreeRTOS Heap_1~5 분석 — 5종 Allocator의 구조와 트레이드오프
- 36TLSF Allocator 분석 — Two-Level Segregated Fit O(1)
- 37Static Allocation — 컴파일 타임으로 동적 위험 제거하기
- 38Memory Pool — Fixed-Size Block Allocator의 단순함과 강력함
- 39Stack Overflow 탐지 — Canary·MPU·Watermark 3중 방어
- 40SMP RTOS 설계 — Ready List·Affinity·IPI·Load Balancing
- 41SMP Spinlock 구현 — LDREX/STREX·Ticket Lock·MCS·WFE/SEV
- 42Software Timer 분석 — Daemon Task·자료구조·ISR-Safe API
- 43RTOS System Call — SVC·ECALL·User/Kernel 분리·FreeRTOS-MPU
- 44TrustZone과 TF-M — Secure/Non-Secure·NSC Veneer·PSA
- 45AMP와 OpenAMP — Heterogeneous SoC·RPMsg·remoteproc
- 46C++ in RTOS — RAII·std::thread·ETL·Coroutine
- 47FreeRTOS 소스 분석 — tasks.c·queue.c·port.c 추적
- 48Zephyr 커널 분석 — k_thread·k_sem·Driver Model
- 49RT-Thread 분석 — Object 모델·Components·Smart·Studio
- 50RTOS 포팅 가이드 — 새 아키텍처에 옮기는 절차
- 51RTOS 선택 가이드 — Footprint·License·Certification·Ecosystem
- 52Apache NuttX 분석 — POSIX·PX4·NASA Ingenuity
- 53PREEMPT_RT Linux — Mainline 6.12·Xenomai 4·EVL
관련 글
PREEMPT_RT Linux — Mainline 6.12·Xenomai 4·EVL
2024년 9월 Linux 6.12 mainline에 합류한 PREEMPT_RT의 핵심 변경을 정리하고, Xenomai 4·EVL과 함께 RTOS와의 선택 기준을 비교합니다. threaded IRQ·sleeping spinlock·cyclictest까지 한 지도에 모읍니다.
Apache NuttX 분석 — POSIX·PX4·NASA Ingenuity
NuttX의 POSIX-compliant 구조를 따라가며 PX4 autopilot과 NASA Ingenuity 화성 헬리콥터 채택 배경을 정리합니다. Flat/Protected/Kernel 빌드, VFS, 네트워크, NSH, micro-ROS 통합까지 한 지도로 모읍니다.
RTOS 선택 가이드 — Footprint·License·Certification·Ecosystem
FreeRTOS·Zephyr·ThreadX·RT-Thread·NuttX·VxWorks·QNX·INTEGRITY·SafeRTOS·µC/OS·PX5를 한 표에 모아 비교합니다. IoT·자동차·항공·산업·의료·웨어러블·드론별 추천과 결정 기준을 정리합니다.
이 글을 참조하는 글 (6)
- Deadlock 분석 — 4 조건·Wait-for Graph·Lock Ordering·Timeout— Practical RTOS Internals
- Priority Inheritance 구현 — Inherit·Disinherit·Chain— Practical RTOS Internals
- Mutex 내부 구현 추적 — Owner·Recursion Count·ISR 금지— Practical RTOS Internals
- Mutex 개념 분해 — Ownership·Recursive·Priority Inheritance— Practical RTOS Internals
- Priority Inversion 진단·예방 — Mars Pathfinder Lesson 추적— Modern Embedded Recipes
- RTOS Mutex 활용 — Recursive·Priority Inheritance 적용— Modern Embedded Recipes