====== Despachante de tarefas ======
:!: alterações na interface em 03/2023
{{ :so:ppos_03_dispatcher.mkv |Vídeo deste projeto}}
Você irá construir um despachante de tarefas baseado em duas entidades: uma tarefa //dispatcher//, responsável pelo controle geral, e uma função //scheduler//, responsável por determinar qual a próxima tarefa a executar a cada troca de contexto. A figura abaixo ilustra o funcionamento geral do sistema:
{{ dispatcher.png?700 |}}
A seguinte chamada para a execução da tarefa atual e retorna ao //dispatcher//:
void task_yield () ;
O que deve fazer essa função:
- coloca a tarefa atual no fim da fila de prontas
- muda o estado da tarefa atual para ''PRONTA''
- devolve a CPU ao despachante
Sugestão: use a função ''task_switch()'' para implementar ''task_yield()''.
===== Observações =====
* O //dispatcher// deve ser implementado como uma tarefa, a ser iniciada usando a chamada ''task_init'' durante a inicialização do sistema (execução de ''ppos_init'').
* O programa principal inicia todas as tarefas de usuário e passa o controle para a tarefa //dispatcher//, que só encerra quando não existirem mais tarefas de usuário a executar.
* Será necessário implementar uma fila de tarefas prontas, usando a biblioteca de filas genéricas desenvolvida anteriormente.
* A **política de escalonamento** será definida por uma função ''scheduler()'', chamada pelo //dispatcher// para decidir qual a próxima tarefa a ativar. Neste projeto, deve ser implementada uma política FCFS.
* Quando uma tarefa encerrar, o controle volta ao //dispatcher// e este libera as estruturas de dados alocadas para a tarefa.
* quando o //dispatcher// encerrar, a chamada ''task_exit'' deve encerrar o programa chamando ''exit''.
O código do corpo da tarefa //dispatcher// deve seguir +/- o seguinte modelo (simplificado):
função dispatcher
início
// retira o dispatcher da fila de prontas, para evitar que ele ative a si próprio
queue_remove (...)
// enquanto houverem tarefas de usuário
enquanto ( userTasks > 0 )
// escolhe a próxima tarefa a executar
próxima = scheduler ()
// escalonador escolheu uma tarefa?
se próxima ≠ NULO então
// transfere controle para a próxima tarefa
task_switch (próxima)
// voltando ao dispatcher, trata a tarefa de acordo com seu estado
caso o estado da tarefa "próxima" seja:
PRONTA : ...
TERMINADA : ...
SUSPENSA : ...
(etc)
fim caso
fim se
fim enquanto
// encerra a tarefa dispatcher
task_exit(0)
fim
Sua implementação deve funcionar com {{pingpong-dispatcher.c|este código}}. A saída da execução deve ser igual a {{pingpong-dispatcher.txt|este exemplo}}.
===== Outras informações =====
* Duração estimada: 5 horas.
* Dependências:
* [[Biblioteca de Filas]]
* [[Gestão de Tarefas]]