From 6da278a639bcac78cf46699d77ebd2bbe181453b Mon Sep 17 00:00:00 2001 From: hujun5 Date: Wed, 11 Dec 2024 13:37:46 +0800 Subject: [PATCH] sched/wdog: use small lock to protect g_wdactivelist reason: We would like to replace the critical section with a small lock. Signed-off-by: hujun5 --- drivers/note/note_driver.c | 4 ++++ sched/wdog/wd_cancel.c | 12 +++++++----- sched/wdog/wd_start.c | 27 +++++++++++++++++++-------- sched/wdog/wdog.h | 2 ++ 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index 1a8da44333135..25d745e9e44fe 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -1393,10 +1393,12 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) void sched_note_wdog(uint8_t event, FAR void *handler, FAR const void *arg) { FAR struct note_driver_s **driver; + irqstate_t flags; struct note_wdog_s note; bool formatted = false; FAR struct tcb_s *tcb = this_task(); + flags = enter_critical_section_wo_note(); for (driver = g_note_drivers; *driver; driver++) { if (note_wdog(*driver, event, handler, arg)) @@ -1421,6 +1423,8 @@ void sched_note_wdog(uint8_t event, FAR void *handler, FAR const void *arg) note_add(*driver, ¬e, sizeof(note)); } + + leave_critical_section_wo_note(flags); } #endif diff --git a/sched/wdog/wd_cancel.c b/sched/wdog/wd_cancel.c index 3cfc960e8f0c7..a82d4abac167d 100644 --- a/sched/wdog/wd_cancel.c +++ b/sched/wdog/wd_cancel.c @@ -38,6 +38,8 @@ #include "sched/sched.h" #include "wdog/wdog.h" +spinlock_t g_wdog_spinlock = SP_UNLOCKED; + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -60,15 +62,10 @@ int wd_cancel(FAR struct wdog_s *wdog) { - irqstate_t flags; int ret; - flags = enter_critical_section(); - ret = wd_cancel_irq(wdog); - leave_critical_section(flags); - return ret; } @@ -91,12 +88,16 @@ int wd_cancel(FAR struct wdog_s *wdog) int wd_cancel_irq(FAR struct wdog_s *wdog) { + irqstate_t flags; bool head; + flags = spin_lock_irqsave(&g_wdog_spinlock); + /* Make sure that the watchdog is valid and still active. */ if (wdog == NULL || !WDOG_ISACTIVE(wdog)) { + spin_unlock_irqrestore(&g_wdog_spinlock, flags); return -EINVAL; } @@ -116,6 +117,7 @@ int wd_cancel_irq(FAR struct wdog_s *wdog) /* Mark the watchdog inactive */ wdog->func = NULL; + spin_unlock_irqrestore(&g_wdog_spinlock, flags); if (head) { diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c index 739cec16a2111..7f1a12b1f2f18 100644 --- a/sched/wdog/wd_start.c +++ b/sched/wdog/wd_start.c @@ -112,10 +112,11 @@ static unsigned int g_wdtimernested; static inline_function void wd_expiration(clock_t ticks) { FAR struct wdog_s *wdog; + wdparm_t arg; irqstate_t flags; wdentry_t func; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_wdog_spinlock); #ifdef CONFIG_SCHED_TICKLESS /* Increment the nested watchdog timer count to handle cases where wd_start @@ -147,12 +148,17 @@ static inline_function void wd_expiration(clock_t ticks) /* Indicate that the watchdog is no longer active. */ func = wdog->func; + arg = wdog->arg; wdog->func = NULL; /* Execute the watchdog function */ up_setpicbase(wdog->picbase); - CALL_FUNC(func, wdog->arg); + spin_unlock_irqrestore(&g_wdog_spinlock, flags); + + CALL_FUNC(func, arg); + + flags = spin_lock_irqsave(&g_wdog_spinlock); } #ifdef CONFIG_SCHED_TICKLESS @@ -161,7 +167,7 @@ static inline_function void wd_expiration(clock_t ticks) g_wdtimernested--; #endif - leave_critical_section(flags); + spin_unlock_irqrestore(&g_wdog_spinlock, flags); } /**************************************************************************** @@ -293,7 +299,7 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks, * the critical section is established. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_wdog_spinlock); #ifdef CONFIG_SCHED_TICKLESS /* We need to reassess timer if the watchdog list head has changed. */ @@ -314,8 +320,13 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks, * then this will pick that new delay. */ + spin_unlock_irqrestore(&g_wdog_spinlock, flags); nxsched_reassess_timer(); } + else + { + spin_unlock_irqrestore(&g_wdog_spinlock, flags); + } #else UNUSED(reassess); @@ -328,8 +339,8 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks, } wd_insert(wdog, ticks, wdentry, arg); + spin_unlock_irqrestore(&g_wdog_spinlock, flags); #endif - leave_critical_section(flags); sched_note_wdog(NOTE_WDOG_START, wdentry, (FAR void *)(uintptr_t)ticks); return OK; @@ -425,13 +436,13 @@ clock_t wd_timer(clock_t ticks, bool noswitches) wd_expiration(ticks); } - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_wdog_spinlock); /* Return the delay for the next watchdog to expire */ if (list_is_empty(&g_wdactivelist)) { - leave_critical_section(flags); + spin_unlock_irqrestore(&g_wdog_spinlock, flags); return 0; } @@ -442,7 +453,7 @@ clock_t wd_timer(clock_t ticks, bool noswitches) wdog = list_first_entry(&g_wdactivelist, struct wdog_s, node); ret = wdog->expired - ticks; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_wdog_spinlock, flags); /* Return the delay for the next watchdog to expire */ diff --git a/sched/wdog/wdog.h b/sched/wdog/wdog.h index f7f4ca577e7d0..812fab463339c 100644 --- a/sched/wdog/wdog.h +++ b/sched/wdog/wdog.h @@ -37,6 +37,7 @@ #include #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -64,6 +65,7 @@ extern "C" */ extern struct list_node g_wdactivelist; +extern spinlock_t g_wdog_spinlock; /**************************************************************************** * Public Function Prototypes