3

デモンストレーションの目的で小さな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 のようなスケジューラでは、実行中の状態のリアルタイム スレッド (SCHED_FIFO または SCHED_RR) がなくなるまで、非リアルタイム スレッド (SCHED_OTHER) は実行されません。しかし、私はこのスレッドを同時に実行することを達成しました:

  • (L) ミューテックスをロックし、CPU を消費する 1 つの非リアルタイム (SCHED_OTHER) スレッド
  • (M) 複数のリアルタイム スレッド (SCHED_FIFO 、および優先順位 > 0) CPU を集中的に使用し、mutex のロックを待機していない
  • (H) 1 つのリアルタイム スレッド (SCHED_FIFO 、および最高の優先度) がロックを待機中

私のシステムのCPUの量よりも多くのリアルタイムCPU集中スレッド(M)が実行されています...しかし、ロックを保持している非リアルタイムスレッド(L)はまだCPUを消費しており、作業を終了し、ミューテックスを解放します「M」スレッドが CPU の消費を終了します。

優先度の低いスレッドがプリエンプトされず、アプリケーションがデッドロックされ、優先度の逆転が得られないのはなぜですか?

カーネル 2.6.38-13 を搭載した Ubuntu デスクトップ 11.04 で g++ 4.5.2 を使用しています。

4

3 に答える 3

5

Re:デモンストレーションの目的で小さな C++ プログラムで優先順位の逆転を引き起こそうとしていますが、できません: ミューテックスを保持する優先順位の低いスレッドは横取りされず、実行を続けます ...

これ優先順位逆転シナリオの始まりです。優先度の低いスレッドは、優先度の高いスレッドがブロックする排他的なリソース (mutex など) を取得します。

優先度の逆転の結果を適切に表示するには、たとえば、低 (L)、中 (M)、および高 (H) の優先度のスレッドの 3 つのスレッドが必要です。

L は、H が競合するミューテックスをロックします。つまり、L は実行されていますが、H は実行されていません。これはすでに悪いことです。重要なスレッド H が、重要度の低いスレッド L が何かをするのを待っています。

M は実行可能になり、計算集約型になります。M はミューテックスを気にしません。H や L とは関係ありません。ただし、M は L よりも優先度が高く、L を CPU から追い出します。

そのため、M は引き続き実行され、L の実行が妨げられます。これにより、L がミューテックスを解放するコード行に到達できなくなり、H がミューテックスを取得できなくなります。

そのため、優先度が最も高いスレッド H の代わりに、優先度が中間のスレッド M が実行されています。

L をブロックすることにより、M は H もブロックできます: 反転。

このように正確にコーディングできるかどうかを確認してください。

于 2012-03-20T00:20:44.673 に答える
3
  1. プログラムをルートとして実行していますか?

  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

-1 に設定sched_rt_runtime_usすると、この安全メカニズムが無効になります。

于 2012-03-20T16:04:53.307 に答える
1

最新のほとんどのスケジューラには、検出された場合、または適切であると見なされた場合に、デッドロックにつながる優先順位の逆転を防ぐために、1 つか 2 つのタイム スライスの優先順位を変更するアンチ デッドロック セーフガードがあります。Linux で使用しているスケジューラーを Linux で使用できるかどうかは、よくわかりません。ただし、まだ行っていない場合は、このことに注意してください。

于 2012-03-20T15:19:53.443 に答える