sched/wdog: fix switch_context caused error in wd_start()

Thead A:                     Thread B:
wd_start(wdogX)
wd_cancel
nxsched_cancel_timer  -->    wd_start(wdogX)
                             wd_cancel
                             add wdogX to g_wdactivelist
                      <--
add wdogX to g_wdactivelist

then, you will find wdogX add twice.

Change-Id: Icbf3b2badff20908e115c9134e2400cdcb32b1e0
Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd
2021-08-25 13:52:20 +08:00
committed by Masayuki Ishikawa
parent 1385ea7673
commit 9116ed9247
3 changed files with 14 additions and 10 deletions
+1 -1
View File
@@ -344,7 +344,7 @@ static unsigned int nxsched_timer_process(unsigned int ticks,
/* Process watchdogs */ /* Process watchdogs */
tmp = wd_timer(ticks); tmp = wd_timer(ticks, noswitches);
if (tmp > 0) if (tmp > 0)
{ {
cmptime = tmp; cmptime = tmp;
+10 -7
View File
@@ -351,6 +351,7 @@ int wd_start(FAR struct wdog_s *wdog, int32_t delay,
* in the interval that just expired is provided. Otherwise, * in the interval that just expired is provided. Otherwise,
* this function is called on each timer interrupt and a value of one * this function is called on each timer interrupt and a value of one
* is implicit. * is implicit.
* noswitches - True: Can't do context switches now.
* *
* Returned Value: * Returned Value:
* If CONFIG_SCHED_TICKLESS is defined then the number of ticks for the * If CONFIG_SCHED_TICKLESS is defined then the number of ticks for the
@@ -363,7 +364,7 @@ int wd_start(FAR struct wdog_s *wdog, int32_t delay,
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS #ifdef CONFIG_SCHED_TICKLESS
unsigned int wd_timer(int ticks) unsigned int wd_timer(int ticks, bool noswitches)
{ {
FAR struct wdog_s *wdog; FAR struct wdog_s *wdog;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
@@ -387,12 +388,9 @@ unsigned int wd_timer(int ticks)
/* Check if there are any active watchdogs to process */ /* Check if there are any active watchdogs to process */
while (g_wdactivelist.head != NULL && ticks > 0)
{
/* Get the watchdog at the head of the list */
wdog = (FAR struct wdog_s *)g_wdactivelist.head; wdog = (FAR struct wdog_s *)g_wdactivelist.head;
while (wdog != NULL && ticks > 0)
{
#ifndef CONFIG_SCHED_TICKLESS_ALARM #ifndef CONFIG_SCHED_TICKLESS_ALARM
/* There is logic to handle the case where ticks is greater than /* There is logic to handle the case where ticks is greater than
* the watchdog lag, but if the scheduling is working properly * the watchdog lag, but if the scheduling is working properly
@@ -411,8 +409,13 @@ unsigned int wd_timer(int ticks)
ticks -= decr; ticks -= decr;
g_wdtickbase += decr; g_wdtickbase += decr;
wdog = wdog->next;
}
/* Check if the watchdog at the head of the list is ready to run */ /* Check if the watchdog at the head of the list is ready to run */
if (!noswitches)
{
wd_expiration(); wd_expiration();
} }
@@ -423,7 +426,7 @@ unsigned int wd_timer(int ticks)
/* Return the delay for the next watchdog to expire */ /* Return the delay for the next watchdog to expire */
ret = g_wdactivelist.head ? ret = g_wdactivelist.head ?
((FAR struct wdog_s *)g_wdactivelist.head)->lag : 0; MAX(((FAR struct wdog_s *)g_wdactivelist.head)->lag, 1) : 0;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
leave_critical_section(flags); leave_critical_section(flags);
+2 -1
View File
@@ -121,6 +121,7 @@ void weak_function wd_initialize(void);
* in the interval that just expired is provided. Otherwise, * in the interval that just expired is provided. Otherwise,
* this function is called on each timer interrupt and a value of one * this function is called on each timer interrupt and a value of one
* is implicit. * is implicit.
* noswitches - True: Can't do context switches now.
* *
* Returned Value: * Returned Value:
* If CONFIG_SCHED_TICKLESS is defined then the number of ticks for the * If CONFIG_SCHED_TICKLESS is defined then the number of ticks for the
@@ -133,7 +134,7 @@ void weak_function wd_initialize(void);
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SCHED_TICKLESS #ifdef CONFIG_SCHED_TICKLESS
unsigned int wd_timer(int ticks); unsigned int wd_timer(int ticks, bool noswitches);
#else #else
void wd_timer(void); void wd_timer(void);
#endif #endif