diff --git a/src/thread.c b/src/thread.c index 481dfebeef2..15e4ee45e85 100644 --- a/src/thread.c +++ b/src/thread.c @@ -885,26 +885,27 @@ RTM_EXPORT(rt_thread_control); #include #endif -static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag) +/* Convert suspend_flag to corresponding thread suspend state value */ +static rt_uint8_t _thread_get_suspend_state(int suspend_flag) { - rt_uint8_t stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE; - - RT_ASSERT(thread != RT_NULL); switch (suspend_flag) { case RT_INTERRUPTIBLE: - stat = RT_THREAD_SUSPEND_INTERRUPTIBLE; - break; + return RT_THREAD_SUSPEND_INTERRUPTIBLE; case RT_KILLABLE: - stat = RT_THREAD_SUSPEND_KILLABLE; - break; + return RT_THREAD_SUSPEND_KILLABLE; case RT_UNINTERRUPTIBLE: - stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE; - break; default: - RT_ASSERT(0); - break; + return RT_THREAD_SUSPEND_UNINTERRUPTIBLE; } +} + +static void _thread_set_suspend_state(struct rt_thread *thread, int suspend_flag) +{ + rt_uint8_t stat; + + RT_ASSERT(thread != RT_NULL); + stat = _thread_get_suspend_state(suspend_flag); RT_SCHED_CTX(thread).stat = stat | (RT_SCHED_CTX(thread).stat & ~RT_THREAD_STAT_MASK); } @@ -943,20 +944,31 @@ rt_err_t rt_thread_suspend_to_list(rt_thread_t thread, rt_list_t *susp_list, int RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); - LOG_D("thread suspend: %s", thread->parent.name); + LOG_D("thread suspend: %s", thread->parent.name); rt_sched_lock(&slvl); stat = rt_sched_thread_get_stat(thread); - if (stat == RT_THREAD_SUSPEND) + if (stat & RT_THREAD_SUSPEND_MASK) { + if (RT_SCHED_CTX(thread).sched_flag_ttmr_set == 1) + { + /* The new suspend operation will halt the tick timer. */ + LOG_D("Thread [%s]'s timer has been halted.\n", thread->parent.name); + rt_sched_thread_timer_stop(thread); + } + /* Upgrade suspend state if new state is stricter */ + if (stat < _thread_get_suspend_state(suspend_flag)) + { + _thread_set_suspend_state(thread, suspend_flag); + } rt_sched_unlock(slvl); - /* Already suspended, just set status to success. */ + /* Already suspended, just set the status to success. */ return RT_EOK; } else if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING)) { - LOG_D("thread suspend: thread disorder, 0x%2x", RT_SCHED_CTX(thread).stat); + LOG_W("thread suspend: thread disorder, 0x%02x", RT_SCHED_CTX(thread).stat); rt_sched_unlock(slvl); return -RT_ERROR; }