Skip to content

Commit af9ecca

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 d583615 commit af9ecca

File tree

3 files changed

+42
-40
lines changed

3 files changed

+42
-40
lines changed

include/rtdef.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,7 @@ struct rt_mutex
10281028
rt_uint8_t ceiling_priority; /**< the priority ceiling of mutexe */
10291029
rt_uint8_t priority; /**< the maximal priority for pending thread */
10301030
rt_uint8_t hold; /**< numbers of thread hold the mutex */
1031-
rt_uint8_t reserved; /**< reserved field */
1031+
rt_uint8_t ctrl_flags; /**< flags to control mutex behavior */
10321032

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

include/rtthread.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -445,13 +445,19 @@ rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg);
445445
*/
446446

447447
#ifdef RT_USING_MUTEX
448+
449+
#define RT_MTX_CTRL_FLAG_DEFAULT 0x0 /* create a mutex with default behavior */
450+
#define RT_MTX_CTRL_FLAG_RESERVED 0x01 /* RESERVED for legacy IPC flag */
451+
RT_STATIC_ASSERT(ident_to_ipc_flag, RT_MTX_CTRL_FLAG_RESERVED == RT_IPC_FLAG_PRIO);
452+
#define RT_MTX_CTRL_FLAG_NO_RECUR 0x02 /* create a mutex without recursive taken */
453+
448454
/*
449455
* mutex interface
450456
*/
451-
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag);
457+
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t ctrl_flag);
452458
rt_err_t rt_mutex_detach(rt_mutex_t mutex);
453459
#ifdef RT_USING_HEAP
454-
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag);
460+
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t ctrl_flag);
455461
rt_err_t rt_mutex_delete(rt_mutex_t mutex);
456462
#endif /* RT_USING_HEAP */
457463
void rt_mutex_drop_thread(rt_mutex_t mutex, rt_thread_t thread);

src/ipc.c

+33-37
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,25 @@ static void _mutex_before_delete_detach(rt_mutex_t mutex)
979979
* @addtogroup mutex
980980
* @{
981981
*/
982+
#define LEGAL_CTRL_FLAGS (RT_MTX_CTRL_FLAG_NO_RECUR | RT_IPC_FLAG_PRIO | RT_IPC_FLAG_FIFO)
983+
static void _mutex_init(rt_mutex_t mutex, rt_uint8_t ctrl_flags)
984+
{
985+
RT_ASSERT(!(~LEGAL_CTRL_FLAGS & ctrl_flags));
986+
987+
/* initialize ipc object */
988+
_ipc_object_init(&(mutex->parent));
989+
990+
mutex->owner = RT_NULL;
991+
mutex->priority = 0xFF;
992+
mutex->hold = 0;
993+
mutex->ceiling_priority = 0xFF;
994+
mutex->ctrl_flags = ctrl_flags;
995+
rt_list_init(&(mutex->taken_list));
996+
997+
/* flag can only be RT_IPC_FLAG_PRIO. RT_IPC_FLAG_FIFO cannot solve the unbounded priority inversion problem */
998+
mutex->parent.parent.flag = RT_IPC_FLAG_PRIO;
999+
rt_spin_lock_init(&(mutex->spinlock));
1000+
}
9821001

9831002
/**
9841003
* @brief Initialize a static mutex object.
@@ -995,9 +1014,11 @@ static void _mutex_before_delete_detach(rt_mutex_t mutex)
9951014
*
9961015
* @param name is a pointer to the name that given to the mutex.
9971016
*
998-
* @param flag is the mutex flag, which determines the queuing way of how multiple threads wait
999-
* when the mutex is not available.
1000-
* NOTE: This parameter has been obsoleted. It can be RT_IPC_FLAG_PRIO, RT_IPC_FLAG_FIFO or RT_NULL.
1017+
* @param flag is the mutex flag, which determines specified behaviors:
1018+
* - RT_MTX_CTRL_FLAG_DEFAULT create a mutex with default behavior
1019+
* - RT_MTX_CTRL_FLAG_NO_RECUR create a mutex without recursive taken
1020+
* - [[obsoleted]] RT_IPC_FLAG_PRIO
1021+
* - [[obsoleted]] RT_IPC_FLAG_FIFO
10011022
*
10021023
* @return Return the operation status. When the return value is RT_EOK, the initialization is successful.
10031024
* If the return value is any other values, it represents the initialization failed.
@@ -1006,27 +1027,13 @@ static void _mutex_before_delete_detach(rt_mutex_t mutex)
10061027
*/
10071028
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
10081029
{
1009-
/* flag parameter has been obsoleted */
1010-
RT_UNUSED(flag);
1011-
10121030
/* parameter check */
10131031
RT_ASSERT(mutex != RT_NULL);
10141032

10151033
/* initialize object */
10161034
rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);
10171035

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));
1036+
_mutex_init(mutex, flag);
10301037

10311038
return RT_EOK;
10321039
}
@@ -1222,9 +1229,11 @@ RTM_EXPORT(rt_mutex_getprioceiling);
12221229
*
12231230
* @param name is a pointer to the name that given to the mutex.
12241231
*
1225-
* @param flag is the mutex flag, which determines the queuing way of how multiple threads wait
1226-
* when the mutex is not available.
1227-
* NOTE: This parameter has been obsoleted. It can be RT_IPC_FLAG_PRIO, RT_IPC_FLAG_FIFO or RT_NULL.
1232+
* @param flag is the mutex flag, which determines specified behaviors:
1233+
* - RT_MTX_CTRL_FLAG_DEFAULT create a mutex with default behavior
1234+
* - RT_MTX_CTRL_FLAG_NO_RECUR create a mutex without recursive taken
1235+
* - [[obsoleted]] RT_IPC_FLAG_PRIO
1236+
* - [[obsoleted]] RT_IPC_FLAG_FIFO
12281237
*
12291238
* @return Return a pointer to the mutex object. When the return value is RT_NULL, it means the creation failed.
12301239
*
@@ -1234,28 +1243,14 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
12341243
{
12351244
struct rt_mutex *mutex;
12361245

1237-
/* flag parameter has been obsoleted */
1238-
RT_UNUSED(flag);
1239-
12401246
RT_DEBUG_NOT_IN_INTERRUPT;
12411247

12421248
/* allocate object */
12431249
mutex = (rt_mutex_t)rt_object_allocate(RT_Object_Class_Mutex, name);
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, flag);
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_MTX_CTRL_FLAG_NO_RECUR) &&
1350+
mutex->hold < RT_MUTEX_HOLD_MAX)
13551351
{
13561352
/* it's the same thread */
13571353
mutex->hold ++;

0 commit comments

Comments
 (0)