Threads de Planejamento

Threads podem ser agendadas e a biblioteca de threads fornece várias instalações para manipular e controlar o planejamento de threads.

Ele também fornece instalações para controlar o planejamento de threads durante operações de sincronização, como bloquear um mutex. Cada thread tem seu próprio conjunto de parâmetros de agendamento. Esses parâmetros podem ser configurados usando o objeto atributos thread antes que a thread seja criada. Os parâmetros também podem ser configurados dinamicamente durante a execução da thread.

Controlar o agendamento de um encadeamento pode ser uma tarefa complicada. Como o planejador trata de todas as threads de largura, os parâmetros de planejamento de uma thread interagem com aqueles de todos os outros threads no processo e nos demais processos. As instalações a seguir são as primeiras a serem usadas se você quiser controlar o planejamento de um encadeamento.

A biblioteca de threads permite que o programador controle o agendamento de execução das threads das seguintes formas:
  • Por configurar atributos de planejamento ao criar um encadeamento
  • Alterando dinamicamente os atributos de planejamento de um encadeamento criado
  • Ao definir o efeito de um mutex no planejamento da thread ao criar um mutex (conhecido como agendamento de sincronização)
  • Alterando dinamicamente o planejamento de uma thread durante as operações de sincronização (conhecido como agendamento de sincronização)

Parâmetros de agendamento

Uma thread tem os seguintes parâmetros de planejamento:

Parâmetro Descrição
escopo O escopo de contenção de uma thread é definido pelo modelo de encadeamento usado na biblioteca threads.
política A política de planejamento de uma thread define como o planejador trata a thread após ele ganhar o controle da CPU.
prioridade A prioridade de planejamento de um encadeamento define a importância relativa do trabalho que está sendo feito por cada thread.

Os parâmetros de agendamento podem ser configurados antes da criação da thread ou durante a execução da thread. Em geral, controlar os parâmetros de planejamento de threads é importante apenas para threads que são intensivas em CPU. Assim, a biblioteca de threads fornece valores padrão que são suficientes para a maioria dos casos.

Usando o atributo heritsched

O atributo ineritsched do objeto atributos thread especifica como os atributos de agendamento do encadeamento serão definidos. Os valores válidos são os seguintes:

Valores Descrição
PTHREAD_HERIT_SCHED Especifica que o novo encadeamento obterá os atributos de planejamento (programpolicy e programparam atributos) de sua thread de criação. Os atributos de planejamento definidos no objeto atributos são ignorados.
PTHREAD_EXPLICIT_SCHED Especifica que o novo encadeamento obterá os atributos de agendamento definidos neste objeto de atributos.

O valor padrão do atributo ineritsched é PTHREAD_INHERIT_SCHED. O atributo é configurado chamando a subroutine pthread_attr_setinheritsched . O valor atual do atributo é retornado chamando a subroutina pthread_attr_getinheritsched .

Para configurar os atributos de planejamento de uma thread no objeto de atributos thread, o atributo ineritsched deve primeiro ser configurado como PTHREAD_EXPLICIT_SCHED. Caso contrário, os atributos de agendamento de objetos são ignorados.

Política de agendamento e prioridade

A biblioteca threads fornece as seguintes políticas de planejamento:

Biblioteca Descrição
SCHED_FIFO Agendamento de primeiro em primeiro lugar (FIFO). Cada thread tem uma prioridade fixa; quando várias threads têm o mesmo nível de prioridade, elas correm para a conclusão na ordem FIFO.
SCHED_RR Agendamento de Round-robin (RR). Cada thread tem uma prioridade fixa; quando várias threads têm o mesmo nível de prioridade, elas são executadas para uma fatia de tempo fixa na ordem FIFO.
SCHED_OUTROS Agendamento padrão AIX. Cada thread tem uma prioridade inicial que é modificada dinamicamente pelo planejador, de acordo com a atividade do encadeamento; a execução de encadeamento é tempo-fatiado. Em outros sistemas, essa política de planejamento pode ser diferente.

Em versões do AIX anteriores a 5.3, a mudança da prioridade de um encadeamento ao configurar sua política de planejamento para SCHED_OTHER não é permitida Neste caso, o kernel gerencia diretamente a prioridade, e o único valor legal que pode ser passado para a subroutine pthread_setprogramparam é o valor DEFAULT_PRIO . O valor DEFAULT_PRIO é definido no arquivo pthread.h como 1 e quaisquer outros valores transmitidos são ignorados.

Começando com AIX 5.3, é possível alterar a prioridade de um encadeamento ao configurar sua política de planejamento para SCHED_OTHER. Os valores legais que podem ser passados para o subroutine pthread_setprogramparam são de 40 80, no entanto, apenas usuários privilegiados podem estabelecer uma prioridade maior que 60. Uma prioridade na faixa de 1 39 fornece a mesma prioridade que a de 40, sendo que uma prioridade na faixa de 81 a 127 fornece a mesma prioridade que a de 80.

