Introdução Instituto de Informátic ca - UFRGS Sistemas Operacionais II es Aula 06 Exclusão mútua pode ser obtida com variáveis lock e semáforos São mecanismos primitivos e estão sujeitos a erros no seu uso! lock/ unlock estão sujeitos a erros de: Desatenção na sequência de primitivas lock/unlock Esquecimento de primitiva lock ou unlock Inversão de prioridade! Semáforos estão sujeitos a erros de: Esquecimento de P ou de V Inicialização Ordem e quantidade de primitivas Erros levam a deadlocks e violação da exclusão mútua Sistemas Operacionais II 2 Além disso... Variáveis tipo lock Exclusão mútua Semáforos Exclusão mútua e sincronização condicional! Objetivos diferentes,,programação diferente! Dificuldade adicional para escrever e compreender um programa Solução: construção de mais alto nível es Objeto que contém dados e procedimentos Conjunto de funções, variáveis e estruturas de dados encapsulados em um módulo especial! Possível chamar funções, mas não alterar as variáveis internas Dados internos ao monitor são acessíveis somente dentro dele Global: todos os procedimentos podem acessar Local: apenas o procedimento que o declara pode utilizá-lo A exclusão mútua é garantida pelo ambiente Compilador insere todas as chamadas de sistema e código necessários para criar filas de espera por recursos Diferença entre um objeto (linguagens OO) e um monitor! Um objeto não é compartilhado por processos concorrentes Sistemas Operacionais II 3 Sistemas Operacionais II 4
Sintaxe e semântica de um monitor Semântica do monitor: exclusão mútua monitor name { Declaração de variáveis permanentes Inicialização Procedimentos - Compartilhadas por todos os procedimentos - Mantém os valores enquanto o monitor existir (estado) - Interface: especifica métodos e parâmetros - Variáveis locais Propriedades de um monitor: Apenas os procedimentos (nomes) são visíveis do exterior Os procedimentos de um monitor não acessam variáveis externas ao monitor Variáveis permanentes são inicializadas antes de qualquer procedimento! Definição de uma invariante do monitor que deve ser mantida pelos procedimentos Apenas um processo está dentro do monitor (ativo) em um instante de tempo t Responsabilidade do compilador garantir a exclusão mútua! Usa lock e/ou semáforos (uso correto garantido pelo compilador!)! Provida implicitamente pelo monitor (sincronização de acesso a dados) Necessário coordenar os processos (espera e entrada) para que haja apenas um no monitor Surgem as variáveis condicionais! Sincronização de controle (coordenação de ações) Quando se fala em monitor, normalmente é usado o termo processo porque eles foram originalmente definidos nesse contexto. No entanto, o discurso é válido para threads. Sistemas Operacionais II 5 Sistemas Operacionais II 6 Semântica do monitor: Variáveis condicionais Primitivas wait e signal Variáveis especiais ligadas ao conceito de monitor Declaradas e usadas apenas dentro do monitor Possuem um fila associada (política da fila não é imposta)! O valor da variável de condição é a fila, mas ela não vista, nem acessível para o programador Só podem ser usadas via primitivas específicas: wait(cv) e signal(cv) Primitiva wait (condition_variable) Retira do monitor, incondicionalmente, o processo que a executa fila de espera associada à variável de condição Primitiva signal(condition_variable) Libera um único processo da fila associada a condição sinalizada Não guarda memória, isto é, se a fila estiver vazia no momento do signal, ele é perdido. As primitivas wait e signal implementam uma política FIFO wait insere o processo no final da fila e signal acorda o processo da frente da fila Possível haver outras políticas (prioridade, e.g.) Sistemas Operacionais II 7 Sistemas Operacionais II 8
Representação genérica de um monitor Simplificações e semânticas possíveis Situação inicial P 1 P 2 Procedure P Condição C P 5 P 6 P 3 P 4 P 1 P 2 Procedure P Condição C P 5 P 6 Procedure Q Condição D Procedure Q Condição D P3 executa signal (C) P 4 Procedure R P 3 Sinalizadores Procedure R Situação final O que fazer com o P 3 quando ele faz o signal? P 1 P 2 P 4 Procedure P Procedure Q Procedure R Condição C P 5 Condição D Sinalizadores P 6 P 3 Uma única fila de espera para entrar no monitor Uma fila para cada variável de condição Questão é o que fazer com os processos sinalizadores? Semânticas para o signal Sistemas Operacionais II 9 Sistemas Operacionais II 10 Estratégias de sinalização Diagrama de estado Signal and Continue (SC): não preemptiva O processo sinalizador continua sua execução e o sinalizado passa para a fila de entrada do monitor! Semântica usada em Java e em ambientes Unix Signal and Wait (SW): preemptiva O processo sinalizador vai para a fila de entrada do monitor e o processo sinalizado inicia sua execução! Semântica proposta por B. Hansen Signal and Urgent Wait (SU) O processo sinalizador vai para a frente da fila de entrada do monitor e o processo sinalizado inicia sua execução! Semântica proposta por Hoare (1974) Signal and Continue Signal and Wait call call signal (cv) fila de entrada fila de entrada fila var. condição monitor fila var. condição Sinalizado (signal(cv)) monitor signal (cv) (sinalizador) wait (cv) execução (monitor) wait (cv) execução (monitor) return return Sistemas Operacionais II 11 Sistemas Operacionais II 12
Semáforo implementados como monitor Problemas monitor Semaphore { int s = 1; # s >= 0 cond pos; # signaled when s > 0 Ordenamento FIFO depende da estratégia de inicialização Signal and continue: não garante FIFO procedure Psem( ) { while ( s == 0 ) wait(pos); s = s 1; procedure Vsem( ) { s = s + 1; signal(pos); Porque usar um while e não um if? Problemas!? P1: while (s == 0) wait(pos); P2: name.vsem ( ); - s = s + 1; (s = 1) - signal(pos): P1 saí da fila da condição e vai para fila de entrada do monitor - P3 na fila de entrada do monitor antes do P1 P3: name.psem ( ); - como s > 0, ganha semáforo antes do P1 (viola FIFO) P1: while ( s == 0) wait (pos); - necessita testar novamente a variável s Signal and Wait:! O while do Psem pode ser substituído por um if! Implementa uma política FIFO Sistemas Operacionais II 13 Sistemas Operacionais II 14 Exercício: reflexão para casa... Primitivas adicionais para condition variables (cv) Transformar o código de semáforos para implementar uma política FIFO independente da estratégia de sinalização Dicas: A diferença entre a política SC e SW é o fato que o processo sinalizador continua e incrementa o valor de s. Esse valor pode ser visto por um processo diferente do que está na fila de espera por condição. Lembre que o processo da fila de condição vai para a fila de processos pela espera do monitor. Págs. 210-211, livro Andrews, mas, compreenda a solução! wait (cv, rank) Processo é posto na fila da cv, mas ordenados de acordo com o valor de rank (crescente). minrank (cv) Consulta o rank do primeiro processo da fila da cv. empty (cv) Retorna true se a fila da cv está vazia, senão, retorna false. signal_all (cv) Sinaliza todos os processo que estão na fila da cv.! Comportamento bem definido para a estratégia SC. (o que ocorre se a estratégia for SW?) Sistemas Operacionais II 15 Sistemas Operacionais II 16
O problema do buffer limitado (outra vez...) Buffer limitado: monitor Relação produtor-consumidor: O produtor insere (envia) mensagens em um buffer compartilhado, o consumidor lê (retira) mensagens. O buffer (array buf) contém mensagens que foram inseridas, mas ainda não foram lidas.! Produtor: buf[rear] = data; rear = (rear+1)% n;! Consumidor: result = buf[front];front=(front+1)% n; Com monitor: Exclusão mútua é garantida por definição! Não há necessidade de usar mecanismos para exclusão mútua Duas condições:! Buffer não está cheio possível produzir até completá-lo! Buffer não está vazio possível consumir até esvaziá-lo monitor Bounded_Buffer { typet buf[n]; int front = 0, rear = 0; count = 0; cond not_full, not_empty; procedure deposit(typet data) { while (cont == n) wait(not_ full); buf[rear] = data; rear = (rear+1) % n; count++; signal(not_empty); procedure fetch(typet &result) { while (count == 0) wait(not_empty); result = buf[front]; front = (front+1) % n; count--; signal(not_full); Sistemas Operacionais II 17 Sistemas Operacionais II 18 Leitores e escritores Leitores/escritores: monitor Dois tipos de processos, leitores e escritores, e uma base de dados Leitores consultam registros e escritores modificam registros! Processos escritores devem ter acesso exclusivo a base de dados! Processos leitores podem acessar concorrentemente a base de dados Leitores disputam com escritores e escritores disputam entre si Condições: Leitores devem esperar que não hajam escritores Escritores devem esperar que não hajam leitores nem outro escritores monitor RW_Controller { int nr = 0, nw = 0; cond oktoread, #signaled when nw == 0 oktowrite; #signaled when nr == 0 e nw == 0 procedure request_read( ) { while (nw > 0) wait(oktoread); nr = nr + 1; procedure release_read( ) { nr = nr - 1; if (nr == 0) signal(oktowrite); procedure request_write( ) { while (nr > 0 nw > 0) wait(oktowrite); nw = nw + 1; procedure release_write( ) { nw = nw - 1; signal(oktowrite); signal_all(oktoread); Sistemas Operacionais II 19 Sistemas Operacionais II 20
Temporizador com monitores Um outro clássico: a barbearia monitor Timer { int tod = 0; cond check; #signaled when tod has increased procedure delay(int interval) { int wake_time; wake_time = tod + interval; while (wake_time > tod) wait (check); procedure tick( ) { tod = tod + 1; signal_all(check); Pressupõe a existência de um relógio de hardware que acorda um processo que realiza uma chamada ao procedimento tick do monitor. Barbeira possui um barbeiro, uma porta de entrada, uma porta de saída e cadeiras para os clientes esperarem Barbeiro dorme enquanto espera clientes Um cliente ao chegar acorda o barbeiro ou esperam (dormindo) em uma das cadeiras Ao terminar um corte o barbeiro abre a porta de saída e a fecha após o cliente sair, se houver clientes esperando, acorda um deles Condições: O barbeiro deve esperar por clientes Os clientes devem esperar o barbeiro estar disponível O cliente, para sair, deve esperar o barbeiro abrir a porta O barbeiro deve esperar o cliente sair para acordar outro Sistemas Operacionais II 21 Sistemas Operacionais II 22 Barbearia Aninhamento de monitores monitor Barber_Shop { int barber = 0, chair = 0; open = 0; cond barber_available; # signaled when barber > 0 cond chair_occupied; # signaled when chair > 0 cond door_open; # signaled when open > 0 cond customer_left; # signaled when open == 0 procedure get_haircut( ) { while (barber == 0) wait(barber_available); barber = barber 1; char = chair + 1; signal(chair_occupied); while (open == 0) wait(door_open); open = open 1; signal (customer_left); procedure get_next_customer( ) { barber = barber + 1; signal (barber_available); while (chair == 0) wait (chair_occupied); chair = chair 1; procedure finish_cut( ) { open = open + 1; signal (door_open); while (open > 0) wait (customer_left); Procedimento de um monitor chama procedimento de outro monitor Temporariamente é feita a saída do primeiro monitor Duas estratégias: closed call: a exclusão mútua no primeiro monitor é mantida open call: o primeiro monitor é liberado e no retorno a ele o processo deve entrar na fila de espera de entrada Como de costume, relação custo x benefício Sistemas Operacionais II 23 Sistemas Operacionais II 24
Aninhamento de monitores: prós e contra Leituras adicionais closed call Por definição não há conflitos com variáveis permanentes Serialização de acessos aos monitores reduz concorrência Aumento a possibilidade de dealock open call Não há conflito com variáveis permanentes se elas não forem passadas por referência Necessário manter invariantes do monitor complexidade Sistemas Operacionais II 25 G. R. Andrews Multithreaded, Parallel and Distributed Programming, Addison Wesley, 2000. Capítulo 5 S. Toscani; R. Oliveira; A. Carissimi; Sistemas Operacionais e programação concorrente Editora Sagra-Luzzato, 2003. Capítulo 9 A. Silberchatz, P. Galvin, G. Gagne; Sistemas Operacionais: conceitos e aplicações. (1 a edição). Campus. 2001. Capítulo 7 Sistemas Operacionais II 26