pthreads com prioridade em tempo real
Preciso gerenciar um pool de threads com prioridades diferentes, então escrevi o seguinte procedimento de inicialização do thread:
static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
pthread_attr_t attr;
int err;
struct sched_param param = {
.sched_priority = prio
};
assert(pthread_attr_init(&attr) == 0);
assert(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0);
assert(pthread_attr_setschedparam(&attr, ¶m) == 0);
err = pthread_create(&thrd->handler, &attr, thread_routine, (void *)thrd);
pthread_attr_destroy(&attr);
return err;
}
Em princípio, o usuário não privilegiado não deve executar este código: a chamada pthread_create () deve retornar EPERM devido às implicações de segurança de executar um encadeamento com alta prioridade.
Inesperadamente, ele funciona para o usuário normal, mas não respeita a prioridade dada.
Tentei modificar o código removendo opthread_attr_t
e definindo o atributo de agendamento após a criação do encadeamento:
static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
pthread_attr_t attr;
int err;
struct sched_param param = {
.sched_priority = prio
};
err = pthread_create(&thrd->handler, NULL /*&attr*/, thread_routine,
(void *)thrd);
if (err != 0) return err;
err = pthread_setschedparam(thrd->handler, SCHED_FIFO, ¶m);
if (err != 0) return err;
return err;
}
Essa abordagem, a propósito, é muito mais difícil de gerenciar, pois, em caso de erro, preciso matar o thread recém-criado. Pelo menos, parece funcionar corretamente com relação aos requisitos de permissão (apenas o root pode executar isso), mas ainda as prioridades não são respeitadas.
Estou fazendo algo errado?
EDITAR
Acabei de adicionar o seguinte trecho de código, que é executado por cada thread:
static
void getinfo ()
{
struct sched_param param;
int policy;
sched_getparam(0, ¶m);
DEBUG_FMT("Priority of this process: %d", param.sched_priority);
pthread_getschedparam(pthread_self(), &policy, ¶m);
DEBUG_FMT("Priority of the thread: %d, current policy is: %d and should be %d",
param.sched_priority, policy, SCHED_FIFO);
}
Com o primeiro método (ou seja,pthread_attr_t
abordagem), verifica-se que a política pthread_attr_setschedpolítica não é totalmente efetiva, pois a prioridade é 0 e a política não é SCHED_FIFO.
Com o segundo método (ou seja,pthread_setschedparam
abordagem) a função imprime os dados esperados, mas a execução continua se comportando de maneira errada.