Nota: Em AIX, o kernel inverte os níveis de prioridade. Para o kernel AIX , a prioridade está na faixa de 0 127, sendo que 0 é a prioridade mais favorecida e 127 a prioridade menos favorecida. Comandos, como o comando ps , relataam a prioridade do kernel.
A biblioteca de encadeamentos manipula a prioridade através de uma estrutura sched_param , definida no arquivo de cabeçalho sys/sched.h . Esta estrutura contém os seguintes campos:
Campos Descrição
sched_priority Especifica a prioridade.
sched_policy Este campo é ignorado pela biblioteca threads. Não use.

Configurando a política de planejamento e prioridade no momento da criação

A política de agendamento pode ser definida ao criar uma thread configurando o atributo agendpolicy do objeto thread atributos. A subroutine pthread_attr_setprogrampolicy configura a política de planejamento para uma das políticas de planejamento previamente definidas. O valor atual do atributo agendpolicy de um objeto de atributos thread pode ser obtido usando a subroutine pthread_attr_getprogrampolicy .

A prioridade de planejamento pode ser definida no tempo de criação de uma thread, configurando o atributo programparam do objeto atributos thread. O subroutine pthread_attr_setprogramparam configura o valor do atributo planejparam , copiando o valor da estrutura especificada. A subroutine pthread_attr_getplanejparam obtém o atributo programparam .

No fragmento de código a seguir, é criado um encadeamento com a política de planejamento de round-robin, utilizando um nível prioritário de 3:
sched_param schedparam;

schedparam.sched_priority = 3;

pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, &schedparam);

pthread_create(&thread, &attr, &start_routine, &args);
pthread_attr_destroy(&attr);
Para obter mais informações sobre o atributo ineritsched , consulte Usando o atributo heritsched.

Configurando os atributos de agendamento no tempo de execução

O subroutine pthread_getplanejparam retorna os atributos programpolicy e programparam de um thread. Estes atributos podem ser configurados chamando a subroutinha pthread_setprogramparam . Se o encadeamento de destino estiver atualmente em execução em um processador, a nova política de planejamento e prioridade será implementada na próxima vez que o encadeamento for agendado. Se o encadeamento de destino não estiver em execução, ele poderá ser agendado imediatamente no final da chamada subroutine.

Por exemplo, considere um thread T que está rodando atualmente com a política round-robin no momento em que o atributo agendpolicy de T é alterado para FIFO. T correrá até o final de sua fatia de tempo, no momento em que seus atributos de planejamento são então reavaliados. Se nenhuma thread tiver prioridade maior, T será reescalonado, mesmo antes de outras threads terem a mesma prioridade. Considere um segundo exemplo onde um fio de baixa prioridade não está em execução. Se essa prioridade da thread for levantada por outro encadeamento chamando a subroutine pthread_setprogramparam , o encadeamento de destino será agendado imediatamente se for o fio runnable mais alto de prioridade.

Nota: Ambas as subroutines usam um parâmetro policy e uma estrutura program_param . Embora esta estrutura contenha umasched_policycampo, os programas não devem utilizá-lo. As subroutines usam o parâmetro policy para passar a política de agendamento, e as subroutines então ignoram osched_policy.

Considerações de agendamento de políticas

Os aplicativos devem utilizar a política de planejamento padrão, a menos que um aplicativo específico necessite do uso de uma política de planejamento de prioridade fixa. Considere os seguintes pontos sobre o uso das políticas não padrão:
  • O uso da política round-robin garante que todas as threads tendo o mesmo nível de prioridade serão agendadas igualmente, independentemente de sua atividade. Isso pode ser útil em programas em que threads devem ler sensores ou escrever atuadores.
  • Usar a política FIFO deve ser feito com muito cuidado. Uma thread rodando com a política FIFO corre até a conclusão, a menos que seja bloqueada por algumas chamadas, como realizar operações de entrada e saída. Um encadeamento FIFO de alta prioridade pode não ser preemptado e pode afetar o desempenho global do sistema. Por exemplo, threads fazendo cálculos intensivos, como inverter uma grande matriz, nunca deve executar com a política FIFO.

A configuração de política de planejamento e prioridade também é influenciada pelo escopo de contenção de threads. Utilizar o FIFO ou a política de round-robin pode nem sempre ser permitido.

program_yield subroutine

O subroutine program_yield é o equivalente para threads do subroutine yield . A subroutine program_yield força a thread de chamada a abdicar do uso de seu processador e dá a outros threads uma oportunidade de ser agendada. O próximo encadeamento programado pode pertencer ao mesmo processo que o encadeamento de chamada ou para outro processo. Não use o subroutine yield em um programa multiencadeado.

A sub-rotina da interface pthread_yield não está disponível na especificação Single UNIX, versão 2.