Системы реального времени
Priority Inversion и протоколы наследования
Mars Pathfinder, 1997
Mars Pathfinder приземлился на Марс 4 июля 1997 года - первая успешная посадка после 21-летнего перерыва. Через несколько дней начались загадочные перезагрузки. Инженеры JPL диагностировали priority inversion в VxWorks через анализ логов телеметрии. Патч был загружен с Земли через командный uplink. После активации PIP система работала стабильно до конца миссии.
NASA потратила $280 млн на Mars Pathfinder. Миссия едва не провалилась из-за одной строки конфигурации mutex в VxWorks - флага `inherit_priority = true`. Priority inversion - не академическая проблема: это реальный failure mode в любой multitasking системе с shared resources.
- **VxWorks (aerospace, automotive)** - PCP включён по умолчанию в safety-critical конфигурациях после инцидента с Pathfinder
- **POSIX pthread_mutexattr_setprotocol** - стандартизированный API для PIP (PTHREAD_PRIO_INHERIT) и PCP (PTHREAD_PRIO_PROTECT)
- **FreeRTOS, RTEMS** - configUSE_MUTEXES с priority inheritance; используется в medical devices, automotive ECU
Priority Inversion: когда низший блокирует высший
В 1997 году марсоход Mars Pathfinder начал периодически перезагружаться после посадки. Телеметрия терялась. Причина - классическая проблема **Priority Inversion**: низкоприоритетная задача удерживала mutex, необходимый высокоприоритетной, а среднеприоритетные задачи вытесняли низкую - и высокая оказывалась заблокирована навсегда.
**Почему это опасно в RTS:** в системах реального времени Task_H имеет deadline. Если она не завершится вовремя из-за priority inversion - нарушение deadline может привести к catastrophic failure (как на Mars Pathfinder).
Priority Inversion возникает, когда:
Priority Inheritance Protocol (PIP): временное повышение приоритета
**Priority Inheritance Protocol (PIP):** когда задача L удерживает mutex, нужный задаче H с более высоким приоритетом, задача L временно наследует приоритет H. Как только L освобождает mutex - приоритет возвращается к исходному. Это устраняет инверсию: Task_M не может вытеснить Task_L, потому что L временно имеет приоритет HIGH.
**Ограничение PIP:** не предотвращает deadlock. Пример: Task_A держит M1 и ждёт M2; Task_B держит M2 и ждёт M1. PIP повысит им приоритеты, но deadlock останется. Также PIP может вызвать chained blocking - цепочку наследований через несколько задач.
При PIP, когда Task_L наследует приоритет Task_H?
Priority Ceiling Protocol (PCP): превентивная защита
**Priority Ceiling Protocol (PCP)** - превентивный подход. Каждому mutex заранее назначается **ceiling** - максимальный приоритет среди всех задач, которые могут его захватить. Задача может захватить mutex только если её приоритет **строго выше** ceiling всех mutex, уже захваченных другими задачами.
| Свойство | Без протокола | PIP | PCP |
|---|---|---|---|
| Priority inversion | Неограниченный | Ограниченный | Ограниченный |
| Deadlock prevention | Нет | Нет | Да (доказуемо) |
| Chained blocking | Возможен | Возможен | Нет |
| Overhead | Нет | Низкий | Средний (проверка ceiling) |
| Реализация | Простая | Умеренно | Сложнее |
Какое ключевое преимущество PCP перед PIP?
Mars Pathfinder: реальная катастрофа из-за Priority Inversion
4 июля 1997 года Mars Pathfinder успешно приземлился на Марс. Через несколько дней система начала периодически перезагружаться, теряя данные. ОС VxWorks обнаруживала «просроченный» системный bus mutex и делала полный reset системы.
**Урок Mars Pathfinder:** баг был известен до запуска - его воспроизвели на Земле, но посчитали редким. В реальных условиях на Марсе он проявился регулярно. Правило: если priority inversion возможна теоретически - она произойдёт в production.
Priority inversion - редкая теоретическая проблема, не стоит усложнять систему PIP/PCP.
Priority inversion воспроизводима и повторяется в production при определённой нагрузке. Mars Pathfinder - доказательство: проблему знали, но недооценили. В системах с deadline реального времени последствия катастрофичны.
Вероятность priority inversion растёт с количеством задач и интенсивностью операций с mutex. В embedded системах с жёсткими deadline (automotive, aerospace, medical) это unacceptable risk.
Почему Mars Pathfinder перезагружался, а не просто «зависал»?
Priority Inversion и протоколы
- **Priority Inversion:** LOW держит mutex, HIGH ждёт, MEDIUM вытесняет LOW - HIGH заблокирована задачей MEDIUM
- **PIP (Priority Inheritance):** LOW временно наследует приоритет HIGH; ограничивает inversion, но не предотвращает deadlock
- **PCP (Priority Ceiling):** mutex имеет ceiling = max приоритет возможных владельцев; задача блокируется максимум один раз, deadlock невозможен
- **Mars Pathfinder:** реальный инцидент - одна строка конфига PIP устранила системные reboot'ы на Марсе
Связанные темы
Priority Inversion - частный случай проблем синхронизации в многозадачных системах.
- Multicore Real-Time Scheduling — На многоядерных системах priority inversion сложнее из-за миграции задач
- Rate Monotonic Scheduling — RMS анализ предполагает отсутствие unbounded priority inversion
Вопросы для размышления
- Почему PCP гарантирует отсутствие deadlock, а PIP - нет? Какое свойство ceiling делает deadlock невозможным?
- В каких сценариях PIP достаточен, и не нужно платить overhead PCP?
- Как watchdog timer в VxWorks, призванный защищать от сбоев, сам стал причиной видимой «поломки» Mars Pathfinder?