不能在C ++中引发优先级反转 [英] Can't provoke Priority Inversion in C++
问题描述
我试图在小型 C ++ 程序上引发优先级反转,但是我无法:持有互斥体的低优先级线程不抢占并继续在关键部分运行。这是我在做什么:
//让我们声明一个全局互斥量
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); //!没有 !
pthread_mutex_init(& my_mutex,& attr);
//创建第一个普通线程(L):
pthread_create(& normal_thread,NULL,the_locking_start_routine,NULL);
//只是为了帮助正常的线程在临界区输入
sleep(2);
//现在将启动:
// *(M)几个CPU密集型SCHED_FIFO线程,优先级< 99
// *(H)一个SCHED_FIFO线程,将尝试锁定互斥体, 99
//为Real Time线程构建实时属性:
pthread_attr_t my_rt_att;
pthread_attr_init(& my_rt_att);
//它在原始帖子中丢失,并且错误:
//即使设置SchedPolicy,你必须设置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,& params);
pthread_create(& prio_thread,& my_rt_att,the_CPU_intensive_start_routine,NULL)
params.sched_priority = 99;
pthread_attr_setschedparam(& my_rt_att,& params);
//创建一个RealTime线程如下:
pthread_create(& prio_thread,& my_rt_att,the_locking_start_routine,NULL)// coma丢失
。
}
void * the_locking_start_routine(void * arg){
...
pthread_mutex_lock(& my_mutex);
//这个线程在关键部分
// ...(跳过)
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。
为什么不低优先级线程被抢占,应用程序死锁, ?
我在内核2.6.38-13的Ubuntu Desktop 11.04上使用g ++ 4.5.2。
kernel.sched_rt_period_us = 1000000
kernel.sched_rt_runtime_us = 950000
这会阻止实时域占用所有CPU。
请参阅: http://www.kernel.org/doc/Documentation/scheduler/sched-rt-group。 txt
如果将 sched_rt_runtime_us
设置为-1,则禁用此安全机制。
I'm trying to provoke Priority Inversion on a small C++ program for demonstration purposes but I can't: The low priority thread that holds the mutex is not preempted and keeps running on the critical section. This is what I'm doing:
// 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);
...
}
... But it doesn't work, I can't have my desired Priority Inversion.
This is what happens:
As I understand, with a scheduller like Linux's CFS, a non-real time thread (SCHED_OTHER) will not run until there isn't any Real Time thread (SCHED_FIFO or SCHED_RR) in runnning state. But I have achieved this threads running simultaneously:
- (L) One non-real time (SCHED_OTHER) thread locking the mutex and consuming CPU
- (M) several Real Time threads (SCHED_FIFO , & priority > 0) CPU intensive and non-waiting to lock the mutex
- (H) One Real Time thread (SCHED_FIFO , & highest priority ) waiting for the lock
There are more Real Time CPU intensive threads (M) running than the amount of CPUs of my system ... but the non-real time thread holding (L) the lock is still consuming CPU and finishes it's work and releases the mutex before the "M" threads finish consuming CPU.
Why isn't the low priority thread preempted, the application dead-locked and I can't get priority inversion?
I'm using g++ 4.5.2 on a Ubuntu Desktop 11.04 with kernel 2.6.38-13.
Are you running the program as root?
What are your values of these sysctl parameters? Here are mine from an Ubuntu box. The default is to give real time only 0.95 seconds out of a 1 second slice:
kernel.sched_rt_period_us = 1000000 kernel.sched_rt_runtime_us = 950000
This prevents the real-time domain from taking all the CPU. If you want real real time, you have to disable these parameters.
See: http://www.kernel.org/doc/Documentation/scheduler/sched-rt-group.txt
If you set sched_rt_runtime_us
to -1, you disable this safety mechanism.
这篇关于不能在C ++中引发优先级反转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!