mirror of https://github.com/RT-Thread/rt-thread
[mutex] mutex may suspend a thread already suspended & fix ceilingprio (#7046)
* [fix] reinsert should not suspend twice * [mutex] fix prioceiling * [mutex] fix prioceiling
This commit is contained in:
parent
fcc01a617d
commit
64cd64baf9
27
src/ipc.c
27
src/ipc.c
|
@ -126,6 +126,8 @@ rt_inline rt_err_t _ipc_list_suspend(rt_list_t *list,
|
||||||
struct rt_thread *thread,
|
struct rt_thread *thread,
|
||||||
rt_uint8_t flag,
|
rt_uint8_t flag,
|
||||||
int suspend_flag)
|
int suspend_flag)
|
||||||
|
{
|
||||||
|
if ((thread->stat & RT_THREAD_SUSPEND_MASK) != RT_THREAD_SUSPEND_MASK)
|
||||||
{
|
{
|
||||||
rt_err_t ret = rt_thread_suspend_with_flag(thread, suspend_flag);
|
rt_err_t ret = rt_thread_suspend_with_flag(thread, suspend_flag);
|
||||||
|
|
||||||
|
@ -134,6 +136,7 @@ rt_inline rt_err_t _ipc_list_suspend(rt_list_t *list,
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (flag)
|
switch (flag)
|
||||||
{
|
{
|
||||||
|
@ -740,6 +743,7 @@ RTM_EXPORT(rt_sem_control);
|
||||||
#endif /* RT_USING_SEMAPHORE */
|
#endif /* RT_USING_SEMAPHORE */
|
||||||
|
|
||||||
#ifdef RT_USING_MUTEX
|
#ifdef RT_USING_MUTEX
|
||||||
|
/* iterate over each suspended thread to update highest priority in pending threads */
|
||||||
rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *mutex)
|
rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *mutex)
|
||||||
{
|
{
|
||||||
struct rt_thread *thread;
|
struct rt_thread *thread;
|
||||||
|
@ -757,6 +761,7 @@ rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *mutex)
|
||||||
return mutex->priority;
|
return mutex->priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get highest priority inside its taken object and its init priority */
|
||||||
rt_inline rt_uint8_t _thread_get_mutex_priority(struct rt_thread* thread)
|
rt_inline rt_uint8_t _thread_get_mutex_priority(struct rt_thread* thread)
|
||||||
{
|
{
|
||||||
rt_list_t *node = RT_NULL;
|
rt_list_t *node = RT_NULL;
|
||||||
|
@ -766,15 +771,20 @@ rt_inline rt_uint8_t _thread_get_mutex_priority(struct rt_thread* thread)
|
||||||
rt_list_for_each(node, &(thread->taken_object_list))
|
rt_list_for_each(node, &(thread->taken_object_list))
|
||||||
{
|
{
|
||||||
mutex = rt_list_entry(node, struct rt_mutex, taken_list);
|
mutex = rt_list_entry(node, struct rt_mutex, taken_list);
|
||||||
if (priority > mutex->priority)
|
rt_uint8_t mutex_prio = mutex->priority;
|
||||||
|
/* prio at least be priority ceiling */
|
||||||
|
mutex_prio = mutex_prio < mutex->ceiling_priority ? mutex_prio : mutex->ceiling_priority;
|
||||||
|
|
||||||
|
if (priority > mutex_prio)
|
||||||
{
|
{
|
||||||
priority = mutex->priority;
|
priority = mutex_prio;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update priority of target thread and the thread suspended it if any */
|
||||||
rt_inline void _thread_update_priority(struct rt_thread *thread, rt_uint8_t priority, int suspend_flag)
|
rt_inline void _thread_update_priority(struct rt_thread *thread, rt_uint8_t priority, int suspend_flag)
|
||||||
{
|
{
|
||||||
rt_err_t ret;
|
rt_err_t ret;
|
||||||
|
@ -987,8 +997,17 @@ rt_uint8_t rt_mutex_setprioceiling(rt_mutex_t mutex, rt_uint8_t priority)
|
||||||
|
|
||||||
if ((mutex) && (priority < RT_THREAD_PRIORITY_MAX))
|
if ((mutex) && (priority < RT_THREAD_PRIORITY_MAX))
|
||||||
{
|
{
|
||||||
|
/* critical section here if multiple updates to one mutex happen */
|
||||||
|
rt_ubase_t level = rt_hw_interrupt_disable();
|
||||||
ret_priority = mutex->ceiling_priority;
|
ret_priority = mutex->ceiling_priority;
|
||||||
mutex->ceiling_priority = priority;
|
mutex->ceiling_priority = priority;
|
||||||
|
if (mutex->owner)
|
||||||
|
{
|
||||||
|
rt_uint8_t priority = _thread_get_mutex_priority(mutex->owner);
|
||||||
|
if (priority != mutex->owner->current_priority)
|
||||||
|
_thread_update_priority(mutex->owner, priority, RT_UNINTERRUPTIBLE);
|
||||||
|
}
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1197,12 +1216,10 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend
|
||||||
if (mutex->ceiling_priority < mutex->owner->current_priority)
|
if (mutex->ceiling_priority < mutex->owner->current_priority)
|
||||||
_thread_update_priority(mutex->owner, mutex->ceiling_priority, suspend_flag);
|
_thread_update_priority(mutex->owner, mutex->ceiling_priority, suspend_flag);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* insert mutex to thread's taken object list */
|
/* insert mutex to thread's taken object list */
|
||||||
rt_list_insert_after(&thread->taken_object_list, &mutex->taken_list);
|
rt_list_insert_after(&thread->taken_object_list, &mutex->taken_list);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* no waiting, return with timeout */
|
/* no waiting, return with timeout */
|
||||||
|
|
Loading…
Reference in New Issue