summaryrefslogtreecommitdiff
path: root/src/ipc.c
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2022-10-16 17:58:51 +0800
committerBernard Xiong <[email protected]>2022-10-16 17:58:51 +0800
commit6823a5110b71d36caa21bab389656d463c863db7 (patch)
tree6beed38527a6b0f98b4db3339cfaf78dc1286b0b /src/ipc.c
parent34c77da153319da3225bd2064333b34942fee933 (diff)
[Kernel] Add prioceiling feature in mutex
Diffstat (limited to 'src/ipc.c')
-rw-r--r--src/ipc.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/src/ipc.c b/src/ipc.c
index 67a998d5df..06a3b8e90b 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -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;