From 4efa8efd90fbc425fd1e0d9596e314719b78fe2e Mon Sep 17 00:00:00 2001 From: liyansheng Date: Wed, 23 Nov 2022 22:52:27 +0100 Subject: [PATCH 1/3] add nested/prioceiling mutex feature(merge from rt-thread master branch) --- include/rtdef.h | 13 +- include/rtthread.h | 4 + src/ipc.c | 433 +++++++++++++++++++++++++++++++++++---------- src/thread.c | 32 +++- 4 files changed, 382 insertions(+), 100 deletions(-) diff --git a/include/rtdef.h b/include/rtdef.h index 060e5c6e45..14f773bbe3 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -698,6 +698,12 @@ struct rt_thread #endif rt_uint32_t number_mask; +#ifdef RT_USING_MUTEX + /* object for IPC */ + rt_list_t taken_object_list; + rt_object_t pending_object; +#endif + #if defined(RT_USING_EVENT) /* thread event */ rt_uint32_t event_set; @@ -819,12 +825,13 @@ struct rt_mutex { struct rt_ipc_object parent; /**< inherit from ipc_object */ - rt_uint16_t value; /**< value of mutex */ - - rt_uint8_t original_priority; /**< priority of last thread hold the mutex */ + rt_uint8_t ceiling_priority; /**< the priority ceiling of mutexe */ + rt_uint8_t priority; /**< the maximal priority for pending thread */ rt_uint8_t hold; /**< numbers of thread hold the mutex */ + rt_uint8_t reserved; /**< reserved field */ struct rt_thread *owner; /**< current owner of mutex */ + rt_list_t taken_list; /**< the object list taken by thread */ }; typedef struct rt_mutex *rt_mutex_t; #endif diff --git a/include/rtthread.h b/include/rtthread.h index 8ab88f1700..69e44dab82 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -336,6 +336,10 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex); rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag); rt_err_t rt_mutex_delete(rt_mutex_t mutex); +void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread); +rt_uint8_t rt_mutex_setprioceiling(rt_mutex_t mutex, rt_uint8_t priority); +rt_uint8_t rt_mutex_getprioceiling(rt_mutex_t mutex); + rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time); rt_err_t rt_mutex_take_interruptible(rt_mutex_t mutex, rt_int32_t time); rt_err_t rt_mutex_take_killable(rt_mutex_t mutex, rt_int32_t time); diff --git a/src/ipc.c b/src/ipc.c index debe74c37e..adc35431b3 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -565,6 +565,83 @@ RTM_EXPORT(rt_sem_control); #endif /* end of RT_USING_SEMAPHORE */ #ifdef RT_USING_MUTEX +rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *mutex) +{ + struct rt_thread *thread; + + if (!rt_list_isempty(&mutex->parent.suspend_thread)) + { + thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist); + mutex->priority = thread->current_priority; + } + else + { + mutex->priority = 0xff; + } + + return mutex->priority; +} + +rt_inline rt_uint8_t _thread_get_mutex_priority(struct rt_thread* thread) +{ + rt_list_t *node = RT_NULL; + struct rt_mutex *mutex = RT_NULL; + rt_uint8_t priority = thread->init_priority; + + rt_list_for_each(node, &(thread->taken_object_list)) + { + mutex = rt_list_entry(node, struct rt_mutex, taken_list); + if (priority > mutex->priority) + { + priority = mutex->priority; + } + } + + return priority; +} + +rt_inline void _thread_update_priority(struct rt_thread *thread, rt_uint8_t priority, int suspend_flag) +{ + RT_DEBUG_LOG(RT_DEBUG_IPC, + ("thread:%s priority -> %d\n", thread->name, priority)); + + /* change priority of the thread */ + rt_thread_control(thread, + RT_THREAD_CTRL_CHANGE_PRIORITY, + &priority); + + if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND) + { + /* whether change the priority of taken mutex */ + struct rt_object* pending_obj = thread->pending_object; + + if (pending_obj && rt_object_get_type(pending_obj) == RT_Object_Class_Mutex) + { + rt_uint8_t mutex_priority; + struct rt_mutex* pending_mutex = (struct rt_mutex *)pending_obj; + + /* re-insert thread to suspended thread list */ + rt_list_remove(&(thread->tlist)); + rt_ipc_list_suspend(&(pending_mutex->parent.suspend_thread), + thread, + pending_mutex->parent.parent.flag,suspend_flag); + + /* update priority */ + _mutex_update_priority(pending_mutex); + /* change the priority of mutex owner thread */ + RT_DEBUG_LOG(RT_DEBUG_IPC, + ("mutex: %s priority -> %d\n", pending_mutex->parent.parent.name, + pending_mutex->priority)); + + mutex_priority = _thread_get_mutex_priority(pending_mutex->owner); + if (mutex_priority != pending_mutex->owner->current_priority) + { + _thread_update_priority(pending_mutex->owner, mutex_priority, suspend_flag); + } + } + } +} + /** * This function will initialize a mutex and put it under control of resource * management. @@ -575,7 +652,7 @@ RTM_EXPORT(rt_sem_control); * * @return the operation status, RT_EOK on successful */ -rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) +rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag RT_UNUSED) { /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -586,13 +663,14 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) /* initialize ipc object */ rt_ipc_object_init(&(mutex->parent)); - mutex->value = 1; - mutex->owner = RT_NULL; - mutex->original_priority = 0xFF; - mutex->hold = 0; + mutex->owner = RT_NULL; + mutex->priority = 0xFF; + mutex->hold = 0; + mutex->ceiling_priority = 0xFF; + rt_list_init(&(mutex->taken_list)); - /* set flag */ - mutex->parent.parent.flag = flag; + /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ + mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return RT_EOK; } @@ -609,21 +687,124 @@ RTM_EXPORT(rt_mutex_init); */ rt_err_t rt_mutex_detach(rt_mutex_t mutex) { + rt_ubase_t level; + /* parameter check */ RT_ASSERT(mutex != RT_NULL); RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex); RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent)); + level = rt_hw_interrupt_disable(); /* wakeup all suspended threads */ rt_ipc_list_resume_all(&(mutex->parent.suspend_thread)); + /* remove mutex from thread's taken list */ + rt_list_remove(&mutex->taken_list); + rt_hw_interrupt_enable(level); - /* detach semaphore object */ + /* detach mutex object */ rt_object_detach(&(mutex->parent.parent)); return RT_EOK; } RTM_EXPORT(rt_mutex_detach); +/* drop a thread from the suspend list of mutex */ + +/** + * @brief drop a thread from the suspend list of mutex + * + * @param mutex is a pointer to a mutex object. + * @param thread is the thread should be dropped from mutex. + */ +void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread) +{ + rt_uint8_t priority; + rt_bool_t need_update = RT_FALSE; + + rt_list_remove(&(thread->tlist)); + + /* should change the priority of mutex owner thread */ + if (mutex->owner->current_priority == thread->current_priority) + need_update = RT_TRUE; + + /* update the priority of mutex */ + if (!rt_list_isempty(&mutex->parent.suspend_thread)) + { + /* more thread suspended in the list */ + struct rt_thread *th; + + th = rt_list_entry(mutex->parent.suspend_thread.next, + struct rt_thread, + tlist); + /* update the priority of mutex */ + mutex->priority = th->current_priority; + } + else + { + /* set mutex priority to maximal priority */ + mutex->priority = 0xff; + } + + /* try to change the priority of mutex owner thread */ + if (need_update) + { + /* get the maximal priority of mutex in thread */ + priority = _thread_get_mutex_priority(mutex->owner); + if (priority != mutex->owner->current_priority) + { + _thread_update_priority(mutex->owner, priority,RT_UNINTERRUPTIBLE); + } + } +} + + +/** + * @brief set the prioceiling attribute of the mutex. + * + * @param mutex is a pointer to a mutex object. + * @param priority is the priority should be set to mutex. + * + * @return return the old priority ceiling + */ +rt_uint8_t rt_mutex_setprioceiling(rt_mutex_t mutex, rt_uint8_t priority) +{ + rt_uint8_t ret_priority = 0xFF; + + if ((mutex) && (priority < RT_THREAD_PRIORITY_MAX)) + { + ret_priority = mutex->ceiling_priority; + mutex->ceiling_priority = priority; + } + else + { + rt_set_errno(-RT_EINVAL); + } + + return ret_priority; +} +RTM_EXPORT(rt_mutex_setprioceiling); + + +/** + * @brief set the prioceiling attribute of the mutex. + * + * @param mutex is a pointer to a mutex object. + * + * @return return the current priority ceiling of the mutex. + */ +rt_uint8_t rt_mutex_getprioceiling(rt_mutex_t mutex) +{ + rt_uint8_t prio = 0xFF; + + if (mutex) + { + prio = mutex->ceiling_priority; + } + + return prio; +} +RTM_EXPORT(rt_mutex_getprioceiling); + #ifdef RT_USING_HEAP /** * This function will create a mutex from system resource @@ -635,7 +816,7 @@ RTM_EXPORT(rt_mutex_detach); * * @see rt_mutex_init */ -rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) +rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag RT_UNUSED) { struct rt_mutex *mutex; @@ -649,13 +830,14 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) /* initialize ipc object */ rt_ipc_object_init(&(mutex->parent)); - mutex->value = 1; - mutex->owner = RT_NULL; - mutex->original_priority = 0xFF; - mutex->hold = 0; + mutex->owner = RT_NULL; + mutex->priority = 0xFF; + mutex->hold = 0; + mutex->ceiling_priority = 0xFF; + rt_list_init(&(mutex->taken_list)); - /* set flag */ - mutex->parent.parent.flag = flag; + /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ + mutex->parent.parent.flag = RT_IPC_FLAG_PRIO; return mutex; } @@ -672,15 +854,21 @@ RTM_EXPORT(rt_mutex_create); */ rt_err_t rt_mutex_delete(rt_mutex_t mutex) { - RT_DEBUG_NOT_IN_INTERRUPT; + rt_ubase_t level; /* parameter check */ RT_ASSERT(mutex != RT_NULL); RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex); RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent) == RT_FALSE); + RT_DEBUG_NOT_IN_INTERRUPT; + + level = rt_hw_interrupt_disable(); /* wakeup all suspended threads */ rt_ipc_list_resume_all(&(mutex->parent.suspend_thread)); + /* remove mutex from thread's taken list */ + rt_list_remove(&mutex->taken_list); + rt_hw_interrupt_enable(level); /* delete mutex object */ rt_object_delete(&(mutex->parent.parent)); @@ -699,14 +887,15 @@ RTM_EXPORT(rt_mutex_delete); * * @return the error code */ -static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t time, int suspend_flag) +static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend_flag) { - register rt_base_t temp; + rt_base_t level; struct rt_thread *thread; rt_err_t ret; /* this function must not be used in interrupt even if time = 0 */ - RT_DEBUG_IN_THREAD_CONTEXT; + /* current context checking */ + RT_DEBUG_NOT_IN_INTERRUPT; /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -716,16 +905,16 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t time, int suspend_fl thread = rt_thread_self(); /* disable interrupt */ - temp = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(mutex->parent.parent))); RT_DEBUG_LOG(RT_DEBUG_IPC, - ("mutex_take: current thread %s, mutex value: %d, hold: %d\n", - thread->name, mutex->value, mutex->hold)); + ("mutex_take: current thread %s, hold: %d\n", + thread->name, mutex->hold)); /* reset thread error */ - thread->error = -RT_EINTR; + thread->error = RT_EOK; if (mutex->owner == thread) { @@ -736,61 +925,53 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t time, int suspend_fl } else { - rt_hw_interrupt_enable(temp); /* enable interrupt */ + rt_hw_interrupt_enable(level); /* enable interrupt */ return -RT_EFULL; /* value overflowed */ } } else { - /* The value of mutex is 1 in initial status. Therefore, if the - * value is great than 0, it indicates the mutex is avaible. - */ - if (mutex->value > 0) + /* whether the mutex has owner thread. */ + if (mutex->owner == RT_NULL) { - /* mutex is available */ - mutex->value --; - /* set mutex owner and original priority */ mutex->owner = thread; - mutex->original_priority = thread->current_priority; - if(mutex->hold < RT_MUTEX_HOLD_MAX) + mutex->priority = 0xff; + mutex->hold = 1; + + if (mutex->ceiling_priority != 0xFF) { - mutex->hold ++; + /* set the priority of thread to the ceiling priority */ + if (mutex->ceiling_priority < mutex->owner->current_priority) + _thread_update_priority(mutex->owner, mutex->ceiling_priority, suspend_flag); } else { - rt_hw_interrupt_enable(temp); /* enable interrupt */ - return -RT_EFULL; /* value overflowed */ + /* insert mutex to thread's taken object list */ + rt_list_insert_after(&thread->taken_object_list, &mutex->taken_list); } } else { /* no waiting, return with timeout */ - if (time == 0) + if (timeout == 0) { /* set error as timeout */ thread->error = -RT_ETIMEOUT; /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); return -RT_ETIMEOUT; } else { + rt_uint8_t priority = thread->current_priority; + /* mutex is unavailable, push to suspend list */ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_take: suspend thread: %s\n", thread->name)); - /* change the owner thread priority of mutex */ - if (thread->current_priority < mutex->owner->current_priority) - { - /* change the owner thread priority */ - rt_thread_control(mutex->owner, - RT_THREAD_CTRL_CHANGE_PRIORITY, - &thread->current_priority); - } - /* suspend current thread */ ret = rt_ipc_list_suspend(&(mutex->parent.suspend_thread), thread, @@ -798,12 +979,24 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t time, int suspend_fl suspend_flag); if (ret != RT_EOK) { - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); return ret; } + /* set pending object in thread to this mutex */ + thread->pending_object = &(mutex->parent.parent); + + /* update the priority level of mutex */ + if (priority < mutex->priority) + { + mutex->priority = priority; + if (mutex->priority < mutex->owner->current_priority) + { + _thread_update_priority(mutex->owner, priority, suspend_flag); + } + } /* has waiting time, start thread timer */ - if (time > 0) + if (timeout > 0) { RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_take: start the timer of thread:%s\n", @@ -812,33 +1005,74 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t time, int suspend_fl /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, - &time); + &timeout); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); /* do schedule */ rt_schedule(); - if (thread->error != RT_EOK) + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + if (thread->error == RT_EOK) { - /* return error */ - return thread->error; + /* get mutex successfully */ } else { - /* the mutex is taken successfully. */ - /* disable interrupt */ - temp = rt_hw_interrupt_disable(); + /* the mutex has not been taken and thread has detach from the pending list. */ + + rt_bool_t need_update = RT_FALSE; + + /* should change the priority of mutex owner thread */ + if (mutex->owner->current_priority == thread->current_priority) + need_update = RT_TRUE; + + /* update the priority of mutex */ + if (!rt_list_isempty(&mutex->parent.suspend_thread)) + { + /* more thread suspended in the list */ + struct rt_thread *th; + + th = rt_list_entry(mutex->parent.suspend_thread.next, + struct rt_thread, + tlist); + /* update the priority of mutex */ + mutex->priority = th->current_priority; + } + else + { + /* set mutex priority to maximal priority */ + mutex->priority = 0xff; + } + + /* try to change the priority of mutex owner thread */ + if (need_update) + { + /* get the maximal priority of mutex in thread */ + priority = _thread_get_mutex_priority(mutex->owner); + if (priority != mutex->owner->current_priority) + { + _thread_update_priority(mutex->owner, priority, suspend_flag); + } + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + /* return error */ + return thread->error; } } } } /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mutex->parent.parent))); @@ -873,7 +1107,7 @@ RTM_EXPORT(rt_mutex_take_killable); */ rt_err_t rt_mutex_release(rt_mutex_t mutex) { - register rt_base_t temp; + rt_base_t level; struct rt_thread *thread; rt_bool_t need_schedule; @@ -890,11 +1124,11 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) thread = rt_thread_self(); /* disable interrupt */ - temp = rt_hw_interrupt_disable(); + level = rt_hw_interrupt_disable(); RT_DEBUG_LOG(RT_DEBUG_IPC, - ("mutex_release:current thread %s, mutex value: %d, hold: %d\n", - thread->name, mutex->value, mutex->hold)); + ("mutex_release:current thread %s, hold: %d\n", + thread->name, mutex->hold)); RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mutex->parent.parent))); @@ -904,7 +1138,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) thread->error = -RT_ERROR; /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); return -RT_ERROR; } @@ -914,64 +1148,75 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) /* if no hold */ if (mutex->hold == 0) { - /* change the owner thread to original priority */ - if (mutex->original_priority != mutex->owner->current_priority) + /* remove mutex from thread's taken list */ + rt_list_remove(&mutex->taken_list); + + /* whether change the thread priority */ + if ((mutex->ceiling_priority != 0xFF) || (thread->current_priority == mutex->priority)) { - rt_thread_control(mutex->owner, + rt_uint8_t priority = 0xff; + + /* get the highest priority in the taken list of thread */ + priority = _thread_get_mutex_priority(thread); + + rt_thread_control(thread, RT_THREAD_CTRL_CHANGE_PRIORITY, - &(mutex->original_priority)); + &priority); + + need_schedule = RT_TRUE; } /* wakeup suspended thread */ if (!rt_list_isempty(&mutex->parent.suspend_thread)) { - /* get suspended thread */ - thread = rt_list_entry(mutex->parent.suspend_thread.next, + /* get the first suspended thread */ + struct rt_thread *next_thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist); RT_DEBUG_LOG(RT_DEBUG_IPC, ("mutex_release: resume thread: %s\n", - thread->name)); + next_thread->name)); - /* set new owner and priority */ - mutex->owner = thread; - mutex->original_priority = thread->current_priority; - if(mutex->hold < RT_MUTEX_HOLD_MAX) + /* remove the thread from the suspended list of mutex */ + rt_list_remove(&(next_thread->tlist)); + + /* set new owner and put mutex into taken list of thread */ + mutex->owner = next_thread; + mutex->hold = 1; + rt_list_insert_after(&next_thread->taken_object_list, &mutex->taken_list); + /* cleanup pending object */ + next_thread->pending_object = RT_NULL; + + /* resume thread */ + rt_thread_resume(next_thread); + + /* update mutex priority */ + if (!rt_list_isempty(&(mutex->parent.suspend_thread))) { - mutex->hold ++; + struct rt_thread *th; + + th = rt_list_entry(mutex->parent.suspend_thread.next, + struct rt_thread, + tlist); + mutex->priority = th->current_priority; } else { - rt_hw_interrupt_enable(temp); /* enable interrupt */ - return -RT_EFULL; /* value overflowed */ + mutex->priority = 0xff; } - /* resume thread */ - rt_ipc_list_resume(&(mutex->parent.suspend_thread)); - need_schedule = RT_TRUE; } else { - if(mutex->value < RT_MUTEX_VALUE_MAX) - { - /* increase value */ - mutex->value ++; - } - else - { - rt_hw_interrupt_enable(temp); /* enable interrupt */ - return -RT_EFULL; /* value overflowed */ - } - /* clear owner */ mutex->owner = RT_NULL; - mutex->original_priority = 0xff; + mutex->priority = 0xff; } } /* enable interrupt */ - rt_hw_interrupt_enable(temp); + rt_hw_interrupt_enable(level); /* perform a schedule */ if (need_schedule == RT_TRUE) diff --git a/src/thread.c b/src/thread.c index 35fb49f148..1bc28bbdba 100644 --- a/src/thread.c +++ b/src/thread.c @@ -153,6 +153,12 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread, thread->current_priority = priority; thread->number_mask = 0; + +#ifdef RT_USING_MUTEX + rt_list_init(&thread->taken_object_list); + thread->pending_object = RT_NULL; +#endif + #if RT_THREAD_PRIORITY_MAX > 32 thread->number = 0; thread->high_mask = 0; @@ -361,6 +367,16 @@ rt_err_t rt_thread_detach(rt_thread_t thread) /* change stat */ thread->stat = RT_THREAD_CLOSE; +#ifdef RT_USING_MUTEX + if ((thread->pending_object) && + (rt_object_get_type(thread->pending_object) == RT_Object_Class_Mutex)) + { + struct rt_mutex *mutex = (struct rt_mutex*)thread->pending_object; + rt_mutex_drop_thread(mutex, thread); + thread->pending_object = RT_NULL; + } +#endif + if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) && thread->cleanup == RT_NULL) { @@ -457,15 +473,25 @@ rt_err_t rt_thread_delete(rt_thread_t thread) rt_schedule_remove_thread(thread); } - /* release thread timer */ - rt_timer_detach(&(thread->thread_timer)); - /* disable interrupt */ lock = rt_hw_interrupt_disable(); + /* release thread timer */ + rt_timer_detach(&(thread->thread_timer)); + /* change stat */ thread->stat = RT_THREAD_CLOSE; +#ifdef RT_USING_MUTEX + if ((thread->pending_object) && + (rt_object_get_type(thread->pending_object) == RT_Object_Class_Mutex)) + { + struct rt_mutex *mutex = (struct rt_mutex*)thread->pending_object; + rt_mutex_drop_thread(mutex, thread); + thread->pending_object = RT_NULL; + } +#endif + /* insert to defunct thread list */ rt_thread_defunct_enqueue(thread); -- Gitee From 81ac3f70b974e1a63319815bf89c18035d2ee0f3 Mon Sep 17 00:00:00 2001 From: liyansheng Date: Wed, 23 Nov 2022 22:58:12 +0100 Subject: [PATCH 2/3] fix pthread_mutex_trylock suspended by locked mutex --- components/libc/time/clock_time.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/libc/time/clock_time.c b/components/libc/time/clock_time.c index 56563aa23f..3e3f2c6aa4 100644 --- a/components/libc/time/clock_time.c +++ b/components/libc/time/clock_time.c @@ -41,14 +41,13 @@ INIT_COMPONENT_EXPORT(clock_time_system_init); int clock_time_to_tick(const struct timespec *time) { - int tick; + int tick = 0; long nsecond, second; struct timespec tp; RT_ASSERT(time != RT_NULL); - tick = RT_WAITING_FOREVER; - if (time != RT_NULL) + if (time->tv_sec != 0 && time->tv_nsec != 0) { /* get current tp */ clock_gettime(CLOCK_REALTIME, &tp); @@ -546,4 +545,4 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, return RT_EOK; } -RTM_EXPORT(timer_settime); \ No newline at end of file +RTM_EXPORT(timer_settime); -- Gitee From e3806cddf9b9be9fee02c99fec09d29192190c77 Mon Sep 17 00:00:00 2001 From: liyansheng Date: Wed, 23 Nov 2022 23:00:25 +0100 Subject: [PATCH 3/3] 1.fix compile error after merge nested mutex feature. 2.fix incorrect return value of pthread_mutex_unlock when unlock an unlocked mutex --- components/lwp/lwp_pmutex.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/components/lwp/lwp_pmutex.c b/components/lwp/lwp_pmutex.c index efbfe4434f..6a450a9383 100644 --- a/components/lwp/lwp_pmutex.c +++ b/components/lwp/lwp_pmutex.c @@ -201,10 +201,10 @@ static int _pthread_mutex_init(void *umutex) } else { - pmutex->lock.kmutex->value = 1; - pmutex->lock.kmutex->owner = RT_NULL; - pmutex->lock.kmutex->original_priority = 0xFF; - pmutex->lock.kmutex->hold = 0; + pmutex->lock.kmutex->owner = RT_NULL; + pmutex->lock.kmutex->priority = 0xFF; + pmutex->lock.kmutex->hold = 0; + pmutex->lock.kmutex->ceiling_priority = 0xFF; } rt_hw_interrupt_enable(level); } @@ -315,8 +315,8 @@ static int _pthread_mutex_unlock(void *umutex) if (pmutex == RT_NULL) { rt_mutex_release(&_pmutex_lock); - rt_set_errno(EINVAL); - return -EINVAL; + rt_set_errno(EPERM); + return -EPERM;//unlock static mutex of unlock state } rt_mutex_release(&_pmutex_lock); @@ -324,7 +324,15 @@ static int _pthread_mutex_unlock(void *umutex) switch (pmutex->type) { case PMUTEX_NORMAL: - lock_ret = rt_sem_release(pmutex->lock.ksem); + if(pmutex->lock.ksem->value >=1) + { + rt_set_errno(EPERM); + return -EPERM;//unlock dynamic mutex of unlock state + } + else + { + lock_ret = rt_sem_release(pmutex->lock.ksem); + } break; case PMUTEX_RECURSIVE: case PMUTEX_ERRORCHECK: -- Gitee