3

決定論的なリアルタイム応答を備えたシステムを作成しようとしています。

いくつかを作成し、cpusets重要ではないすべてのタスクと固定されていないカーネルスレッドを1つのセットに移動してから、各リアルタイムスレッドをそれぞれが単一のCPUで構成される独自のCPUセットに固定します。

$ non-critical tasks and unpinned kernel threads
cset proc --move --fromset=root --toset=system
cset proc --kthread --fromset=root --toset=system

$ realtime threads
cset proc --move --toset=shield/RealtimeTest1/thread1 --pid=17651
cset proc --move --toset=shield/RealtimeTest1/thread2 --pid=17654

私のシナリオはこれです:

  • スレッド1 SCHED_OTHER:、に固定されset1、待機中std::future<void>
  • スレッド2 SCHED_FIFO:、に固定set2、呼び出しstd::promise<void>::set_value()

スレッド1は永久にブロックします。 ただし、スレッド2を変更するとSCHED_OTHER、スレッド1は続行できます。

strace -f私はより多くの洞察を得るためにを実行しました。スレッド1はfutex(の内部を想定していstd::futureます)を待機しているようですが、ウェイクアップされることはありません。

私は絶対に困惑しています-スレッドピン自体をコアに設定し、そのスケジューラーをFIFOに設定してから、を使用して、std::promiseこのいわゆるリアルタイムセットアップが完了するのを待っている別のスレッドをウェイクアップする方法はありますか?

thread2を作成するthread1のコードは次のとおりです。

// Thread1:
std::promise<void> p;
std::future <void> f = p.get_future();

_thread = std::move(std::thread(std::bind(&Dispatcher::Run, this, std::ref(p))));

LOG_INFO << "waiting for thread2 to start" << std::endl;

if (f.valid())
    f.wait();

また、thread2のRun関数は次のとおりです。

// Thread2:
LOG_INFO << "started: threadId=" << Thread::GetId() << std::endl;

Realtime::Service* rs = Service::Registry::Lookup<Realtime::Service>();
if (rs)
    rs->ConfigureThread(this->Name()); // this does the pinning and FIFO etc

LOG_INFO << "thread2 has started" << std::endl;
p.set_value(); // indicate fact that the thread has started

straceの出力は次のとおりです。

  • スレッド1は[pid 17651]
  • スレッド2は[pid 17654]

簡潔にするために、出力の一部を削除しました。

//////// Thread 1 creates thread 2 and waits on a future ////////

[pid 17654] gettid()                    = 17654
[pid 17651] write(2, "09:29:52 INFO waiting for thread"..., 4309:29:52 INFO waiting for thread2 to start
 <unfinished ...>
[pid 17654] gettid( <unfinished ...>
[pid 17651] <... write resumed> )       = 43
[pid 17654] <... gettid resumed> )      = 17654
[pid 17651] futex(0xd52294, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid 17654] gettid()                    = 17654
[pid 17654] write(2, "09:29:52 INFO thread2 started: t"..., 6109:29:52 INFO thread2  started: threadId=17654
) = 61

//////// <snip> thread2 performs pinning, FIFO, etc </snip> ////////

[pid 17654] write(2, "09:29:52 INFO thread2 has starte"..., 3409:29:52 INFO thread2 has started
) = 34
[pid 17654] futex(0xd52294, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0xd52268, 2) = 1
[pid 17651] <... futex resumed> )       = 0
[pid 17654] futex(0xd522c4, FUTEX_WAKE_PRIVATE, 2147483647 <unfinished ...>
[pid 17651] futex(0xd52268, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
[pid 17654] <... futex resumed> )       = 0
[pid 17651] <... futex resumed> )       = 0

//////// blocks here forever ////////

pid 17651(thread1)が報告していることがわかりますがfutex resumed、間違ったCPUで実行されており、として実行されているthread2の背後でブロックされている可能性がありFIFOますか?

更新:これは、固定されているCPUで実行されていないスレッドの問題のようです。

top -p 17649 -Hを使用f,jして、スレッド1が実際にスレッド2のCPUで実行されlast used cpuていることを示します。

top - 10:00:59 up 18:17,  3 users,  load average: 7.16, 7.61, 4.18
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  7.1%us,  0.1%sy,  0.0%ni, 89.5%id,  0.0%wa,  0.0%hi,  3.3%si,  0.0%st
Mem:   8180892k total,   722800k used,  7458092k free,    43364k buffers
Swap:  8393952k total,        0k used,  8393952k free,   193324k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  P COMMAND                                                                                                                                                                                             
17654 root      -2   0 54080  35m 7064 R  100  0.4   5:00.77 3 RealtimeTest                                                                                                                                                                                         
17649 root      20   0 54080  35m 7064 S    0  0.4   0:00.05 2 RealtimeTest                                                                                                                                                                                         
17651 root      20   0 54080  35m 7064 R    0  0.4   0:00.00 3 RealtimeTest    

ただし、cpusetファイルシステムを見ると、タスクが要求したCPUに固定されていることがわかります。

/cpusets/shield/RealtimeTest1 $ for i in `find -name tasks`; do echo $i; cat $i; echo "------------"; done

./thread1/tasks
17651 
------------
./main/tasks
17649 
------------
./thread2/tasks
17654
------------

cpuset構成の表示:

$ cset set --list -r
cset: 
         Name       CPUs-X    MEMs-X Tasks Subs Path
 ------------ ---------- - ------- - ----- ---- ----------
         root       0-23 y     0-1 y   279    2 /
       system 0,2,4,6,8,10 n       0 n   202    0 /system
       shield 1,3,5,7,9,11 n       1 n     0    2 /shield
RealtimeTest1    1,3,5,7 n       1 n     0    4 /shield/RealtimeTest1
      thread1          3 n       1 n     1    0 /shield/RealtimeTest1/thread1
      thread2          5 n       1 n     1    0 /shield/RealtimeTest1/thread2
         main          1 n       1 n     1    0 /shield/RealtimeTest1/main

このことから、thread2はCPU 5で実行されているはずですが、topはCPU3で実行されていると言います。

興味深いことに、何をするのかをsched_getaffinity報告しますcpuset-thread1はcpu 3にあり、thread2はcpu5にあります。

ただし、実行された各タスク/proc/17649/taskを見つけるために見てみましょう。last_cpu

/proc/17649/task $  for i in `ls -1`; do cat $i/stat | awk '{print $1 " is on " $(NF - 5)}'; done
17649 is on 2
17651 is on 3
17654 is on 3

sched_getaffinity一つのことを報告しますが、現実は別のものです

興味深いことに、mainスレッド[ pid 17649]は(出力によると)CPU 1上にあるはずですcsetが、実際には(別のソケット上にある)CPU2上で実行されています。

だから私はそれが機能しcpusetていないと言うでしょうか?

私のマシン構成は次のとおりです。

$ cat /etc/SuSE-release
SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 1
$ uname -a
Linux foobar 2.6.32.12-0.7-default #1 SMP 2010-05-20 11:14:20 +0200 x86_64 x86_64 x86_64 GNU/Linux
4

1 に答える 1

1

SLES 11 / SP 2ボックスでテストを再実行しましたが、ピン留めは機能します。

そのため、これを回答としてマークします。これは、SP1に関連する問題です。

于 2012-07-16T03:08:50.880 に答える