diff --git a/sched/irq/irq_csection.c b/sched/irq/irq_csection.c index 5b517de8bbf..c9f9f91c18c 100644 --- a/sched/irq/irq_csection.c +++ b/sched/irq/irq_csection.c @@ -507,6 +507,36 @@ void leave_critical_section(irqstate_t flags) rtcb->irqcount = 0; spin_clrbit(&g_cpu_irqset, cpu, &g_cpu_irqsetlock, &g_cpu_irqlock); + + /* Have all CPUs released the lock? */ + + if (!spin_islocked(&g_cpu_irqlock)) + { + /* Check if there are pending tasks and that pre-emption + * is also enabled. + * + * REVISIT: Is there an issue here? up_release_pending() + * must be called from within a critical section but here + * we have just left the critical section. At least we + * still have interrupts disabled on this CPU. + */ + + if (g_pendingtasks.head != NULL && + !spin_islocked(&g_cpu_schedlock)) + { + /* Release any ready-to-run tasks that have collected + * in g_pendingtasks if the scheduler is not locked. + * + * NOTE: This operation has a very high likelihood of + * causing this task to be switched out! + * + * REVISIT: Should this not be done while we are in the + * critical section. + */ + + up_release_pending(); + } + } } } } diff --git a/sched/sched/sched_unlock.c b/sched/sched/sched_unlock.c index df783dee7b7..ff676c827a2 100644 --- a/sched/sched/sched_unlock.c +++ b/sched/sched/sched_unlock.c @@ -102,8 +102,7 @@ int sched_unlock(void) #ifdef CONFIG_SMP /* The lockcount has decremented to zero and we need to perform - * release our hold on the lock. Pre-emption may still be locked - * from other CPUs. + * release our hold on the lock. */ DEBUGASSERT(g_cpu_schedlock == SP_LOCKED && @@ -119,12 +118,13 @@ int sched_unlock(void) * * NOTE: This operation has a very high likelihood of causing * this task to be switched out! - * - * NOTE: In SMP mode, pre-emption may still be locked due to - * operations on other CPUs. */ +#ifdef CONFIG_SMP + if (!spin_islocked(&g_cpu_schedlock) && g_pendingtasks.head != NULL) +#else if (g_pendingtasks.head != NULL) +#endif { up_release_pending(); }