[Kernel] Add prioceiling feature in mutex
This commit is contained in:
parent
34c77da153
commit
6823a5110b
|
@ -771,11 +771,13 @@ struct rt_mutex
|
||||||
{
|
{
|
||||||
struct rt_ipc_object parent; /**< inherit from ipc_object */
|
struct rt_ipc_object parent; /**< inherit from ipc_object */
|
||||||
|
|
||||||
|
rt_uint8_t ceiling_priority; /**< the priority ceiling of mutexe */
|
||||||
rt_uint8_t priority; /**< the maximal priority for pending thread */
|
rt_uint8_t priority; /**< the maximal priority for pending thread */
|
||||||
rt_uint8_t hold; /**< numbers of thread hold the mutex */
|
rt_uint8_t hold; /**< numbers of thread hold the mutex */
|
||||||
|
rt_uint8_t reserv;
|
||||||
|
|
||||||
struct rt_thread *owner; /**< current owner of mutex */
|
struct rt_thread *owner; /**< current owner of mutex */
|
||||||
rt_list_t taken_list; /**< the object list taken by thread */
|
rt_list_t taken_list; /**< the object list taken by thread */
|
||||||
};
|
};
|
||||||
typedef struct rt_mutex *rt_mutex_t;
|
typedef struct rt_mutex *rt_mutex_t;
|
||||||
#endif /* RT_USING_MUTEX */
|
#endif /* RT_USING_MUTEX */
|
||||||
|
|
|
@ -369,6 +369,8 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag);
|
||||||
rt_err_t rt_mutex_delete(rt_mutex_t mutex);
|
rt_err_t rt_mutex_delete(rt_mutex_t mutex);
|
||||||
#endif
|
#endif
|
||||||
void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread);
|
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 timeout);
|
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout);
|
||||||
rt_err_t rt_mutex_trytake(rt_mutex_t mutex);
|
rt_err_t rt_mutex_trytake(rt_mutex_t mutex);
|
||||||
|
|
90
src/ipc.c
90
src/ipc.c
|
@ -43,6 +43,7 @@
|
||||||
* 2022-01-24 THEWON let rt_mutex_take return thread->error when using signal
|
* 2022-01-24 THEWON let rt_mutex_take return thread->error when using signal
|
||||||
* 2022-04-08 Stanley Correct descriptions
|
* 2022-04-08 Stanley Correct descriptions
|
||||||
* 2022-10-15 Bernard add nested mutex feature
|
* 2022-10-15 Bernard add nested mutex feature
|
||||||
|
* 2022-10-16 Bernard add prioceiling feature in mutex
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
@ -708,6 +709,8 @@ RTM_EXPORT(rt_sem_control);
|
||||||
/**@}*/
|
/**@}*/
|
||||||
#endif /* RT_USING_SEMAPHORE */
|
#endif /* RT_USING_SEMAPHORE */
|
||||||
|
|
||||||
|
#define RT_USING_MUTEX
|
||||||
|
|
||||||
#ifdef RT_USING_MUTEX
|
#ifdef RT_USING_MUTEX
|
||||||
rt_inline rt_uint8_t _mutex_update_priority(struct rt_mutex *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)
|
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_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;
|
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->owner = RT_NULL;
|
||||||
mutex->priority = 0xFF;
|
mutex->priority = 0xFF;
|
||||||
mutex->hold = 0;
|
mutex->hold = 0;
|
||||||
|
mutex->ceiling_priority = 0xFF;
|
||||||
rt_list_init(&(mutex->taken_list));
|
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 */
|
/* 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);
|
RTM_EXPORT(rt_mutex_detach);
|
||||||
|
|
||||||
/* drop a thread from the suspend list of mutex */
|
/* 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)
|
void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread)
|
||||||
{
|
{
|
||||||
rt_uint8_t priority;
|
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
|
#ifdef RT_USING_HEAP
|
||||||
/**
|
/**
|
||||||
* @brief This function will create a mutex object.
|
* @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->owner = RT_NULL;
|
||||||
mutex->priority = 0xFF;
|
mutex->priority = 0xFF;
|
||||||
mutex->hold = 0;
|
mutex->hold = 0;
|
||||||
|
mutex->ceiling_priority = 0xFF;
|
||||||
rt_list_init(&(mutex->taken_list));
|
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 */
|
/* 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_err_t rt_mutex_delete(rt_mutex_t mutex)
|
||||||
{
|
{
|
||||||
rt_ubase_t level;
|
rt_ubase_t level;
|
||||||
|
|
||||||
/* parameter check */
|
/* parameter check */
|
||||||
RT_ASSERT(mutex != RT_NULL);
|
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->owner = thread;
|
||||||
mutex->priority = 0xff;
|
mutex->priority = 0xff;
|
||||||
mutex->hold = 1;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -1298,7 +1374,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
|
||||||
rt_list_remove(&mutex->taken_list);
|
rt_list_remove(&mutex->taken_list);
|
||||||
|
|
||||||
/* whether change the thread priority */
|
/* 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;
|
rt_uint8_t priority = 0xff;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue