Планирование pthread FIFO не строго определено c? - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь заставить этот поток всегда работать на одном ядре процессора (из 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 во многих потоках с низким приоритетом исчисляется тысячами или десятками тысяч. Похоже, это указывает на то, что поток с высоким приоритетом в реальном времени почему-то не всегда работает (пока выполняется процесс). Или я что-то упустил? Полная программа в х. cc здесь: https://github.com/ywkaras/MiscRepo/tree/master/TWATCH. (Я запускаю программу как root.)

Ответы [ 2 ]

3 голосов
/ 24 апреля 2020

Это, кажется, указывает на то, что поток с высоким приоритетом в реальном времени почему-то не всегда работает

Ваш вывод не следует из наблюдаемых фактов.

Вкл Linix, при достижении точки останова в потоке SCHED_FIFO этот поток больше не работает, но все остальные потоки работают и продолжают работать. (Примечание: другие ОС останавливают все потоки, когда любой поток достигает точки останова, но Linux нет.)

Поскольку поток FIFO отлаживается, ядро ​​(в конце концов) уведомляет GDB (через waitpid). возврат), что этот поток остановлен (другие потоки продолжают работать).

Когда GDB замечает, что поток FIFO остановлен, он останавливает все другие потоки (только в режиме all-stop) и, наконец, выдает приглашение обратно. Только в этот момент вы можете проверить значение i во всех потоках.

Хотя время между пробуждением и остановкой всех потоков GDB довольно короткое (обычно миллисекунды), это не должно удивлять что другим потокам удалось увеличить переменную на 10 с тысяч раз.


0 голосов
/ 25 апреля 2020

Похоже, что да, планирование FIFO является детерминированным c. Я сделал два предположения, задавая этот вопрос, одно или оба из которых неверны:

  1. Архитектура x86_64 позволяет устанавливать точку останова выполнения, при которой одно ядро ​​переходит на ISR, а все остальные ядра чтобы приостановить выполнение.
  2. GDB для 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;
}

(пересмотренная программа в х. cc в https://github.com/ywkaras/MiscRepo/tree/master/TWATCH2.)

Наибольшее выходное значение для i в любом потоке с низким приоритетом было 13.

Одна вещь, которую я до сих пор не понимаю, это то, что, если я увеличу количество потоков с низким приоритетом до гораздо более 10 , программа никогда не завершится.

(Я пытался удалить вопрос, но получил ответ, что лучше не удалять вопросы с ответами.)

...