【问题标题】:Is pthread FIFO scheduling not strictly deterministic?pthread FIFO调度不是严格确定的吗?
【发布时间】:2020-08-08 10:26:47
【问题描述】:

我试图让这个线程在它所在的进程运行时始终在一个 CPU 核心(共 24 个)上运行:

void *t_mon_func(void *)
{
  while (true) {
    if (f) {
      break_on();
    }
  }
  return nullptr;
}

我将其配置为 SCHED_FIFO 调度和最大优先级。我有 50 个其他线程正在使用这个线程函数运行(默认优先级):

void *tfunc(void *)
{
  std::atomic<unsigned> i = 0;
  while (true) {
    if (f) {
      ++i;
    }
  }
  return nullptr;
}

在 gdb 中,我在 break_on 函数上设置断点,继续执行程序,然后触发该程序以将 f(全局变量)的值更改为非零值(通过来自较低优先级的线程)。当断点被击中时,许多低优先级线程中i的值在数千或数万之间。这似乎表明实时的高优先级线程并不总是在运行(在进程运行时)。还是我错过了什么?完整的程序在 x.cc 中:https://github.com/ywkaras/MiscRepo/tree/master/TWATCH。 (我以 root 身份运行程序。)

【问题讨论】:

  • 高优先级 != 实时 != 始终运行
  • 纯断言!=有用
  • 我不认为您的测试测试您认为它测试的内容,因为它基于启动和停止事物,而不是在稳态条件下运行的事物。平台可能会以某种特定的顺序启动和停止某些事情,从而使某些事情在流程中的各个点运行而其他事情不运行。
  • @WaltK 我认为问题在于您自己的声明"...the real-time, high-priorty thread is somehow not always running..." 似乎等同于高优先级和实时的概念。操作系统内核交换线程的原因有很多。您似乎假设将 atomic int f 设置为非零值将作为交换高优先级线程的信号——事实并非如此。
  • 是的,我希望有人比“任何数量的原因”更具体地知道。在具有确定性调度的实时操作系统中,一个比任何其他线程具有更高优先级的可运行线程始终在运行,除非我认为所有内核上都运行着 ISR。我不明白为什么我的程序中的高优先级线程永远无法运行,它没有系统调用。

标签: c++ multithreading gdb pthreads rhel


【解决方案1】:

这似乎表明实时的高优先级线程并不总是在运行

您的结论并非来自观察到的事实。

在 Linix 上,当在 SCHED_FIFO 线程中遇到断点时,该线程不再可运行,但所有其他线程都可以运行,因此继续运行。 (注意:当任何线程遇到断点时,其他操作系统会停止所有线程,但 Linux 不会。)

由于 FIFO 线程正在调试,内核(最终)通知 GDB(通过waitpid return)该线程已停止(其他线程继续运行)。

当 GDB 注意到 FIFO 线程已经停止时,它会停止所有其他线程(仅在all-stop 模式下),最后给出提示。只有在那一刻,您才能在所有线程中检查i 的值。

虽然 GDB 唤醒和停止所有线程之间的时间很短(通常是几毫秒),但其他线程设法将变量增加 10 万倍也就不足为奇了。


【讨论】:

  • 嗯,但是当我将 show non-stop 添加到 gdb 脚本时,输出为 Controlling the inferior in non-stop mode is off.
  • @WaltK non-stop mode is off 等价于all-stop mode。所以没什么新意?在不间断模式下,其他线程将继续运行,增加i 更多。
  • 那么 x86 架构是否缺乏配置执行断点的能力,该断点会暂停所有内核并只允许单个内核执行关联的 ISR?
  • @WaltK 我不知道,但你正在混合完全不相关的东西。用户空间附近没有ISRs(这是您的程序运行的地方)。
  • @ Employed Russian 我认为断点会导致至少对于命中断点(并进入 ISR)的内核切换到内核上下文。
【解决方案2】:

看来,是的,pthread FIFO 调度是确定性的。我在问这个问题时做了两个假设,其中一个或两个都是错误的:

  1. x86_64 架构允许设置执行断点,导致一个内核跳转到 ISR,而所有其他内核暂停执行。
  2. GDB for x86_64 使用这种功能来执行断点。

我将低优先级线程的函数更改为:

void *tfunc(void *)
{
  std::atomic<unsigned> i = 0;

  while (!flag) {
    ;
  }
  while (run) {
    ++i;
  }

  if (i) {
    std::cout << i << std::endl;
  }

  return nullptr;
}

高优先级线程的函数为:

void *t_mon_func(void *)
{
  while (!flag) {
    ;
  }
  run = 0;
  flag = 0;

  return nullptr;
}

(修改后的程序在x.cc中https://github.com/ywkaras/MiscRepo/tree/master/TWATCH2。)

i 在任何低优先级线程中的最大输出值为 13。

有一件事我还是不明白,如果我将低优先级线程的数量增加到超过 10 个,程序将永远不会退出。

(我试图删除问题,但收到回复说最好不要删除有答案的问题。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 2014-09-18
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多