Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2020fengziyang
rt-thread
提交
79e29814
R
rt-thread
项目概览
2020fengziyang
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
79e29814
编写于
11月 06, 2022
作者:
B
Bernard Xiong
提交者:
GitHub
11月 06, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #6523 from BernardXiong/nested_mutex
[Kernel] Add nested mutex feature
上级
ac2fb2be
c06c4075
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
362 addition
and
77 deletion
+362
-77
components/finsh/cmd.c
components/finsh/cmd.c
+5
-4
include/rtdef.h
include/rtdef.h
+11
-3
include/rtthread.h
include/rtthread.h
+3
-0
src/ipc.c
src/ipc.c
+316
-70
src/thread.c
src/thread.c
+27
-0
未找到文件。
components/finsh/cmd.c
浏览文件 @
79e29814
...
@@ -411,9 +411,9 @@ long list_mutex(void)
...
@@ -411,9 +411,9 @@ long list_mutex(void)
maxlen
=
RT_NAME_MAX
;
maxlen
=
RT_NAME_MAX
;
rt_kprintf
(
"%-*.s owner hold suspend thread
\n
"
,
maxlen
,
item_title
);
rt_kprintf
(
"%-*.s owner hold suspend thread
priority
\n
"
,
maxlen
,
item_title
);
object_split
(
maxlen
);
object_split
(
maxlen
);
rt_kprintf
(
" -------- ---- --------------
\n
"
);
rt_kprintf
(
" -------- ---- --------------
--------
\n
"
);
do
do
{
{
...
@@ -436,13 +436,14 @@ long list_mutex(void)
...
@@ -436,13 +436,14 @@ long list_mutex(void)
rt_hw_interrupt_enable
(
level
);
rt_hw_interrupt_enable
(
level
);
m
=
(
struct
rt_mutex
*
)
obj
;
m
=
(
struct
rt_mutex
*
)
obj
;
rt_kprintf
(
"%-*.*s %-8.*s %04d %d
\n
"
,
rt_kprintf
(
"%-*.*s %-8.*s %04d %d
%d
\n
"
,
maxlen
,
RT_NAME_MAX
,
maxlen
,
RT_NAME_MAX
,
m
->
parent
.
parent
.
name
,
m
->
parent
.
parent
.
name
,
RT_NAME_MAX
,
RT_NAME_MAX
,
m
->
owner
->
name
,
m
->
owner
->
name
,
m
->
hold
,
m
->
hold
,
rt_list_len
(
&
m
->
parent
.
suspend_thread
));
rt_list_len
(
&
m
->
parent
.
suspend_thread
),
m
->
priority
);
}
}
}
}
...
...
include/rtdef.h
浏览文件 @
79e29814
...
@@ -673,12 +673,19 @@ struct rt_thread
...
@@ -673,12 +673,19 @@ struct rt_thread
/* priority */
/* priority */
rt_uint8_t
current_priority
;
/**< current priority */
rt_uint8_t
current_priority
;
/**< current priority */
rt_uint8_t
init_priority
;
/**< initialized priority */
#if RT_THREAD_PRIORITY_MAX > 32
#if RT_THREAD_PRIORITY_MAX > 32
rt_uint8_t
number
;
rt_uint8_t
number
;
rt_uint8_t
high_mask
;
rt_uint8_t
high_mask
;
#endif
/* RT_THREAD_PRIORITY_MAX > 32 */
#endif
/* RT_THREAD_PRIORITY_MAX > 32 */
rt_uint32_t
number_mask
;
rt_uint32_t
number_mask
;
#ifdef RT_USING_MUTEX
/* object for IPC */
rt_list_t
taken_object_list
;
rt_object_t
pending_object
;
#endif
#ifdef RT_USING_EVENT
#ifdef RT_USING_EVENT
/* thread event */
/* thread event */
rt_uint32_t
event_set
;
rt_uint32_t
event_set
;
...
@@ -772,12 +779,13 @@ struct rt_mutex
...
@@ -772,12 +779,13 @@ struct rt_mutex
{
{
struct
rt_ipc_object
parent
;
/**< inherit from ipc_object */
struct
rt_ipc_object
parent
;
/**< inherit from ipc_object */
rt_uint16_t
value
;
/**< value of mutex */
rt_uint8_t
ceiling_priority
;
/**< the priority ceiling of mutexe */
rt_uint8_t
priority
;
/**< the maximal priority for pending thread */
rt_uint8_t
original_priority
;
/**< priority of last thread hold the mutex */
rt_uint8_t
hold
;
/**< numbers of thread hold the mutex */
rt_uint8_t
hold
;
/**< numbers of thread hold the mutex */
rt_uint8_t
reserved
;
/**< reserved field */
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 */
};
};
typedef
struct
rt_mutex
*
rt_mutex_t
;
typedef
struct
rt_mutex
*
rt_mutex_t
;
#endif
/* RT_USING_MUTEX */
#endif
/* RT_USING_MUTEX */
...
...
include/rtthread.h
浏览文件 @
79e29814
...
@@ -368,6 +368,9 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex);
...
@@ -368,6 +368,9 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex);
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_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
);
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
);
...
...
src/ipc.c
浏览文件 @
79e29814
...
@@ -42,6 +42,8 @@
...
@@ -42,6 +42,8 @@
* 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to ipc.c
* 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to ipc.c
* 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-16 Bernard add prioceiling feature in mutex
*/
*/
#include <rtthread.h>
#include <rtthread.h>
...
@@ -708,6 +710,83 @@ RTM_EXPORT(rt_sem_control);
...
@@ -708,6 +710,83 @@ RTM_EXPORT(rt_sem_control);
#endif
/* RT_USING_SEMAPHORE */
#endif
/* RT_USING_SEMAPHORE */
#ifdef RT_USING_MUTEX
#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
)
{
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
));
_ipc_list_suspend
(
&
(
pending_mutex
->
parent
.
suspend_thread
),
thread
,
pending_mutex
->
parent
.
parent
.
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
);
}
}
}
}
/**
/**
* @addtogroup mutex
* @addtogroup mutex
*/
*/
...
@@ -752,10 +831,11 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
...
@@ -752,10 +831,11 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
/* initialize ipc object */
/* initialize ipc object */
_ipc_object_init
(
&
(
mutex
->
parent
));
_ipc_object_init
(
&
(
mutex
->
parent
));
mutex
->
value
=
1
;
mutex
->
owner
=
RT_NULL
;
mutex
->
owner
=
RT_NULL
;
mutex
->
original_
priority
=
0xFF
;
mutex
->
priority
=
0xFF
;
mutex
->
hold
=
0
;
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 */
/* 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
;
mutex
->
parent
.
parent
.
flag
=
RT_IPC_FLAG_PRIO
;
...
@@ -785,13 +865,19 @@ RTM_EXPORT(rt_mutex_init);
...
@@ -785,13 +865,19 @@ RTM_EXPORT(rt_mutex_init);
*/
*/
rt_err_t
rt_mutex_detach
(
rt_mutex_t
mutex
)
rt_err_t
rt_mutex_detach
(
rt_mutex_t
mutex
)
{
{
rt_ubase_t
level
;
/* parameter check */
/* parameter check */
RT_ASSERT
(
mutex
!=
RT_NULL
);
RT_ASSERT
(
mutex
!=
RT_NULL
);
RT_ASSERT
(
rt_object_get_type
(
&
mutex
->
parent
.
parent
)
==
RT_Object_Class_Mutex
);
RT_ASSERT
(
rt_object_get_type
(
&
mutex
->
parent
.
parent
)
==
RT_Object_Class_Mutex
);
RT_ASSERT
(
rt_object_is_systemobject
(
&
mutex
->
parent
.
parent
));
RT_ASSERT
(
rt_object_is_systemobject
(
&
mutex
->
parent
.
parent
));
level
=
rt_hw_interrupt_disable
();
/* wakeup all suspended threads */
/* wakeup all suspended threads */
_ipc_list_resume_all
(
&
(
mutex
->
parent
.
suspend_thread
));
_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 mutex object */
/* detach mutex object */
rt_object_detach
(
&
(
mutex
->
parent
.
parent
));
rt_object_detach
(
&
(
mutex
->
parent
.
parent
));
...
@@ -800,6 +886,104 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex)
...
@@ -800,6 +886,104 @@ 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 */
/**
* @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
);
}
}
}
/**
* @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.
...
@@ -836,10 +1020,11 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
...
@@ -836,10 +1020,11 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
/* initialize ipc object */
/* initialize ipc object */
_ipc_object_init
(
&
(
mutex
->
parent
));
_ipc_object_init
(
&
(
mutex
->
parent
));
mutex
->
value
=
1
;
mutex
->
owner
=
RT_NULL
;
mutex
->
owner
=
RT_NULL
;
mutex
->
original_priority
=
0xFF
;
mutex
->
priority
=
0xFF
;
mutex
->
hold
=
0
;
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 */
/* 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
;
mutex
->
parent
.
parent
.
flag
=
RT_IPC_FLAG_PRIO
;
...
@@ -869,6 +1054,8 @@ RTM_EXPORT(rt_mutex_create);
...
@@ -869,6 +1054,8 @@ 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
;
/* parameter check */
/* parameter check */
RT_ASSERT
(
mutex
!=
RT_NULL
);
RT_ASSERT
(
mutex
!=
RT_NULL
);
RT_ASSERT
(
rt_object_get_type
(
&
mutex
->
parent
.
parent
)
==
RT_Object_Class_Mutex
);
RT_ASSERT
(
rt_object_get_type
(
&
mutex
->
parent
.
parent
)
==
RT_Object_Class_Mutex
);
...
@@ -876,8 +1063,12 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex)
...
@@ -876,8 +1063,12 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex)
RT_DEBUG_NOT_IN_INTERRUPT
;
RT_DEBUG_NOT_IN_INTERRUPT
;
level
=
rt_hw_interrupt_disable
();
/* wakeup all suspended threads */
/* wakeup all suspended threads */
_ipc_list_resume_all
(
&
(
mutex
->
parent
.
suspend_thread
));
_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 */
/* delete mutex object */
rt_object_delete
(
&
(
mutex
->
parent
.
parent
));
rt_object_delete
(
&
(
mutex
->
parent
.
parent
));
...
@@ -933,8 +1124,8 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
...
@@ -933,8 +1124,8 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
RT_OBJECT_HOOK_CALL
(
rt_object_trytake_hook
,
(
&
(
mutex
->
parent
.
parent
)));
RT_OBJECT_HOOK_CALL
(
rt_object_trytake_hook
,
(
&
(
mutex
->
parent
.
parent
)));
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
(
"mutex_take: current thread %s,
mutex value: %d,
hold: %d
\n
"
,
(
"mutex_take: current thread %s, hold: %d
\n
"
,
thread
->
name
,
mutex
->
value
,
mutex
->
hold
));
thread
->
name
,
mutex
->
hold
));
/* reset thread error */
/* reset thread error */
thread
->
error
=
RT_EOK
;
thread
->
error
=
RT_EOK
;
...
@@ -954,25 +1145,24 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
...
@@ -954,25 +1145,24 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
}
}
else
else
{
{
/* The value of mutex is 1 in initial status. Therefore, if the
/* whether the mutex has owner thread. */
* value is great than 0, it indicates the mutex is avaible.
if
(
mutex
->
owner
==
RT_NULL
)
*/
if
(
mutex
->
value
>
0
)
{
{
/* mutex is available */
mutex
->
value
--
;
/* set mutex owner and original priority */
/* set mutex owner and original priority */
mutex
->
owner
=
thread
;
mutex
->
owner
=
thread
;
mutex
->
original_priority
=
thread
->
current_priority
;
mutex
->
priority
=
0xff
;
if
(
mutex
->
hold
<
RT_MUTEX_HOLD_MAX
)
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
);
}
}
else
else
{
{
rt_hw_interrupt_enable
(
level
);
/* enable interrup
t */
/* insert mutex to thread's taken object lis
t */
r
eturn
-
RT_EFULL
;
/* value overflowed */
r
t_list_insert_after
(
&
thread
->
taken_object_list
,
&
mutex
->
taken_list
);
}
}
}
}
else
else
...
@@ -990,23 +1180,28 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
...
@@ -990,23 +1180,28 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
}
}
else
else
{
{
rt_uint8_t
priority
=
thread
->
current_priority
;
/* mutex is unavailable, push to suspend list */
/* mutex is unavailable, push to suspend list */
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
(
"mutex_take: suspend thread: %s
\n
"
,
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
(
"mutex_take: suspend thread: %s
\n
"
,
thread
->
name
));
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 */
/* suspend current thread */
_ipc_list_suspend
(
&
(
mutex
->
parent
.
suspend_thread
),
_ipc_list_suspend
(
&
(
mutex
->
parent
.
suspend_thread
),
thread
,
thread
,
mutex
->
parent
.
parent
.
flag
);
mutex
->
parent
.
parent
.
flag
);
/* 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
);
}
}
/* has waiting time, start thread timer */
/* has waiting time, start thread timer */
if
(
timeout
>
0
)
if
(
timeout
>
0
)
...
@@ -1028,16 +1223,57 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
...
@@ -1028,16 +1223,57 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout)
/* do schedule */
/* do schedule */
rt_schedule
();
rt_schedule
();
if
(
thread
->
error
!=
RT_EOK
)
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
if
(
thread
->
error
==
RT_EOK
)
{
{
/* return error */
/* get mutex successfully */
return
thread
->
error
;
}
}
else
else
{
{
/* the mutex is taken successfully. */
/* the mutex has not been taken and thread has detach from the pending list. */
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
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
);
}
}
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
/* return error */
return
thread
->
error
;
}
}
}
}
}
}
...
@@ -1109,8 +1345,8 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
...
@@ -1109,8 +1345,8 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
level
=
rt_hw_interrupt_disable
();
level
=
rt_hw_interrupt_disable
();
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
(
"mutex_release:current thread %s,
mutex value: %d,
hold: %d
\n
"
,
(
"mutex_release:current thread %s, hold: %d
\n
"
,
thread
->
name
,
mutex
->
value
,
mutex
->
hold
));
thread
->
name
,
mutex
->
hold
));
RT_OBJECT_HOOK_CALL
(
rt_object_put_hook
,
(
&
(
mutex
->
parent
.
parent
)));
RT_OBJECT_HOOK_CALL
(
rt_object_put_hook
,
(
&
(
mutex
->
parent
.
parent
)));
...
@@ -1130,60 +1366,70 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
...
@@ -1130,60 +1366,70 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
/* if no hold */
/* if no hold */
if
(
mutex
->
hold
==
0
)
if
(
mutex
->
hold
==
0
)
{
{
/* change the owner thread to original priority */
/* remove mutex from thread's taken list */
if
(
mutex
->
original_priority
!=
mutex
->
owner
->
current_priority
)
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
,
RT_THREAD_CTRL_CHANGE_PRIORITY
,
&
(
mutex
->
original_priority
));
&
priority
);
need_schedule
=
RT_TRUE
;
}
}
/* wakeup suspended thread */
/* wakeup suspended thread */
if
(
!
rt_list_isempty
(
&
mutex
->
parent
.
suspend_thread
))
if
(
!
rt_list_isempty
(
&
mutex
->
parent
.
suspend_thread
))
{
{
/* get suspended thread */
/* get
the first
suspended thread */
thread
=
rt_list_entry
(
mutex
->
parent
.
suspend_thread
.
next
,
struct
rt_thread
*
next_
thread
=
rt_list_entry
(
mutex
->
parent
.
suspend_thread
.
next
,
struct
rt_thread
,
struct
rt_thread
,
tlist
);
tlist
);
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
(
"mutex_release: resume thread: %s
\n
"
,
RT_DEBUG_LOG
(
RT_DEBUG_IPC
,
(
"mutex_release: resume thread: %s
\n
"
,
thread
->
name
));
next_
thread
->
name
));
/* set new owner and priority */
/* remove the thread from the suspended list of mutex */
mutex
->
owner
=
thread
;
rt_list_remove
(
&
(
next_thread
->
tlist
));
mutex
->
original_priority
=
thread
->
current_priority
;
if
(
mutex
->
hold
<
RT_MUTEX_HOLD_MAX
)
/* 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
else
{
{
rt_hw_interrupt_enable
(
level
);
/* enable interrupt */
mutex
->
priority
=
0xff
;
return
-
RT_EFULL
;
/* value overflowed */
}
}
/* resume thread */
_ipc_list_resume
(
&
(
mutex
->
parent
.
suspend_thread
));
need_schedule
=
RT_TRUE
;
need_schedule
=
RT_TRUE
;
}
}
else
else
{
{
if
(
mutex
->
value
<
RT_MUTEX_VALUE_MAX
)
{
/* increase value */
mutex
->
value
++
;
}
else
{
rt_hw_interrupt_enable
(
level
);
/* enable interrupt */
return
-
RT_EFULL
;
/* value overflowed */
}
/* clear owner */
/* clear owner */
mutex
->
owner
=
RT_NULL
;
mutex
->
owner
=
RT_NULL
;
mutex
->
original_
priority
=
0xff
;
mutex
->
priority
=
0xff
;
}
}
}
}
...
...
src/thread.c
浏览文件 @
79e29814
...
@@ -31,6 +31,7 @@
...
@@ -31,6 +31,7 @@
* 2021-12-27 Meco Man remove .init_priority
* 2021-12-27 Meco Man remove .init_priority
* 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to thread.c
* 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to thread.c
* 2022-01-24 THEWON let rt_thread_sleep return thread->error when using signal
* 2022-01-24 THEWON let rt_thread_sleep return thread->error when using signal
* 2022-10-15 Bernard add nested mutex feature
*/
*/
#include <rthw.h>
#include <rthw.h>
...
@@ -187,10 +188,16 @@ static rt_err_t _thread_init(struct rt_thread *thread,
...
@@ -187,10 +188,16 @@ static rt_err_t _thread_init(struct rt_thread *thread,
/* priority init */
/* priority init */
RT_ASSERT
(
priority
<
RT_THREAD_PRIORITY_MAX
);
RT_ASSERT
(
priority
<
RT_THREAD_PRIORITY_MAX
);
thread
->
init_priority
=
priority
;
thread
->
current_priority
=
priority
;
thread
->
current_priority
=
priority
;
thread
->
number_mask
=
0
;
thread
->
number_mask
=
0
;
#ifdef RT_USING_MUTEX
rt_list_init
(
&
thread
->
taken_object_list
);
thread
->
pending_object
=
RT_NULL
;
#endif
#ifdef RT_USING_EVENT
#ifdef RT_USING_EVENT
thread
->
event_set
=
0
;
thread
->
event_set
=
0
;
thread
->
event_info
=
0
;
thread
->
event_info
=
0
;
...
@@ -420,6 +427,16 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
...
@@ -420,6 +427,16 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
/* change stat */
/* change stat */
thread
->
stat
=
RT_THREAD_CLOSE
;
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 */
/* insert to defunct thread list */
rt_thread_defunct_enqueue
(
thread
);
rt_thread_defunct_enqueue
(
thread
);
...
@@ -523,6 +540,16 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
...
@@ -523,6 +540,16 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
/* change stat */
/* change stat */
thread
->
stat
=
RT_THREAD_CLOSE
;
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 */
/* insert to defunct thread list */
rt_thread_defunct_enqueue
(
thread
);
rt_thread_defunct_enqueue
(
thread
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录