C++ std::promise::在固定到内核的FIFO线程上设置#u值';未来

C++ std::promise::在固定到内核的FIFO线程上设置#u值';未来,c++,linux,c++11,real-time,scheduler,C++,Linux,C++11,Real Time,Scheduler,我试图创建一个具有确定性实时响应的系统 我创建了许多,将所有非关键任务和未固定的内核线程移动到一个集合中,然后将每个实时线程固定到自己的cpuset,每个cpuset由一个cpu组成 $ non-critical tasks and unpinned kernel threads cset proc --move --fromset=root --toset=system cset proc --kthread --fromset=root --toset=system $ realtime

我试图创建一个具有确定性实时响应的系统

我创建了许多,将所有非关键任务和未固定的内核线程移动到一个集合中,然后将每个实时线程固定到自己的cpuset,每个cpuset由一个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
  • 线程2:
    SCHED\u FIFO
    ,固定到
    set2
    ,调用
    std::promise::set\u value()
线程1永远阻塞。 但是,如果我更改线程2,使其成为
SCHED_OTHER
,则线程1可以继续

我运行了一个
strace-f
,以获得更多的洞察力;线程1似乎正在等待一个
futex
(我假设
std::future
的内部代码),但从未被唤醒

我完全被阻碍了——有没有办法让线程将自身固定到核心,并将其调度程序设置为FIFO,然后使用
std::promise
唤醒另一个线程,该线程正在等待它完成所谓的实时设置

thread1创建thread2的代码如下:

// 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:
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
您可以看到pid 17651(thread1)报告
futex已恢复
,但它是否可能在错误的cpu上运行,并在thread2(以
FIFO
运行)后被阻塞

更新:这似乎是一个线程没有在被固定到的CPU上运行的问题。

top-p 17649-H
使用
f,j
调出上次使用的
cpu
显示线程1确实在线程2的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说它在cpu 3上运行

有趣的是,
sched_getaffinity
报告了
cpuset
的功能-thread1在cpu 3上,thread2在cpu 5上

但是,查看
/proc/17649/task
以查找其上运行的每个任务的
最后一个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
输出),但实际上它在cpu 2上运行(在另一个套接字上)

所以我想说,
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

我已经在一个SLES 11/SP 2盒上重新运行了测试,钉扎工作正常


因此,我将把这标记为一个答案,即:这是一个与SP1

相关的问题,我不会对这个主题投反对票,但我真的不确定这是提出这样一个具体问题的地方,因为它涉及的是内核配置而不是用户代码。也许试一试?@ildjarn-谢谢-我会的我在serverfault上提出了一个问题:这里的代码在许多方面与另一个问题上的代码相似:这个问题是由另一个问题“回答”的,还是关于同一个/类似代码中的不同问题的问题?@MichaelBurr-我想你可能是对的,很可能是这样的-我将在承诺中使用
std::move
,并让您知道结果
$ 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