Skip to content

Commit 89eae2d

Browse files
committed
feat: ipc: add nested-free flag support to mutex
This patch introduces a `nested-free` control flag to the mutex, allowing more flexible control over mutex hold limits. The change is necessary to handle scenarios where nested mutex acquisition is restricted, since it will introduce possibility of data corruption in a nested access to the critical area. Changes: - Added `ctrl_flags` field in `rt_mutex` structure to replace the reserved field for holding control flags. - Introduced `RT_MUTEX_CTRL_NESTED_FREE` command in `rt_mutex_control` to enable the new flag. - Refactored mutex initialization by extracting common logic into a new `_mutex_init` function, reducing code duplication. - Updated the `_rt_mutex_take` function to respect the `nested-free` flag, preventing nested acquisition when the flag is set. - Modified `rt_mutex_control` to handle the new control command and return appropriate error codes for invalid commands. Signed-off-by: Shell <[email protected]>
1 parent 5010c17 commit 89eae2d

File tree

3 files changed

+41
-32
lines changed

3 files changed

+41
-32
lines changed

include/rtdef.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ struct rt_mutex
10171017
rt_uint8_t ceiling_priority; /**< the priority ceiling of mutexe */
10181018
rt_uint8_t priority; /**< the maximal priority for pending thread */
10191019
rt_uint8_t hold; /**< numbers of thread hold the mutex */
1020-
rt_uint8_t reserved; /**< reserved field */
1020+
rt_uint8_t ctrl_flags; /**< reserved field */
10211021

10221022
struct rt_thread *owner; /**< current owner of mutex */
10231023
rt_list_t taken_list; /**< the object list taken by thread */

include/rtthread.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,12 @@ rt_err_t rt_mutex_trytake(rt_mutex_t mutex);
463463
rt_err_t rt_mutex_take_interruptible(rt_mutex_t mutex, rt_int32_t time);
464464
rt_err_t rt_mutex_take_killable(rt_mutex_t mutex, rt_int32_t time);
465465
rt_err_t rt_mutex_release(rt_mutex_t mutex);
466-
rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg);
466+
467+
typedef enum rt_mutex_ctrl_cmd
468+
{
469+
RT_MUTEX_CTRL_NESTED_FREE = 1,
470+
} rt_mutex_ctrl_cmd_t;
471+
rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_mutex_ctrl_cmd_t cmd, void *arg);
467472

468473
rt_inline rt_thread_t rt_mutex_get_owner(rt_mutex_t mutex)
469474
{

src/ipc.c

+34-30
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,23 @@ static void _mutex_before_delete_detach(rt_mutex_t mutex)
980980
* @{
981981
*/
982982

983+
static void _mutex_init(rt_mutex_t mutex)
984+
{
985+
/* initialize ipc object */
986+
_ipc_object_init(&(mutex->parent));
987+
988+
mutex->owner = RT_NULL;
989+
mutex->priority = 0xFF;
990+
mutex->hold = 0;
991+
mutex->ceiling_priority = 0xFF;
992+
mutex->ctrl_flags = 0;
993+
rt_list_init(&(mutex->taken_list));
994+
995+
/* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */
996+
mutex->parent.parent.flag = RT_IPC_FLAG_PRIO;
997+
rt_spin_lock_init(&(mutex->spinlock));
998+
}
999+
9831000
/**
9841001
* @brief Initialize a static mutex object.
9851002
*
@@ -1015,18 +1032,7 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
10151032
/* initialize object */
10161033
rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);
10171034

1018-
/* initialize ipc object */
1019-
_ipc_object_init(&(mutex->parent));
1020-
1021-
mutex->owner = RT_NULL;
1022-
mutex->priority = 0xFF;
1023-
mutex->hold = 0;
1024-
mutex->ceiling_priority = 0xFF;
1025-
rt_list_init(&(mutex->taken_list));
1026-
1027-
/* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */
1028-
mutex->parent.parent.flag = RT_IPC_FLAG_PRIO;
1029-
rt_spin_lock_init(&(mutex->spinlock));
1035+
_mutex_init(mutex);
10301036

10311037
return RT_EOK;
10321038
}
@@ -1244,18 +1250,7 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
12441250
if (mutex == RT_NULL)
12451251
return mutex;
12461252

1247-
/* initialize ipc object */
1248-
_ipc_object_init(&(mutex->parent));
1249-
1250-
mutex->owner = RT_NULL;
1251-
mutex->priority = 0xFF;
1252-
mutex->hold = 0;
1253-
mutex->ceiling_priority = 0xFF;
1254-
rt_list_init(&(mutex->taken_list));
1255-
1256-
/* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */
1257-
mutex->parent.parent.flag = RT_IPC_FLAG_PRIO;
1258-
rt_spin_lock_init(&(mutex->spinlock));
1253+
_mutex_init(mutex);
12591254

12601255
return mutex;
12611256
}
@@ -1351,7 +1346,8 @@ static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t timeout, int suspend
13511346

13521347
if (mutex->owner == thread)
13531348
{
1354-
if (mutex->hold < RT_MUTEX_HOLD_MAX)
1349+
if (!(mutex->ctrl_flags & RT_MUTEX_CTRL_NESTED_FREE) &&
1350+
mutex->hold < RT_MUTEX_HOLD_MAX)
13551351
{
13561352
/* it's the same thread */
13571353
mutex->hold ++;
@@ -1730,13 +1726,21 @@ RTM_EXPORT(rt_mutex_release);
17301726
* @return Return the operation status. When the return value is RT_EOK, the operation is successful.
17311727
* If the return value is any other values, it means that this function failed to execute.
17321728
*/
1733-
rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg)
1729+
rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_mutex_ctrl_cmd_t cmd, void *arg)
17341730
{
1735-
RT_UNUSED(mutex);
1736-
RT_UNUSED(cmd);
1737-
RT_UNUSED(arg);
1731+
rt_err_t error = RT_EOK;
1732+
1733+
switch (cmd)
1734+
{
1735+
case RT_MUTEX_CTRL_NESTED_FREE:
1736+
mutex->ctrl_flags |= RT_MUTEX_CTRL_NESTED_FREE;
1737+
break;
1738+
default:
1739+
error = RT_EINVAL;
1740+
break;
1741+
}
17381742

1739-
return -RT_EINVAL;
1743+
return -error;
17401744
}
17411745
RTM_EXPORT(rt_mutex_control);
17421746

0 commit comments

Comments
 (0)