mirror of
https://github.com/apache/nuttx.git
synced 2026-05-24 07:46:16 +08:00
sim: replace wdog to work queue to avoid deadlock
The wdog callbacks are executed in the host's signal handler context, which has strict limitations on what operations can be safely performed. Specifically, signal handlers should not call non-async-signal-safe functions (e.g., sim_alsa use mutex_lock in wdog and cause deadlock). This change only replaces uses of wdog for periodic tasks. Other interrupt callbacks that are still invoked from the host signal handler are not replace to work queue. Signed-off-by: guanyi3 <guanyi3@xiaomi.com>
This commit is contained in:
@@ -29,8 +29,7 @@
|
||||
#include <nuttx/audio/audio.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <nuttx/wdog.h>
|
||||
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <debug.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
@@ -53,10 +52,9 @@ struct sim_audio_s
|
||||
{
|
||||
struct audio_lowerhalf_s dev;
|
||||
struct dq_queue_s pendq;
|
||||
struct work_s work;
|
||||
mutex_t pendlock;
|
||||
|
||||
struct wdog_s wdog; /* Watchdog for event loop */
|
||||
|
||||
bool playback;
|
||||
bool offload;
|
||||
bool paused;
|
||||
@@ -1134,13 +1132,14 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sim_alsa_interrupt(wdparm_t arg)
|
||||
static void sim_audio_work_handler(FAR void *arg)
|
||||
{
|
||||
struct sim_audio_s *priv = (struct sim_audio_s *)arg;
|
||||
|
||||
sim_audio_process(priv);
|
||||
|
||||
wd_start_next(&priv->wdog, SIM_AUDIO_PERIOD, sim_alsa_interrupt, arg);
|
||||
work_queue_next(HPWORK, &priv->work, sim_audio_work_handler, priv,
|
||||
SIM_AUDIO_PERIOD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1169,7 +1168,9 @@ struct audio_lowerhalf_s *sim_audio_initialize(bool playback, bool offload)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wd_start(&priv->wdog, 0, sim_alsa_interrupt, (wdparm_t)priv);
|
||||
memset(&priv->work, 0, sizeof(struct work_s));
|
||||
work_queue(HPWORK, &priv->work, sim_audio_work_handler, priv,
|
||||
SIM_AUDIO_PERIOD);
|
||||
|
||||
/* Setting default config */
|
||||
|
||||
@@ -1181,6 +1182,5 @@ struct audio_lowerhalf_s *sim_audio_initialize(bool playback, bool offload)
|
||||
priv->channels = 2;
|
||||
priv->bps = 16;
|
||||
priv->frame_size = 4;
|
||||
|
||||
return &priv->dev;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <nuttx/power/pm.h>
|
||||
#include <nuttx/spi/spi_flash.h>
|
||||
#include <nuttx/spi/qspi_flash.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -51,11 +52,11 @@
|
||||
|
||||
#if defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK) || \
|
||||
defined(CONFIG_SIM_BUTTONS)
|
||||
static struct wdog_s g_x11event_wdog; /* Watchdog for event loop */
|
||||
static struct work_s g_x11event_work; /* Watchdog for event loop */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SIM_X11FB
|
||||
static struct wdog_s g_x11update_wdog; /* Watchdog for update loop */
|
||||
static struct work_s g_x11update_work; /* Watchdog for update loop */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@@ -88,11 +89,11 @@ static void sim_init_cmdline(void)
|
||||
|
||||
#if defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK) || \
|
||||
defined(CONFIG_SIM_BUTTONS)
|
||||
static void sim_x11event_interrupt(wdparm_t arg)
|
||||
static void sim_x11event_work(void *arg)
|
||||
{
|
||||
sim_x11events();
|
||||
wd_start_next((FAR struct wdog_s *)arg, SIM_X11EVENT_PERIOD,
|
||||
sim_x11event_interrupt, arg);
|
||||
work_queue_next(HPWORK, &g_x11event_work, sim_x11event_work,
|
||||
NULL, SIM_X11EVENT_PERIOD);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -105,11 +106,11 @@ static void sim_x11event_interrupt(wdparm_t arg)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SIM_X11FB
|
||||
static void sim_x11update_interrupt(wdparm_t arg)
|
||||
static void sim_x11update_work(void *arg)
|
||||
{
|
||||
sim_x11loop();
|
||||
wd_start_next((FAR struct wdog_s *)arg, SIM_X11UPDATE_PERIOD,
|
||||
sim_x11update_interrupt, arg);
|
||||
work_queue_next(HPWORK, &g_x11update_work, sim_x11update_work,
|
||||
NULL, SIM_X11UPDATE_PERIOD);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -317,12 +318,12 @@ void up_initialize(void)
|
||||
|
||||
#if defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK) || \
|
||||
defined(CONFIG_SIM_BUTTONS)
|
||||
wd_start(&g_x11event_wdog, 0, sim_x11event_interrupt,
|
||||
(wdparm_t)&g_x11event_wdog);
|
||||
work_queue(HPWORK, &g_x11event_work, sim_x11event_work,
|
||||
NULL, SIM_X11EVENT_PERIOD);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SIM_X11FB
|
||||
wd_start(&g_x11update_wdog, 0, sim_x11update_interrupt,
|
||||
(wdparm_t)&g_x11update_wdog);
|
||||
work_queue(HPWORK, &g_x11update_work, sim_x11update_work,
|
||||
NULL, SIM_X11UPDATE_PERIOD);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ struct sim_netdev_s
|
||||
struct netdev_lowerhalf_s dev;
|
||||
#endif
|
||||
uint8_t buf[SIM_NETDEV_BUFSIZE]; /* Used when packet buffer is fragmented */
|
||||
struct wdog_s wdog;
|
||||
struct work_s work;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -268,7 +268,7 @@ static void netdriver_rxready_interrupt(void *priv)
|
||||
netdev_lower_rxready(dev);
|
||||
}
|
||||
|
||||
static void sim_netdev_interrupt(wdparm_t arg)
|
||||
static void sim_netdev_work(void *arg)
|
||||
{
|
||||
struct sim_netdev_s *priv = (struct sim_netdev_s *)arg;
|
||||
struct netdev_lowerhalf_s *dev = &priv->dev;
|
||||
@@ -278,8 +278,8 @@ static void sim_netdev_interrupt(wdparm_t arg)
|
||||
netdev_lower_rxready(dev);
|
||||
}
|
||||
|
||||
wd_start_next(&priv->wdog, SIM_NETDEV_PERIOD,
|
||||
sim_netdev_interrupt, arg);
|
||||
work_queue_next(HPWORK, &priv->work, sim_netdev_work, arg,
|
||||
SIM_NETDEV_PERIOD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -330,8 +330,9 @@ int sim_netdriver_init(void)
|
||||
|
||||
netdev_lower_register(dev, devidx < CONFIG_SIM_WIFIDEV_NUMBER ?
|
||||
NET_LL_IEEE80211 : NET_LL_ETHERNET);
|
||||
wd_start(&g_sim_dev[devidx].wdog, 0,
|
||||
sim_netdev_interrupt, (wdparm_t)&g_sim_dev[devidx]);
|
||||
work_queue(HPWORK, &g_sim_dev[devidx].work,
|
||||
sim_netdev_work, &g_sim_dev[devidx],
|
||||
SIM_NETDEV_PERIOD);
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <nuttx/rpmsg/rpmsg_virtio_lite.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include "sim_internal.h"
|
||||
|
||||
@@ -67,9 +67,9 @@ struct sim_rpmsg_virtio_dev_s
|
||||
char cpuname[RPMSG_NAME_SIZE + 1];
|
||||
char shmemname[RPMSG_NAME_SIZE + 1];
|
||||
|
||||
/* Wdog for transmit */
|
||||
/* Work for transmit */
|
||||
|
||||
struct wdog_s wdog;
|
||||
struct work_s work;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -164,7 +164,7 @@ sim_rpmsg_virtio_register_callback(struct rpmsg_virtio_lite_s *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sim_rpmsg_virtio_work(wdparm_t arg)
|
||||
static void sim_rpmsg_virtio_work(void *arg)
|
||||
{
|
||||
struct sim_rpmsg_virtio_dev_s *dev = (struct sim_rpmsg_virtio_dev_s *)arg;
|
||||
|
||||
@@ -189,8 +189,8 @@ static void sim_rpmsg_virtio_work(wdparm_t arg)
|
||||
}
|
||||
}
|
||||
|
||||
wd_start(&dev->wdog, SIM_RPMSG_VIRTIO_WORK_DELAY,
|
||||
sim_rpmsg_virtio_work, (wdparm_t)dev);
|
||||
work_queue_next(HPWORK, &dev->work, sim_rpmsg_virtio_work, dev,
|
||||
SIM_RPMSG_VIRTIO_WORK_DELAY);
|
||||
}
|
||||
|
||||
static int sim_rpmsg_virtio_notify(struct rpmsg_virtio_lite_s *dev,
|
||||
@@ -252,5 +252,6 @@ int sim_rpmsg_virtio_init(const char *shmemname, const char *cpuname,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return wd_start(&priv->wdog, 0, sim_rpmsg_virtio_work, (wdparm_t)priv);
|
||||
return work_queue(HPWORK, &priv->work, sim_rpmsg_virtio_work, priv,
|
||||
SIM_RPMSG_VIRTIO_WORK_DELAY);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <nuttx/drivers/addrenv.h>
|
||||
#include <nuttx/rptun/rptun.h>
|
||||
#include <nuttx/list.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include "sim_internal.h"
|
||||
|
||||
@@ -74,9 +74,9 @@ struct sim_rptun_dev_s
|
||||
char shmemname[RPMSG_NAME_SIZE + 1];
|
||||
pid_t pid;
|
||||
|
||||
/* Wdog for transmit */
|
||||
/* Work for transmit */
|
||||
|
||||
struct wdog_s wdog;
|
||||
struct work_s work;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -358,7 +358,8 @@ static void sim_rptun_work(wdparm_t arg)
|
||||
}
|
||||
}
|
||||
|
||||
wd_start(&dev->wdog, SIM_RPTUN_WORK_DELAY, sim_rptun_work, (wdparm_t)dev);
|
||||
work_queue_next(HPWORK, &dev->work, sim_rptun_work, dev,
|
||||
SIM_RPTUN_WORK_DELAY);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -405,5 +406,6 @@ int sim_rptun_init(const char *shmemname, const char *cpuname, int master)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return wd_start(&dev->wdog, 0, sim_rptun_work, (wdparm_t)dev);
|
||||
return work_queue(HPWORK, &dev->work, sim_rptun_work, dev,
|
||||
SIM_RPTUN_WORK_DELAY);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
@@ -159,7 +159,7 @@ struct sim_usbdev_s
|
||||
uint16_t epavail; /* Bitset of available endpoints */
|
||||
struct sim_ep_s eps[SIM_USB_EPNUM];
|
||||
spinlock_t lock; /* Spinlock */
|
||||
struct wdog_s wdog; /* Watchdog for event loop */
|
||||
struct work_s work; /* Work for event loop */
|
||||
};
|
||||
|
||||
struct sim_req_s
|
||||
@@ -1045,7 +1045,7 @@ static void sim_usbdev_devinit(struct sim_usbdev_s *dev)
|
||||
dev->epavail = SIM_EPSET_NOEP0;
|
||||
}
|
||||
|
||||
static void sim_usbdev_interrupt(wdparm_t arg)
|
||||
static void sim_usbdev_work(void *arg)
|
||||
{
|
||||
struct sim_usbdev_s *priv = (struct sim_usbdev_s *)arg;
|
||||
struct sim_ep_s *privep;
|
||||
@@ -1080,7 +1080,8 @@ static void sim_usbdev_interrupt(wdparm_t arg)
|
||||
}
|
||||
}
|
||||
|
||||
wd_start_next(&priv->wdog, SIM_USB_PERIOD, sim_usbdev_interrupt, arg);
|
||||
work_queue_next(HPWORK, &priv->work, sim_usbdev_work, priv,
|
||||
SIM_USB_PERIOD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -1138,7 +1139,7 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
|
||||
#endif
|
||||
}
|
||||
|
||||
wd_start(&priv->wdog, 0, sim_usbdev_interrupt, (wdparm_t)priv);
|
||||
work_queue(HPWORK, &priv->work, sim_usbdev_work, priv, SIM_USB_PERIOD);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbhost.h>
|
||||
#include <nuttx/usb/usbhost_trace.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
|
||||
#include "sim_usbhost.h"
|
||||
#include "sim_internal.h"
|
||||
@@ -111,7 +112,7 @@ struct sim_usbhost_s
|
||||
sem_t pscsem; /* Semaphore to wait for port status change events */
|
||||
|
||||
struct usbhost_devaddr_s devgen; /* Address generation data */
|
||||
struct wdog_s wdog;
|
||||
struct work_s work;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -712,7 +713,7 @@ static void sim_usbhost_rqcomplete(struct sim_usbhost_s *drvr)
|
||||
* Name: sim_usbhost_interrupt
|
||||
****************************************************************************/
|
||||
|
||||
static void sim_usbhost_interrupt(wdparm_t arg)
|
||||
static void sim_usbhost_work(void *arg)
|
||||
{
|
||||
struct sim_usbhost_s *priv = (struct sim_usbhost_s *)arg;
|
||||
struct usbhost_hubport_s *hport;
|
||||
@@ -778,7 +779,8 @@ static void sim_usbhost_interrupt(wdparm_t arg)
|
||||
}
|
||||
}
|
||||
|
||||
wd_start_next(&priv->wdog, SIM_USBHOST_PERIOD, sim_usbhost_interrupt, arg);
|
||||
work_queue_next(HPWORK, &priv->work, sim_usbhost_work, priv,
|
||||
SIM_USBHOST_PERIOD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -851,7 +853,7 @@ int sim_usbhost_initialize(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
wd_start(&priv->wdog, 0, sim_usbhost_interrupt, (wdparm_t)priv);
|
||||
work_queue(HPWORK, &priv->work, sim_usbhost_work, priv, SIM_USBHOST_PERIOD);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user