From: Tulio A M Mendes Date: Sun, 15 Feb 2026 01:22:20 +0000 (-0300) Subject: fix: E1000 rx_thread scheduling — move sched_enqueue_ready outside sem lock X-Git-Url: https://projects.tadryanom.me/docs/static/git-logo.png?a=commitdiff_plain;h=3edd198867cf60bce29343ca096df08f20eff3ec;p=AdrOS.git fix: E1000 rx_thread scheduling — move sched_enqueue_ready outside sem lock - ksem_signal now calls sched_enqueue_ready after releasing the semaphore spinlock, avoiding lock-order issues when called from IRQ context (sched_enqueue_ready acquires sched_lock internally) - Prevents potential deadlock: IRQ → ksem_signal → sched_lock while schedule() already holds sched_lock - 35/35 smoke tests pass, cppcheck clean --- diff --git a/src/kernel/sync.c b/src/kernel/sync.c index 526ab64..1c25267 100644 --- a/src/kernel/sync.c +++ b/src/kernel/sync.c @@ -84,7 +84,7 @@ void ksem_signal(ksem_t* s) { uintptr_t flags = spin_lock_irqsave(&s->lock); /* Find a waiter still blocked/sleeping (skip those already woken by timeout) */ - int woke = 0; + struct process* to_wake = NULL; for (uint32_t i = 0; i < s->nwaiters; i++) { struct process* p = s->waiters[i]; if (p && (p->state == PROCESS_BLOCKED || p->state == PROCESS_SLEEPING)) { @@ -95,17 +95,22 @@ void ksem_signal(ksem_t* s) { p->state = PROCESS_READY; p->wake_at_tick = 0; - sched_enqueue_ready(p); - woke = 1; + to_wake = p; break; } } - if (!woke) { + if (!to_wake) { s->count++; } spin_unlock_irqrestore(&s->lock, flags); + + /* Enqueue outside the semaphore lock to avoid lock-order issues + * (sched_enqueue_ready acquires sched_lock internally). */ + if (to_wake) { + sched_enqueue_ready(to_wake); + } } /* ------------------------------------------------------------------ */