diff --git a/ChangeLog b/ChangeLog index 25fdef764c..5333449b2e 100755 --- a/ChangeLog +++ b/ChangeLog @@ -13466,5 +13466,13 @@ (2016-12-24). * STM32 F4: Allow dma in 1 bit mode in STM32F4xxx. From David Sidrane (2016-12-24). + * termios.h: Fix CRTSCTS define to include input and output flow. + From Lorenz Meier (2016-12-26). + * SMP: Enforce this rule: Tasks which are normally restored when + sched_unlock() is called must remain pending (1) if we are in a + critical section, i.e., g_cpu_irqlock is locked , or (2) other CPUs + still have pre-emption disabled, i.e., g_cpu_schedlock is locked. In + those cases, the release of the pending tasks must be deferred until + those conditions are met (2016-12-26). 7.20 2017-xx-xx Gregory Nutt diff --git a/sched/irq/irq_csection.c b/sched/irq/irq_csection.c index c9f9f91c18..16be425cd7 100644 --- a/sched/irq/irq_csection.c +++ b/sched/irq/irq_csection.c @@ -513,12 +513,9 @@ void leave_critical_section(irqstate_t flags) 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. + * is also enabled. This is necessary becaue we may have + * deferred the up_release_pending() call in sched_unlock() + * because we were within a critical section then. */ if (g_pendingtasks.head != NULL && @@ -529,9 +526,6 @@ void leave_critical_section(irqstate_t flags) * * 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 ff676c827a..0ad26242a7 100644 --- a/sched/sched/sched_unlock.c +++ b/sched/sched/sched_unlock.c @@ -44,6 +44,7 @@ #include #include +#include "irq/irq.h" #include "sched/sched.h" /**************************************************************************** @@ -113,16 +114,30 @@ int sched_unlock(void) #endif /* Release any ready-to-run tasks that have collected in - * g_pendingtasks. In the SMP case, the scheduler remains - * locked if interrupts are disabled. + * g_pendingtasks. * * NOTE: This operation has a very high likelihood of causing * this task to be switched out! */ #ifdef CONFIG_SMP - if (!spin_islocked(&g_cpu_schedlock) && g_pendingtasks.head != NULL) + /* In the SMP case, the tasks remains pend(1) if we are + * in a critical section, i.e., g_cpu_irqlock is locked , or (2) + * other CPUs still have pre-emption disabled, i.e., + * g_cpu_schedlock is locked. In those cases, the release of the + * pending tasks must be deferred until those conditions are met.ing + */ + + if (!spin_islocked(&g_cpu_schedlock) && + !spin_islocked(&g_cpu_irqlock) && + g_pendingtasks.head != NULL) #else + /* In the single CPU case, decrementing irqcount to zero is + * sufficient to release the pending tasks. Further, in that + * configuration, critical sections and pre-emption can operate + * fully independently. + */ + if (g_pendingtasks.head != NULL) #endif {