You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2020/10/17 08:25:07 UTC

[incubator-nuttx] branch releases/10.0 updated: sched: task: Fix nxtask_exit() for SMP

This is an automated email from the ASF dual-hosted git repository.

btashton pushed a commit to branch releases/10.0
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/releases/10.0 by this push:
     new a876a68  sched: task: Fix nxtask_exit() for SMP
a876a68 is described below

commit a876a68d0995c93a694a462d5574f856a336282e
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Thu Oct 8 14:39:22 2020 +0900

    sched: task: Fix nxtask_exit() for SMP
    
    Summary:
    - During Wi-Fi audio streaming test, I found a deadlock in nxtask_exit()
    - Actually, nxtask_exit() was called and tried to enter critical section
    - In enter_critical_section(), there is a deadlock avoidance logic
    - However, if switched to a new rtcb with irqcount=0, the logic did not work
    - Because the 2nd critical section was treated as if it were the 1st one
    - Actually, it tried to run the deadlock avoidance logic
    - But nxtask_exit() was called with critical section (i.e. IRQ already disabled)
    - So the logic did not work as expected because up_irq_restore() did not enable the IRQ.
    - This commit fixes this issue by incrementing irqcount before calling nxtask_terminate()
    - Also it adjusts g_cpu_irqlock and g_cpu_lockset
    
    Impact:
    - Affects SMP only
    
    Testing:
    - Tested with spresense:wifi_smp (smp, ostest, nxplayer, telnetd)
    - Tested with sabre-6quad:smp with QEMU (smp, ostest)
    - Tested with maix-bit:smp with QEMU (smp, ostest)
    - Tested with esp32-core:smp with QEMU (smp, ostest)
    
    Signed-off-by: Masayuki Ishikawa <Ma...@jp.sony.com>
---
 sched/task/task_exit.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/sched/task/task_exit.c b/sched/task/task_exit.c
index 831cb3a..6607f49 100644
--- a/sched/task/task_exit.c
+++ b/sched/task/task_exit.c
@@ -28,6 +28,10 @@
 
 #include  "sched/sched.h"
 
+#ifdef CONFIG_SMP
+#  include "irq/irq.h"
+#endif
+
 #include "signal/signal.h"
 #include "task/task.h"
 
@@ -140,7 +144,36 @@ int nxtask_exit(void)
    */
 
   nxsched_add_blocked(dtcb, TSTATE_TASK_INACTIVE);
+
+#ifdef CONFIG_SMP
+  /* NOTE:
+   * During nxtask_terminate(), enter_critical_section() will be called
+   * to deallocate tcb. However, this would aquire g_cpu_irqlock if
+   * rtcb->irqcount = 0, event though we are in critical section.
+   * To prevent from aquiring, increment rtcb->irqcount here.
+   */
+
+  if (rtcb->irqcount == 0)
+    {
+      spin_setbit(&g_cpu_irqset, this_cpu(), &g_cpu_irqsetlock,
+                  &g_cpu_irqlock);
+    }
+
+  rtcb->irqcount++;
+#endif
+
   ret = nxtask_terminate(dtcb->pid, true);
+
+#ifdef CONFIG_SMP
+  rtcb->irqcount--;
+
+  if (rtcb->irqcount == 0)
+    {
+      spin_clrbit(&g_cpu_irqset, this_cpu(), &g_cpu_irqsetlock,
+                  &g_cpu_irqlock);
+    }
+#endif
+
   rtcb->task_state = TSTATE_TASK_RUNNING;
 
   /* Decrement the lockcount on rctb. */