Я собрал ядро Linux с примененным исправлением RT.Он скомпилирован правильно, я вижу набор политик планировщика
CONFIG_PREEMPT_RT_FULL=y
ядро говорит, что это PREEMPT RT:
debian@beaglebone:~$ uname -a
Linux beaglebone 4.14.94-ti-rt-r93 #2 SMP PREEMPT RT Mon Mar 11 12:09:49 MSK 2019 armv7l GNU/Linux
Чтобы проверить это, я использую BeagleBone Black и простой самодельный модуль ядра, который просто порождает2 потока ядра с разными приоритетами.
// ...
struct sched_param paramL = { .sched_priority = MAX_RT_PRIO - 20 };
struct sched_param paramH = { .sched_priority = MAX_RT_PRIO - 10 };
// ...
adev->high_thread = kthread_create(
high_work_thread, adev, "high_pr_thread");
ret = sched_setscheduler(adev->high_thread, SCHED_FIFO, ¶mH);
if (ret) {
dev_warn(&adev->pdev->dev, "High priority rejected!\n");
}
adev->low_thread = kthread_create(
low_work_thread, adev, "low_pr_thread");
ret = sched_setscheduler(adev->low_thread, SCHED_FIFO, ¶mL);
if (ret) {
dev_warn(&adev->pdev->dev, "Low priority rejected!\n");
}
wake_up_process(adev->high_thread);
wake_up_process(adev->low_thread);
Каждый поток переключает свой GPIO.Поток с высоким приоритетом (делает 100000 переключений, затем спит) * 5 раз
/* HIGH PRIO */
int i, j;
struct plng_arinc_device * adev = data;
for(j = 0; j != 5; j++) {
for(i = 0; i != 100000; i++) {
FLIP(high_val);
gpiod_set_value(adev->gpioHIGH, high_val);
}
msleep(15);
}
Поток с низким приоритетом просто непрерывно переключает свой PIN-код 1000000 раз
/* LOW PRIO */
int i;
struct plng_arinc_device * adev = data;
for(i = 0; i != 1000000; i++) {
FLIP(low_val);
gpiod_set_value(adev->gpioLOW, low_val);
}
Теперь, глядя на экран осциллографа, я не наденуНе вижу никакой разницы с непропатченным ядром:
Рис 1
Зеленая нить с высоким приоритетом (HIGH), вытесняется желтой нитью с низким приоритетом (LOW)однажды зеленый спит.Затем LOW работает до завершения ...
Изменение или даже изменение приоритетов ничего не дает.Одной вещью, которая влияет на ситуацию, является последовательность порождения потока.Когда я изменил его, получил это:
wake_up_process(adev->low_thread);
wake_up_process(adev->high_thread);
Рис 2
LOW работает до завершения ДО ВЫСОКОГО
То, что я ожидаю увидеть, это изображениекак это:
Pic 3
На предыдущем изображении LOW установлен в политику SCHED_NORMAL:
// ...
struct sched_param paramL = { .sched_priority = 0 };
struct sched_param paramH = { .sched_priority = MAX_RT_PRIO - 10 };
// ...
ret = sched_setscheduler(adev->high_thread, SCHED_FIFO, ¶mH);
// ...
ret = sched_setscheduler(adev->low_thread, SCHED_NORMAL, ¶mL);
// ...
Я ожидал, что 2 потока SCHED_FIFO ведут себя одинаково
И СЕЙЧАС ВОПРОС: Так как это мой первый опыт работы с исправленным ядром RT, я даже не могу сказать, нормальное ли это поведение или нет.Я ожидаю, что полностью выгружаемое ядро будет ПОЛНОСТЬЮ ПРЕДВАРИТЕЛЬНЫМ - если поток с высоким приоритетом находится в состоянии выполнения - он просто получает процессорное время.То, что я вижу, это просто гонка с приоритетом, НЕ принятым во внимание.
Может быть, я делаю что-то НЕПРАВИЛЬНОЕ?Не пробовал это из пользовательского пространства.
ТОЛЬКО для полной картинки - 2 нити SCHED_NORMAL:
2 нормальных нити
имеют одинаковые интервалы времени.