====== 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]]