RTOS'ta deadlock nasıl oluşur? Nasıl tespit edilir ve önlenir?
Cevap
Deadlock, iki veya daha fazla task'ın birbirinin elindeki kaynağı süresiz beklemesi sonucu hiçbirinin ilerleyememesidir. Klasik senaryo: Task A önce mutex X'i, sonra Y'yi alır; Task B ise önce Y'yi, sonra X'i almaya çalışır.
/* Task A */ /* Task B */
xSemaphoreTake(mtxSpi, portMAX_DELAY); xSemaphoreTake(mtxI2c, portMAX_DELAY);
xSemaphoreTake(mtxI2c, portMAX_DELAY); xSemaphoreTake(mtxSpi, portMAX_DELAY);
/* A, I2c'yi bekler; B, Spi'yi bekler: ikisi de sonsuza kadar bloklu */Deadlock'ın dört koşulu (Coffman)
- Karşılıklı dışlama (kaynak paylaşılamaz)
- Tut ve bekle (bir kaynağı tutarken diğerini beklemek)
- Zorla geri alınamama (preemption yok)
- Döngüsel bekleme
Bu koşullardan biri kırıldığında deadlock oluşmaz.
Önleme yöntemleri
- Sabit kilit sırası: Tüm kod mutex'leri her zaman aynı global sırayla alır (ör. önce SPI, sonra I2C). En etkili yöntemdir.
- Timeout kullanmak:
portMAX_DELAYyerine anlamlı bir süre verip başarısızlıkta aldığı kilitleri bırakmak ve hata kaydetmek. - Kilit tutarken bloklanmamak: Mutex tutarken queue beklemek,
vTaskDelayçağırmak veya başka bir task'ı beklemek riskli bir alışkanlıktır. - Gatekeeper task: Paylaşılan bir kaynağa (UART, SPI bus) sadece bir task erişir; diğerleri ona queue ile istek gönderir. Mutex'e ihtiyaç kalmaz.
- Kritik bölgeleri küçük tutmak, mümkünse tek bir kilitle tasarlamak.
- Recursive mutex'i sadece gerçekten gerekiyorsa kullanmak; tasarım hatalarını gizleyebilir.
Tespit
- Watchdog check-in mekanizması hangi task'ın takıldığını gösterir.
vTaskList()/uxTaskGetSystemState()ile task durumlarına bakmak (hepsi "Blocked" ise şüphelenin).xSemaphoreGetMutexHolder()ile mutex'in kimde olduğunu loglamak.- SEGGER SystemView, Percepio Tracealyzer gibi trace araçlarıyla olay zaman çizelgesini incelemek.
Not: Benzer bir sorun olan livelock'ta task'lar çalışır ama sürekli birbirine yol verdiği için ilerleme olmaz. Starvation ise düşük öncelikli bir task'ın yüksek öncelikli task'lar yüzünden hiç CPU alamamasıdır.
İ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?
- Priority inversion nedir? Priority inheritance bu sorunu nasıl çözer?
- RTOS'ta preemptive priority-based scheduling nasıl çalışır? Bare-metal super loop yerine ne zaman RTOS tercih edilir?
- RTOS kullanan çok görevli bir sistemde watchdog'u nasıl beslersiniz? Sadece idle task'ta veya bir timer kesmesinde beslemek neden yetersizdir?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.