Я собираю полупрозрачный класс потоков Unix/Linux (т. Е. Используя библиотеку pthread) для проекта, над которым я работаю. Часть проекта требует возможности установить приоритет определенных потоков, чтобы другие потоки в одном процессе увеличивали время процессора; в который входит функция pthread_setschedparam
, и мой класс попадает в кирпичную стену.portable pthread_setschedparam с SCHED_OTHER
Ниже приведен простой тест, который я поставил вместе, чтобы проиллюстрировать мою проблему:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include <string.h>
#include <errno.h>
pthread_mutex_t m_mtx;
bool m_goahead;
void dosleep(int millis)
{
usleep(millis*1000);
}
void domsg(const char *msg)
{
pthread_mutex_lock(&m_mtx);
std::cout << msg << std::endl;
pthread_mutex_unlock(&m_mtx);
}
void dowait() {
while (!m_goahead) {
dosleep(1);
}
}
void *fn1(void *param)
{
domsg("in fn1...waiting");
dowait();
while (m_goahead) {
dosleep(1000);
domsg("in fn1 loop");
}
}
void *fn2(void *param)
{
domsg("in fn2...waiting");
dowait();
while (m_goahead) {
dosleep(1000);
domsg("in fn2 loop");
}
}
int main(int argc, char **argv)
{
// min prio = -2, max prio = 2
int t1_pri = 2, t2_pri = 0, main_pri = 1;
//SCHED_RR, SCHED_FIFO, SCHED_OTHER (POSIX scheduling policies)
int sched = SCHED_OTHER; // standard
// get the range between min and max and set the priorities base on split range
int min = sched_get_priority_min(sched);
int max = sched_get_priority_max(sched);
int skip = (max - min)/5; // 5 since -2...2
struct sched_param main_param, t1_param, t2_param;
memset(&main_param, 0, sizeof(sched_param));
memset(&t1_param, 0, sizeof(sched_param));
memset(&t2_param, 0, sizeof(sched_param));
main_param.sched_priority = (min + ((main_pri+2) * (skip+1))) + (skip/2);
t1_param.sched_priority = (min + ((t1_pri+2) * (skip+1))) + (skip/2);
t2_param.sched_priority = (min + ((t2_pri+2) * (skip+1))) + (skip/2);
std::cout << "main thread will have a prio of " << main_param.sched_priority << std::endl;
std::cout << "t1 thread will have a prio of " << t1_param.sched_priority << std::endl;
std::cout << "t2 thread will have a prio of " << t2_param.sched_priority << std::endl;
m_goahead = false;
pthread_mutex_init(&m_mtx, NULL);
pthread_t t1, t2;
// Create the threads
if (pthread_create(&t1, NULL, fn1, NULL) != 0) {
std::cout << "couldn't create t1" << std::endl;
return -1;
}
if (pthread_create(&t2, NULL, fn2, NULL) != 0) {
std::cout << "couldn't create t2" << std::endl;
return -1;
}
dosleep(1000); // sleep a second before setting priorities
// --main thread--
if (pthread_setschedparam(pthread_self(), sched, &main_param) != 0) {
std::cout << "error setting priority for main thread: (" << errno << "), " << strerror(errno) << std::endl;
}
// --t1 thread--
if (pthread_setschedparam(t1, sched, &t1_param) != 0) {
std::cout << "error setting priority for T1: (" << errno << "), " << strerror(errno) << std::endl;
}
// --t2 thread--
if (pthread_setschedparam(t2, sched, &t2_param) != 0) {
std::cout << "error setting priority for T2: (" << errno << "), " << strerror(errno) << std::endl;
}
m_goahead = true; // all start
// loop until user interupt
for (;;) {
dosleep(1000);
domsg("in main loop");
}
pthread_mutex_destroy(&m_mtx);
return 0;
}
Base на этот код, если я компилирую это и запустить его на системе OpenBSD, я получаю следующее:
main thread will have a prio of 24
t1 thread will have a prio of 31
t2 thread will have a prio of 17
in fn1...waiting
in fn2...waiting
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
Обратите внимание, как он идет в порядке приоритета нити, fn1, главный, fn2 ...
Если я запускаю этот же тест на системе Ubuntu 10.04LTS, я получаю следующее:
main thread will have a prio of 3
t1 thread will have a prio of 4
t2 thread will have a prio of 2
in fn1...waiting
in fn2...waiting
error setting priority for main thread: (22), Invalid argument
error setting priority for T1: (22), Invalid argument
error setting priority for T2: (22), Invalid argument
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
Я понимаю, что неверный аргумент, потому что я указать класс приоритета в SCHED_OTHER
и пытается присвоить ему любое число, отличное от 0; что я не могу понять, как я могу сделать эту работу должным образом?
Я попытался «принять» SCHED_FIFO
или SCHED_RR
класс приоритета, чтобы получить значения min/max, которые дают мне действительные минимальные/максимальные значения, и я не получаю ошибку «недопустимый аргумент», но цикл функции вывод не находится в приоритетном порядке, вместо этого в любом порядке функция вызвана вызовом (ожидается, если не будет установлен приоритет).
В идеале я бы получил класс приоритетов текущего процесса, а затем назначил поток на этом классе, однако, если приоритет текущего процесса равен SCHED_OTHER
, тогда установите поток на основе того, что создает недопустимые результаты, которые я не хочу ,
Есть ли более «портативный» способ установить приоритет потока или получить допустимые значения min/max? Могу ли я установить приоритет потока под SCHED_OTHER
в определенных средах или эта функциональность оставлена в указанной среде?
Я нахожусь в тупике с этой проблемой и буду признателен за любые прозрения или указатели в правильном направлении.
Спасибо и, пожалуйста, дайте мне знать, если мой код/объяснение неясно.
Спасибо за информацию! К сожалению использование 'nice' действует только на процессы, а не на потоки, но из того, что я могу видеть в разных источниках ядра, приоритеты потоков - ОЧЕНЬ зависящие от системы; OpenBSD реализует абсолютный минимальный стандарт POSIX, но имеет более надежный планировщик потоков, в то время как Ubuntu реализует некоторые непереносимые идиомы POSIX и имеет более простой диспетчер потоков, где Solaris реализует политику 'SCHED_OTHER'. Я все еще охочусь за этим. – txtechhelp