我试图在一个小的 C++ 程序上激发 Priority Inversion 用于演示目的,但我不能:持有互斥锁 is not preempted 的低优先级线程并继续在关键部分运行 . 这就是我正在做的事情:
// let's declare a global mutex
pthread_mutex_t my_mutex;
...
int main(int argc, char **argv) {
...
pthread_t normal_thread;
pthread_t prio_thread;
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_NONE); // ! None !
pthread_mutex_init(&my_mutex, &attr);
// create first normal thread (L):
pthread_create(&normal_thread, NULL, the_locking_start_routine, NULL);
// just to help the normal thread enter in the critical section
sleep(2);
// now will launch:
// * (M) several CPU intensive SCHED_FIFO threads with priority < 99
// * (H) one SCHED_FIFO thread that will try to lock the mutex, with priority < 99
// build Real Time attributes for the Real Time threads:
pthread_attr_t my_rt_att;
pthread_attr_init(&my_rt_att);
// it was missing in the original post and it was also wrong:
// even setting the SchedPolicy you have to set "InheritSched"
pthread_attr_setinheritsched(&my_rt_att, PTHREAD_EXPLICIT_SCHED)
pthread_attr_setschedpolicy(&my_rt_att, SCHED_FIFO);
struct sched_param params;
params.sched_priority = 1;
pthread_attr_setschedparam(&my_rt_att, ¶ms);
pthread_create(&prio_thread, &my_rt_att, the_CPU_intensive_start_routine, NULL)
params.sched_priority = 99;
pthread_attr_setschedparam(&my_rt_att, ¶ms);
// create one RealTime thread like this:
pthread_create(&prio_thread, &my_rt_att, the_locking_start_routine, NULL) //coma was missing
...
}
void *the_locking_start_routine(void *arg) {
...
pthread_mutex_lock(&my_mutex);
// This thread is on the critical section
// ... (skipped)
pthread_mutex_unlock(&my_mutex);
...
}
...但它不起作用,我不能有我想要的优先级倒置 .
这是发生的事情:
据我所知,使用像Linux的CFS这样的scheduller,非实时线程(SCHED_OTHER)将不会运行,直到没有任何实时线程(SCHED_FIFO或SCHED_RR)处于运行状态 . 但我已经实现了同时运行的这些线程:
-
(L)一个非实时(SCHED_OTHER)线程锁定互斥锁并占用CPU
-
(M)几个实时线程(SCHED_FIFO,&priority> 0)CPU密集型且无法等待锁定互斥锁
-
(H)等待锁定的一个实时线程(SCHED_FIFO,和最高优先级)
运行的实时CPU密集型线程(M)比我的系统的CPU数量多......但非实时线程持有(L)锁仍然消耗CPU并完成它的工作并在之前释放互斥锁“M”线程完成消耗CPU .
Why isn't the low priority thread preempted, the application dead-locked and I can't get priority inversion?
我在内核2.6.38-13的Ubuntu Desktop 11.04上使用g 4.5.2 .
3 回答
您是否以root身份运行该程序?
这些sysctl参数的值是多少?这是我的Ubuntu盒子 . 默认设置是在1秒切片中仅提供0.95秒的实时时间:
这可以防止实时域占用所有CPU . 如果您想要实时,则必须禁用这些参数 .
见:http://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt
如果将
sched_rt_runtime_us
设置为-1,则禁用此安全机制 .Re:I 'm trying to provoke Priority Inversion on a small C++ program for demonstration purposes but I can' t:保存互斥锁的低优先级线程没有被抢占并继续运行......
那是 is 优先倒置情景的开始 . 低优先级线程抓取高优先级线程然后阻塞的独占资源(例如互斥锁) .
要正确显示优先级倒置的后果,您需要三个线程:低(L),中(M)和高(H)优先级线程 .
L锁定互斥锁,H争辩 . 所以L在运行,H不是 . 这已经很糟糕了:重要的线程H正在等待不太重要的线程L做某事 .
现在M变得可运行并且是计算密集型的 . M不关心互斥体;它与H或L无关 . 但是M具有比L更高的优先级并且从CPU中取出L .
所以现在M继续执行,阻止L运行 . 这可以防止L到达释放互斥锁的代码行,从而阻止H获取互斥锁 .
因此,正在运行中优先级线程M而不是最高优先级线程H.
通过阻挡L,M也能够阻挡H:反转 .
看看你是否可以像这样编码 .
大多数现代调度程序都具有防死锁保护措施,可以在一个或两个时间片上更改优先级,以防止在检测到或认为合适时导致死锁的优先级倒置 . 无论linux是否与您使用的调度程序一起使用,我都不确定 . 但是,如果你还没有,请注意这一点 .