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

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 43d26e289094346f7a2c7d303716585b15582882
Author: wangshaoxin <[email protected]>
AuthorDate: Thu Mar 13 09:50:31 2025 +0800

    drivers/rptun: solve the poweroff stuck problem
    
    The rpmsg_ioctl() function will first obtain the read lock before
    traversing g_rpmsg, then the rpmsg_dev_destory function will try
    to obtain the write lock.
    
    At this time, rpmsg_ioctl does not release the read lock, resulting
    in a deadlock.
    
    To solve this problem, add a standardalone list for the rptun instance
    to avoid hold the rpmsg lock when execute rptun_poweroff()
    
    Backtrace:
    Thread 14 nsh_main
    0  0x4412b9da in up_switch_context (tcb=0xeac03380, rtcb=0xe7f02480) at 
sim/sim_switchcontext.c:95
    1  0x43fbe5e4 in nxsem_wait_slow (sem=0x5179d570 <g_rpmsg_lock+16>) at 
semaphore/sem_wait.c:170
    2  0x43fbeacf in nxsem_wait (sem=0x5179d570 <g_rpmsg_lock+16>) at 
semaphore/sem_wait.c:272
    3  0x44671a26 in down_write (rwsem=0x5179d560 <g_rpmsg_lock>) at 
semaphore/sem_rw.c:248
    4  0x4401e255 in rpmsg_device_destory (rpmsg=0xe7b03280) at 
rpmsg/rpmsg.c:469
    5  0x4402f5fe in rptun_dev_stop (rproc=0xe7b033e4, stop_ns=true) at 
rptun/rptun.c:973
    6  0x4402aa28 in rptun_ioctl (rpmsg=0xe7b03280, cmd=11109, arg=0) at 
rptun/rptun.c:661
    7  0x4401ba1e in rpmsg_dev_ioctl_ (rpmsg=0xe7b03280, cmd=11109, arg=0) at 
rpmsg/rpmsg.c:137
    8  0x4401ee88 in rpmsg_ioctl (cpuname=0x0, cmd=11109, arg=0) at 
rpmsg/rpmsg.c:562
    9  0x44030cb0 in rptun_poweroff (cpuname=0x0) at rptun/rptun.c:1183
    10 0x43f27be2 in board_power_off (status=0) at sim/sim_head.c:211
    11 0x446fd933 in boardctl (cmd=65283, arg=0) at boardctl.c:401
    12 0x44313b95 in cmd_poweroff (vtbl=0xe7600e80, argc=1, argv=0xe7824350) at 
nsh_syscmds.c:368
    13 0x442d148c in nsh_command (vtbl=0xe7600e80, argc=1, argv=0xe7824350) at 
nsh_command.c:1275
    14 0x442f65f5 in nsh_execute (vtbl=0xe7600e80, argc=1, argv=0xe7824350, 
param=0xe78242b0) at nsh_parse.c:716
    15 0x44304fb4 in nsh_parse_command (vtbl=0xe7600e80, cmdline=0xe7601338 
"poweroff") at nsh_parse.c:2809
    16 0x44305a50 in nsh_parse (vtbl=0xe7600e80, cmdline=0xe7601338 "poweroff") 
at nsh_parse.c:2919
    17 0x442bdc91 in nsh_session (pstate=0xe7600e80, login=1, argc=1, 
argv=0xe7814870) at nsh_session.c:246
    18 0x442bbbe5 in nsh_consolemain (argc=1, argv=0xe7814870) at 
nsh_consolemain.c:75
    19 0x4422b4bb in nsh_main (argc=1, argv=0xe7814870) at nsh_main.c:74
    20 0x440ee098 in nxtask_startup (entrypt=0x4422b39a <nsh_main>, argc=1, 
argv=0xe7814870) at sched/task_startup.c:72
    21 0x43fa1d6e in nxtask_start () at task/task_start.c:116
    22 0x4412982c in pre_start () at sim/sim_initialstate.c:53
    23 0x00000000 in ?? ()
    
    Signed-off-by: wangshaoxin <[email protected]>
---
 drivers/rptun/rptun.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c
index bdc0a68bf97..05cd4e43a14 100644
--- a/drivers/rptun/rptun.c
+++ b/drivers/rptun/rptun.c
@@ -62,6 +62,7 @@ struct rptun_priv_s
   struct rpmsg_virtio_device   rvdev;
   FAR struct rptun_dev_s       *dev;
   struct remoteproc            rproc;
+  struct metal_list            node;
   struct rpmsg_virtio_shm_pool pool[2];
   sem_t                        semtx;
   sem_t                        semrx;
@@ -165,6 +166,9 @@ static const struct rpmsg_ops_s g_rptun_rpmsg_ops =
   rptun_get_cpuname,
 };
 
+static struct metal_list g_rptun_priv = METAL_INIT_LIST(g_rptun_priv);
+static metal_mutex_t g_rptun_lock = METAL_MUTEX_INIT(g_rptun_lock);
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -1161,6 +1165,9 @@ int rptun_initialize(FAR struct rptun_dev_s *dev)
   pm_wakelock_init(&priv->wakelock, name, PM_IDLE_DOMAIN, PM_IDLE);
 #endif
 
+  metal_mutex_acquire(&g_rptun_lock);
+  metal_list_add_tail(&g_rptun_priv, &priv->node);
+  metal_mutex_release(&g_rptun_lock);
   return OK;
 
 err_thread:
@@ -1174,17 +1181,53 @@ err_driver:
   return ret;
 }
 
+static int rptun_ioctl_foreach(FAR const char *cpuname, int cmd,
+                               unsigned long value)
+{
+  FAR struct metal_list *node;
+  bool needlock = !up_interrupt_context() && !sched_idletask();
+  int ret = OK;
+
+  if (needlock)
+    {
+      metal_mutex_acquire(&g_rptun_lock);
+    }
+
+  metal_list_for_each(&g_rptun_priv, node)
+    {
+      FAR struct rptun_priv_s *priv;
+
+      priv = metal_container_of(node, struct rptun_priv_s, node);
+
+      if (!cpuname || !strcmp(RPTUN_GET_CPUNAME(priv->dev), cpuname))
+        {
+          ret = rptun_ioctl(&priv->rpmsg, cmd, value);
+          if (ret < 0)
+            {
+              break;
+            }
+        }
+    }
+
+  if (needlock)
+    {
+      metal_mutex_release(&g_rptun_lock);
+    }
+
+  return ret;
+}
+
 int rptun_boot(FAR const char *cpuname)
 {
-  return rpmsg_ioctl(cpuname, RPTUNIOC_START, 0);
+  return rptun_ioctl_foreach(cpuname, RPTUNIOC_START, 0);
 }
 
 int rptun_poweroff(FAR const char *cpuname)
 {
-  return rpmsg_ioctl(cpuname, RPTUNIOC_STOP, 0);
+  return rptun_ioctl_foreach(cpuname, RPTUNIOC_STOP, 0);
 }
 
 int rptun_reset(FAR const char *cpuname, int value)
 {
-  return rpmsg_ioctl(cpuname, RPTUNIOC_RESET, value);
+  return rptun_ioctl_foreach(cpuname, RPTUNIOC_RESET, value);
 }

Reply via email to