不能在C ++中引发优先级反转 [英] Can't provoke Priority Inversion in C++

查看:180
本文介绍了不能在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_pa​​ram 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。


  • p>这些sysctl参数的值是什么?这是我从一个Ubuntu框。默认值是在1秒的切片中只提供0.95秒的实时时间:

      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, &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);
    
      // 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.

    解决方案

    1. Are you running the program as root?

    2. 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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