====== Construção de semáforos ======
{{ :so:ppos_10_semaforos.mkv |Video deste projeto}}
O objetivo deste projeto é implementar **semáforos clássicos** em nosso sistema. As funções a implementar são descritas na sequência.
==== Cria um semáforo ====
int sem_init (semaphore_t *s, int value)
Inicializa um semáforo apontado por ''s'' com o valor inicial ''value'' e uma fila vazia. O tipo ''semaphore_t'' deve ser definido no arquivo ''pos_data.h''.
A chamada retorna 0 em caso de sucesso ou -1 em caso de erro.
==== Requisita um semáforo ====
int sem_down (semaphore_t *s)
Realiza a operação //Down// no semáforo apontado por ''s''. Esta chamada **pode ser bloqueante**: caso o contador do semáforo seja negativo, a tarefa corrente é suspensa, inserida no final da fila do semáforo e a execução volta ao //dispatcher//; caso contrário, a tarefa continua a executar sem ser suspensa.
Se a tarefa for bloqueada, ela será reativada quando uma outra tarefa liberar o semáforo (através da operação ''sem_up'') ou caso o semáforo seja destruído (operação ''sem_destroy'').
A chamada retorna 0 em caso de sucesso ou -1 em caso de erro (semáforo não existe ou foi destruído).
==== Libera um semáforo ====
int sem_up (semaphore_t *s)
Realiza a operação //Up// no semáforo apontado por ''s''. Esta chamada **não é bloqueante** (a tarefa que a executa não perde o processador). Se houverem tarefas aguardando na fila do semáforo, a primeira da fila deve ser acordada e retornar à fila de tarefas prontas.
A chamada retorna 0 em caso de sucesso ou -1 em caso de erro (semáforo não existe ou foi destruído).
==== Destrói um semáforo ====
int sem_destroy (semaphore_t *s)
Destrói o semáforo apontado por ''s'', acordando todas as tarefas que aguardavam por ele.
A chamada retorna 0 em caso de sucesso ou -1 em caso de erro.
As tarefas que estavam suspensas aguardando o semáforo que foi destruído devem ser acordadas e retornar da operação //Down// correspondente com um código de erro (valor de retorno -1).
===== Condições de disputa =====
Caso duas //threads// tentem acessar o mesmo semáforo simultaneamente, podem ocorrer **condições de disputa** nas variáveis internas dos semáforos. Por isso, as funções que implementam os semáforos devem ser protegidas usando um mecanismo de **exclusão mútua**.
Como obviamente não podemos usar semáforos para resolver esse problema m(, deve ser usado um mecanismo mais primitivo, baseado em espera ocupada. Para tal, Sugere-se usar [[so:exclusao_mutua#operações atômicas]].
===== Observações: =====
* O arquivo ''ppos_data.h'' contém os tipos de dados (incompletos) e o arquivo ''ppos.h'' os protótipos das funções a serem implementadas em ''ppos_core.c'' (opcionalmente, podem ser usado um arquivo separado ''ppos_ipc.c'', para abrigar a implementação das funções de IPC).
* Os semáforos deverão ser totalmente implementados em seu código; sua implementação não deverá usar funções de semáforo de bibliotecas externas ou do sistema operacional subjacente.
* Você deverá definir a estrutura ''semaphore_t'' (observe que cada semáforo deve ter seu próprio contador e sua própria fila).
Sua implementação deve funcionar com estes dois arquivos de teste:
* {{pingpong-semaphore.c}} e {{pingpong-semaphore.txt|sua saída}}
* {{pingpong-racecond.c}} e {{pingpong-racecond.txt|sua saída}}
===== Outras informações =====
* Duração estimada: 4 horas.
* Dependências:
* [[Gestão de Tarefas]]
* [[Dispatcher]]
* [[Preempção por Tempo]]
* [[Tarefas suspensas]]
* [[Tarefas dormindo]]