From 48c78ba4e093269c547510c30ddf778d7198937e Mon Sep 17 00:00:00 2001 From: xqyjlj Date: Wed, 27 Dec 2023 20:36:39 +0800 Subject: 🐞 fix: fix rt_thread_delay, assert, deadlock (#8366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/thread.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'src/thread.c') diff --git a/src/thread.c b/src/thread.c index 7f0d123f32..9f2a89ee4f 100644 --- a/src/thread.c +++ b/src/thread.c @@ -34,6 +34,7 @@ * 2022-10-15 Bernard add nested mutex feature * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable * 2023-12-10 xqyjlj fix thread_exit/detach/delete + * fix rt_thread_delay */ #include @@ -642,7 +643,7 @@ RTM_EXPORT(rt_thread_yield); */ rt_err_t rt_thread_sleep(rt_tick_t tick) { - rt_base_t level, level_local; + rt_base_t level; struct rt_thread *thread; int err; @@ -660,10 +661,11 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) RT_DEBUG_SCHEDULER_AVAILABLE(RT_TRUE); /* reset thread error */ thread->error = RT_EOK; - level_local = rt_hw_local_irq_disable(); + level = rt_hw_local_irq_disable(); /* suspend thread */ + rt_enter_critical(); err = rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE); - level = rt_spin_lock_irqsave(&(thread->spinlock)); + rt_spin_lock(&(thread->spinlock)); /* reset the timeout of thread timer and start it */ if (err == RT_EOK) { @@ -671,8 +673,10 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) rt_timer_start(&(thread->thread_timer)); /* enable interrupt */ - rt_spin_unlock_irqrestore(&(thread->spinlock), level); - rt_hw_local_irq_enable(level_local); + rt_hw_local_irq_enable(level); + rt_spin_unlock(&(thread->spinlock)); + rt_exit_critical(); + thread->error = -RT_EINTR; rt_schedule(); @@ -683,8 +687,9 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) } else { - rt_spin_unlock_irqrestore(&(thread->spinlock), level); - rt_hw_local_irq_enable(level_local); + rt_hw_local_irq_enable(level); + rt_spin_unlock(&(thread->spinlock)); + rt_exit_critical(); } return err; @@ -727,12 +732,12 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); - /* disable interrupt */ - level = rt_spin_lock_irqsave(&(thread->spinlock)); - /* reset thread error */ thread->error = RT_EOK; + /* disable interrupt */ + level = rt_hw_local_irq_disable(); + cur_tick = rt_tick_get(); if (cur_tick - *tick < inc_tick) { @@ -740,14 +745,20 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) *tick += inc_tick; left_tick = *tick - cur_tick; - rt_spin_unlock_irqrestore(&(thread->spinlock), level); + + rt_enter_critical(); /* suspend thread */ rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE); - level = rt_spin_lock_irqsave(&(thread->spinlock)); + + rt_spin_lock(&(thread->spinlock)); + /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &left_tick); rt_timer_start(&(thread->thread_timer)); - rt_spin_unlock_irqrestore(&(thread->spinlock), level); + + rt_hw_local_irq_enable(level); + rt_spin_unlock(&(thread->spinlock)); + rt_exit_critical(); rt_schedule(); @@ -760,7 +771,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) else { *tick = cur_tick; - rt_spin_unlock_irqrestore(&(thread->spinlock), level); + rt_hw_local_irq_enable(level); } return thread->error; -- cgit v1.3.1