Skip to content

Commit 83887a1

Browse files
committed
fix(kernel): properly release mutexes in _thread_detach_from_mutex()
1 parent f9564d4 commit 83887a1

File tree

3 files changed

+36
-10
lines changed

3 files changed

+36
-10
lines changed

include/rtthread.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ rt_err_t rt_mutex_trytake(rt_mutex_t mutex);
465465
rt_err_t rt_mutex_take_interruptible(rt_mutex_t mutex, rt_int32_t time);
466466
rt_err_t rt_mutex_take_killable(rt_mutex_t mutex, rt_int32_t time);
467467
rt_err_t rt_mutex_release(rt_mutex_t mutex);
468+
rt_err_t rt_mutex_force_release(rt_mutex_t mutex);
468469
rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg);
469470

470471
rt_inline rt_thread_t rt_mutex_get_owner(rt_mutex_t mutex)

src/ipc.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,15 +1578,15 @@ RTM_EXPORT(rt_mutex_trytake);
15781578
* @brief This function will release a mutex. If there is thread suspended on the mutex, the thread will be resumed.
15791579
*
15801580
* @note If there are threads suspended on this mutex, the first thread in the list of this mutex object
1581-
* will be resumed, and a thread scheduling (rt_schedule) will be executed.
1581+
* will be resumed.
15821582
* If no threads are suspended on this mutex, the count value mutex->value of this mutex will increase by 1.
1583+
* This operation requires mutex->spinlock to be held.
15831584
*
15841585
* @param mutex is a pointer to a mutex object.
15851586
*
1586-
* @return Return the operation status. When the return value is RT_EOK, the operation is successful.
1587-
* If the return value is any other values, it means that the mutex release failed.
1587+
* @return Return RT_TRUE if scheduling is needed, RT_FALSE otherwise.
15881588
*/
1589-
rt_err_t rt_mutex_release(rt_mutex_t mutex)
1589+
static rt_err_t _rt_mutex_release(rt_mutex_t mutex, rt_bool_t is_force)
15901590
{
15911591
rt_sched_lock_level_t slvl;
15921592
struct rt_thread *thread;
@@ -1612,11 +1612,15 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
16121612
RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mutex->parent.parent)));
16131613

16141614
/* mutex only can be released by owner */
1615-
if (thread != mutex->owner)
1615+
if (is_force)
1616+
{
1617+
/* Force release by setting hold count to 1 */
1618+
mutex->hold = 1;
1619+
}
1620+
else if (thread != mutex->owner)
16161621
{
16171622
thread->error = -RT_ERROR;
16181623
rt_spin_unlock(&(mutex->spinlock));
1619-
16201624
return -RT_ERROR;
16211625
}
16221626

@@ -1713,9 +1717,31 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
17131717

17141718
return RT_EOK;
17151719
}
1716-
RTM_EXPORT(rt_mutex_release);
17171720

17181721

1722+
rt_err_t rt_mutex_force_release(rt_mutex_t mutex)
1723+
{
1724+
return _rt_mutex_release(mutex, RT_TRUE);
1725+
}
1726+
1727+
1728+
/**
1729+
* @brief Release a mutex owned by current thread.
1730+
*
1731+
* @note Resumes first suspended thread if any (requires scheduling).
1732+
* Increases mutex->value if no threads waiting.
1733+
* Must be called by mutex owner with spinlock held.
1734+
*
1735+
* @param mutex Pointer to the mutex object.
1736+
*
1737+
* @return RT_EOK on success, -RT_ERROR if not owner.
1738+
*/
1739+
rt_err_t rt_mutex_release(rt_mutex_t mutex)
1740+
{
1741+
return _rt_mutex_release(mutex, RT_FALSE);
1742+
}
1743+
RTM_EXPORT(rt_mutex_release);
1744+
17191745
/**
17201746
* @brief This function will set some extra attributions of a mutex object.
17211747
*

src/thread.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ RT_OBJECT_HOOKLIST_DEFINE(rt_thread_inited);
7777
#endif /* defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR) */
7878

7979
#ifdef RT_USING_MUTEX
80+
8081
static void _thread_detach_from_mutex(rt_thread_t thread)
8182
{
8283
rt_list_t *node;
@@ -101,9 +102,7 @@ static void _thread_detach_from_mutex(rt_thread_t thread)
101102
{
102103
mutex = rt_list_entry(node, struct rt_mutex, taken_list);
103104
LOG_D("Thread [%s] exits while holding mutex [%s].\n", thread->parent.name, mutex->parent.parent.name);
104-
/* recursively take */
105-
mutex->hold = 1;
106-
rt_mutex_release(mutex);
105+
rt_mutex_force_release(mutex);
107106
}
108107

109108
rt_spin_unlock_irqrestore(&thread->spinlock, level);

0 commit comments

Comments
 (0)