Priority inversion nedir? Priority inheritance bu sorunu nasıl çözer?
Cevap
Priority inversion, yüksek öncelikli bir task'ın, düşük öncelikli bir task'ın tuttuğu kaynağı beklerken orta öncelikli bir task tarafından dolaylı olarak bloklanmasıdır.
Senaryo
Task'lar: H (yüksek), M (orta), L (düşük). L ile H aynı mutex'i kullanır.
- L mutex'i alır, kritik bölgeye girer.
- H hazır olur, L'yi keser, mutex'i ister ve bloklanır.
- L devam eder, ama bu arada M hazır olur. M, L'den yüksek öncelikli olduğu için L'yi keser.
- M uzun süre çalışır. L mutex'i bırakamaz, H bekler.
Sonuç: Mutex ile hiç ilgisi olmayan M, en yüksek öncelikli H'yi süresiz geciktirir; sınırsız (unbounded) inversion. Ünlü örnek: Mars Pathfinder (1997) bu yüzden sürekli watchdog reset'i yaşadı; sorun uzaktan priority inheritance açılarak çözüldü.
Priority inheritance
Düşük öncelikli task, mutex'i beklediği sürece bekleyen en yüksek öncelikli task'ın önceliğini miras alır. Senaryoda L geçici olarak H önceliğine yükselir; M onu kesemez. L mutex'i bırakınca eski önceliğine döner ve H hemen çalışır.
FreeRTOS'ta mutex (xSemaphoreCreateMutex) priority inheritance uygular; binary semaphore uygulamaz. Kaynak koruması için bu yüzden semaphore değil mutex kullanılmalıdır.
SemaphoreHandle_t spi_mutex = xSemaphoreCreateMutex();
void task_x(void *arg) {
for (;;) {
if (xSemaphoreTake(spi_mutex, pdMS_TO_TICKS(50)) == pdTRUE) {
spi_transfer(...);
xSemaphoreGive(spi_mutex);
} else {
/* timeout: hata raporla, kilitlenme yerine tespit */
}
}
}Priority ceiling protocol
Alternatif: her mutex'e onu kullanabilecek en yüksek task önceliği (ceiling) atanır; mutex'i alan task hemen bu önceliğe çıkar. Inversion'ı sınırlar ve deadlock'u da önler, ama her kaynağın kullanıcılarının önceden bilinmesini gerektirir. OSEK/AUTOSAR bu yaklaşımı kullanır.
Tasarım önerileri
- Kritik bölgeleri olabildiğince kısa tutun.
- Mutex tutarken bloklayan çağrı (delay, başka bir queue bekleme) yapmayın.
- İç içe mutex alıyorsanız her yerde aynı sırayla alın (deadlock önlemi).
- Bir kaynağa tek bir gatekeeper task sahip olsun, diğerleri ona queue ile istek göndersin; mutex ihtiyacı tamamen kalkar.
İlgili RTOS soruları
- RTOS nedir? Bare-metal programlamadan farkı nedir?
- RTOS'ta ISR içinde hangi API'ler kullanılabilir? Deferred interrupt processing nasıl yapılır?
- FreeRTOS'ta queue, binary semaphore, counting semaphore ve mutex arasındaki farklar nelerdir? Hangisi ne zaman kullanılır?
- RTOS'ta preemptive priority-based scheduling nasıl çalışır? Bare-metal super loop yerine ne zaman RTOS tercih edilir?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.