2012-03-19 46 views
3

優先級反轉我試圖挑起優先級反轉上演示的目的一個小C++程序但我不能:持有互斥不搶佔低優先級線程並繼續在關鍵部分運行。這是我在做什麼:不能挑起C++

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

...但它不工作,我不能有我想要的優先倒置。

這是發生了什麼:

據我瞭解,有喜歡的Linux的CFS一個scheduller,非實時線程(SCHED_OTHER)將不會運行,直到沒有任何實時線程(SCHED_FIFO或SCHED_RR)在奔跑狀態。但我已經達到了這個線程同時運行:

  • (L)一個非實時(SCHED_OTHER)線程鎖定互斥體和 消耗CPU
  • (M)幾個實時線程(SCHED_FIFO,&優先> 0)CPU 密集型和非等待鎖定互斥
  • (H)一個實時線程(SCHED_FIFO,&最高優先級)等待 的鎖

還有更多的實時CPU密集線程(M)運行的比我的系統的CPU數量更多......但非實時線程持有(L)鎖仍然佔用CPU並完成它的工作並釋放互斥鎖之前「M」線程完成消耗CPU。

爲什麼低優先級的線程不被搶佔,應用程序是否被鎖定,我無法獲得優先級反轉?

我在內核2.6.38-13的Ubuntu Desktop 11.04上使用g ++ 4.5.2。

+0

請顯示the_start_routine的所有代碼。我看不出它在鎖定和解鎖之間做了什麼。也在關鍵部分之外 - 大概有一個循環在某處變成了點?如果它在CS內部,爲什麼它會被搶佔 - 這是唯一準備好/正在運行的線程,因爲所有其他線程都停留在互斥鎖上。 – 2012-03-19 23:22:25

+0

接下來的回答(無論是否)大多數現代調度程序都具有反死鎖保護措施,可以在一個或多個時間片段中改變優先級,以防止優先級反轉導致死鎖,當檢測到或被認爲合適時。無論您使用的是哪種調度程序,Linux都無法確定。但是,如果你還沒有,請注意這一點。 – 2012-03-20 15:17:51

+0

嗨@天使,你爲什麼設置PTHREAD_PRIO_NONE而不是PTHREAD_PRIO_INHERIT? – ransh 2015-10-03 20:20:34

回答

3
  1. 你是否以root身份運行程序?

  2. 這些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,禁用該安全機制。

+0

真的非常感謝你,Jeremy Collake和Kaz。我想知道是否會發生這樣的事情。我已經能夠使用非RT線程來完成一些CPU週期,而運行更多的RealTime線程比我擁有的核心數量更多。這可能只是一些這樣的機制,但我甚至不知道從哪裏開始尋找它。你統治!非常感謝!!! ;) – Angel 2012-03-21 07:41:37

+2

再次嗨!在原來的文章中還有其他錯誤:我沒有調用pthread_attr_setinheritsched來設置PTHREAD_EXPLICIT_SCHED,它對於它的生效至關重要。我在/etc/sysctl.conf上用「kernel.sched_rt_runtime_us = -1」測試了它,並且我有了我期望的Inversion of Priority,今天我會睡得更開心;)再次感謝大家。 /天使 – Angel 2012-03-22 21:34:30

5

回覆:我試圖挑起用於演示的一個小C++程序的優先級反轉,但我不能:持有互斥量不被搶佔,並保持運行的低優先級線程...

優先級反轉場景的開始。低優先級線程獲取高優先級線程阻塞的獨佔資源(例如互斥體)。要正確顯示優先級反轉的結果,例如,需要三個線程:低(L),中(M)和高(H)優先級線程。

L鎖定H爲其爭奪的互斥鎖。所以L在跑,H不在。這已經很糟糕了:重要的線程H正在等待較不重要的線程L做些事情。

現在M變成可運行的並且是計算密集型的。 M不關心互斥;它與H或L無關。但M比L具有更高的優先級並將L踢出CPU。

所以現在M繼續執行,阻止L運行。這可以防止L到達釋放互斥鎖的代碼行,並阻止H獲取互斥鎖。

所以中間優先級的線程M的,而不是運行在最高優先級的線程H.

的通過阻斷L,M能夠H座也:反轉。

看看你是否可以像這樣編寫代碼。

+0

你可以看到各種算法如何處理這個問題。例如繼承權:當H想要互斥體時,當前互斥體所有者被給予臨時優先級提升,以至於它至少等於H.這導致M不能搶佔L. – Kaz 2012-03-20 00:22:06

+0

我已經更新了問題,源代碼是「近似」的。總結是:我不能讓Real Time(M)線程搶佔(L)非實時線程,它們只是增加負載......最後,互斥鎖(L)被正常釋放,並且(H)最終可以鎖定互斥體。任何幫助將非常感激。最好的祝福! – Angel 2012-03-20 11:07:40

1

大多數現代調度程序都具有反死鎖保護功能,可以在某個時間片或兩個時間片中更改優先級,以防止在檢測到或被認爲適當時導致死鎖的優先級反轉。無論您使用的是哪種調度程序,Linux都無法確定。但是,如果你還沒有,請注意這一點。