diff options
| author | Bernard Xiong <[email protected]> | 2022-10-16 17:58:51 +0800 |
|---|---|---|
| committer | Bernard Xiong <[email protected]> | 2022-10-16 17:58:51 +0800 |
| commit | 6823a5110b71d36caa21bab389656d463c863db7 (patch) | |
| tree | 6beed38527a6b0f98b4db3339cfaf78dc1286b0b /src | |
| parent | 34c77da153319da3225bd2064333b34942fee933 (diff) | |
[Kernel] Add prioceiling feature in mutex
Diffstat (limited to 'src')
| -rw-r--r-- | src/ipc.c | 90 |
1 files changed, 83 insertions, 7 deletions
@@ -43,6 +43,7 @@ * 2022-01-24 THEWON let rt_mutex_take return thread->error when using signal * 2022-04-08 Stanley Correct descriptions * 2022-10-15 Bernard add nested mutex feature + * 2022-10-16 Bernard add prioceiling feature in mutex */ #include <rtthread.h> @@ -708,6 +709,8 @@ RTM_EXPORT(rt_sem_control); /**@}*/ #endif /* RT_USING_SEMAPHORE */ +#define RT_USING_MUTEX + #ifdef RT_USING_MUTEX rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *mutex) { @@ -728,12 +731,17 @@ rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *mutex) rt_inline rt_uint8_t _thread_get_mutex_priority(struct rt_thread* thread) { - struct rt_mutex *mutex; + rt_list_t *node = RT_NULL; + struct rt_mutex *mutex = RT_NULL; rt_uint8_t priority = thread->init_priority; - rt_list_for_each_entry(mutex, &(thread->taken_object_list), taken_list) + rt_list_for_each(node, &(thread->taken_object_list)) { - if (priority > mutex->priority) priority = mutex->priority; + mutex = rt_list_entry(node, struct rt_mutex, taken_list); + if (priority > mutex->priority) + { + priority = mutex->priority; + } } return priority; @@ -830,6 +838,7 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) mutex->owner = RT_NULL; mutex->priority = 0xFF; mutex->hold = 0; + mutex->ceiling_priority = 0xFF; rt_list_init(&(mutex->taken_list)); /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ @@ -882,6 +891,13 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex) 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; @@ -923,6 +939,55 @@ void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread) } } + +/** + * @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 /** * @brief This function will create a mutex object. @@ -962,6 +1027,7 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) mutex->owner = RT_NULL; mutex->priority = 0xFF; mutex->hold = 0; + mutex->ceiling_priority = 0xFF; rt_list_init(&(mutex->taken_list)); /* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */ @@ -992,7 +1058,7 @@ RTM_EXPORT(rt_mutex_create); */ rt_err_t rt_mutex_delete(rt_mutex_t mutex) { - rt_ubase_t level; + rt_ubase_t level; /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -1090,8 +1156,18 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout) mutex->owner = thread; mutex->priority = 0xff; mutex->hold = 1; - /* insert mutex to thread's taken object list */ - rt_list_insert_after(&thread->taken_object_list, &mutex->taken_list); + + if (mutex->ceiling_priority != 0xFF) + { + /* 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); + } + else + { + /* insert mutex to thread's taken object list */ + rt_list_insert_after(&thread->taken_object_list, &mutex->taken_list); + } } else { @@ -1298,7 +1374,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex) rt_list_remove(&mutex->taken_list); /* whether change the thread priority */ - if (thread->current_priority == mutex->priority) + if ((mutex->ceiling_priority != 0xFF) || (thread->current_priority == mutex->priority)) { rt_uint8_t priority = 0xff; |
