Skip to content

互斥锁嵌套使用中的优先级翻转问题? #3272

@13824125580

Description

@13824125580

基于lts分支测试如下代码:
#include <typedef.h>
#include <rtthread.h>
#include <waitqueue.h>
#include <rthw.h>
#include <arch.h>
#include <log.h>

void udelay(unsigned int us);
static rt_mutex_t mutex_s1, mutex_s2;
static void pri_task_a(void *ARG_UNUSED(para))
{
while (1)
{
rt_thread_delay(2000);
__log("before got s1");
rt_mutex_take(mutex_s1, RT_WAITING_FOREVER);
__log("got s1");
udelay(100 * 1000 * 1000);
__log("after delay 100s");
rt_mutex_release(mutex_s1);
__log("release s1");
}
}

static void pri_task_b(void *ARG_UNUSED(para))
{
rt_thread_delay(5000);

while (1)
{
udelay(1);
}

}

static void pri_task_c(void *ARG_UNUSED(para))
{
while (1)
{
rt_thread_delay(1000);
__log("before got s1");
rt_mutex_take(mutex_s1, RT_WAITING_FOREVER);
__log("got s1");
rt_mutex_take(mutex_s2, RT_WAITING_FOREVER);
__log("got s2");
udelay(100 * 1000 * 1000);
__log("delay 100s");
rt_mutex_release(mutex_s2);
__log("release s2");
rt_mutex_release(mutex_s1);
__log("release s1");
}
}

static void pri_task_d(void *ARG_UNUSED(para))
{
while (1)
{
__log("before got s2");
rt_mutex_take(mutex_s2, RT_WAITING_FOREVER);
__log("got s2");
udelay(100 * 1000 * 1000);
__log("after delay 100s.");
rt_mutex_release(mutex_s2);
__log("release s2.");
}
}

/* ----------------------------------------------------------------------------/
/

  • @brief schedule_in_irqlock <test pattern, Thread swith out when iterrupt
  •      disable>
    

/
/
----------------------------------------------------------------------------*/
void priority_entry(void)
{
rt_thread_t thread;

mutex_s1 = rt_mutex_create("mutexs1", RT_IPC_FLAG_FIFO);
mutex_s2 = rt_mutex_create("mutexs2", RT_IPC_FLAG_FIFO);
if(mutex_s1 == RT_NULL || mutex_s2 == RT_NULL)
{
    __err("fatal error");
    return;
}

thread = rt_thread_create("pri_a", pri_task_a, RT_NULL, 0x1000, 0, 10);
rt_thread_startup(thread);

thread = rt_thread_create("pri_b", pri_task_b, RT_NULL, 0x1000, 1, 10);
rt_thread_startup(thread);

thread = rt_thread_create("pri_c", pri_task_c, RT_NULL, 0x1000, 2, 10);
rt_thread_startup(thread);

thread = rt_thread_create("pri_d", pri_task_d, RT_NULL, 0x1000, 3, 10);
rt_thread_startup(thread);

return;

}
--------------------------------------------
现象:
[DBG]: [pri_task_d:0075]: before got s2
[DBG]: [pri_task_d:0077]: got s2
[DBG]: [pri_task_c:0057]: before got s1
[DBG]: [pri_task_c:0059]: got s1
[DBG]: [pri_task_a:0032]: before got s1
------------------------
系统输出最后一行后,打印停止,finsh不在交互,处于永久锁死状态

测试条件:
A,B,C,D四个任务,mutexs1, mutexs2两个信号量.
任务优先级A>B>C>D
程序流程:
1.D 执行,获取S2
2.C被唤醒,抢占D
3. C获取S1成功,但2已经被D占有,C被阻塞,D优先级继承C.
4. D继续执行,但中途A被唤醒,A抢占D
5. A尝试占有S1, 但S1此时被C占有,A阻塞,C优先级继承了A,但扔阻塞在S2上
6.D继续执行,中途B被唤醒,B抢占了D
7. 由于B不需要占用任何资源,所以高优先级任务A被中间优先级任务B阻塞,优先级继承失效。

-------------------------------------------
我理解可以通过让B睡眠一段时间的方式解锁这个过程,但机制上,A的唤醒时间依赖于B何时去主动出让处理器,而这个条件完全由B决定是不合理的,A虽然最高优先级但无法保证deadline。高优先级任务A的优先级没有传染给依赖链。

请社区各位朋友帮忙check,是否存在这样的问题,面对复杂的执行流,这个路径应该有可能出现,谢谢大家的指导!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions