sproc1pv2

71
Capítulo 7: Sincronização de Processos Fundamentos O Problema da Seção Crítica Sincronismo por Hardware Semáforos Problemas Clássicos de Sincronização Regiões Criticas Operating System Concepts Regiões Criticas Monitores Sincronização em Solaris 2 & Windows 2000

Transcript of sproc1pv2

Page 1: sproc1pv2

Capítulo 7: Sincronização de Processos

� Fundamentos� O Problema da Seção Crítica� Sincronismo por Hardware� Semáforos� Problemas Clássicos de Sincronização� Regiões Criticas

Operating System Concepts

� Regiões Criticas� Monitores� Sincronização em Solaris 2 & Windows 2000

Page 2: sproc1pv2

Fundamentos

� O acesso concorrente à dados compartilhados pode resultar em inconsistência dos dados.

� A manutenção da consistência dos dados requer mecanismos que assegurem a execução ordenada dos processos cooperantes.

� A Solução de Memória Compartilhada para o problema buffer-limitado (Capítulo 4) permite no máximo

Operating System Concepts

buffer-limitado (Capítulo 4) permite no máximo “tamanho_do_buffer – 1” items no buffer ao mesmo tempo. Uma solução, onde todos os items do buffer são usados requer alterações no algoritmo.� Suponha que queiramos modificar o algoritmo do produtor-

consumidor adicionando uma variável inteira counter, inicializada com 0 e incrementada cada vez que um novo item é adicionado ao buffer.

Page 3: sproc1pv2

Buffer-Limitado

� Dados compartilhados

#define BUFFER_SIZE 10typedef struct {

. . .} item ;item buffer[BUFFER_SIZE];

Operating System Concepts

item buffer[BUFFER_SIZE];int in = 0;int out = 0;int counter = 0;

Page 4: sproc1pv2

Buffer-Limitado

� Processo Produtor

while (1) {/* produz um item em nextProduced; */while (counter == BUFFER_SIZE)

Operating System Concepts

while (counter == BUFFER_SIZE); /* não faz coisa alguma */

buffer[in] = nextProduced;in = (in + 1) % BUFFER_SIZE;counter++;

}

Page 5: sproc1pv2

Buffer-Limitado

� Processo Consumidor

while (1) {while (counter == 0)

; /* não faz coisa alguma */nextConsumed = buffer[out];

Operating System Concepts

nextConsumed = buffer[out];out = (out + 1) % BUFFER_SIZE;counter--;/* consome o item em nextConsumed */

}

Page 6: sproc1pv2

Buffer-Limitado

� Os comandos

counter++;counter--;

devem ser executados atomicamente.

Operating System Concepts

� Operação atômica � operação que é totalmente realizada sem interrupção.

Page 7: sproc1pv2

Buffer-Limitado

� O comando “counter++ ” pode ser implementado em linguagem de máquina da seguinte forma:

register1 = counterregister1 = register1 + 1counter = register1

Operating System Concepts

� O comando “counter-- ” pode ser implementado assim:

register2 = counterregister2 = register2 – 1counter = register2

Page 8: sproc1pv2

Buffer-Limitado

� Se ambos o produtor e o consumidor tentarem atualizar o buffer concorrentemente, os comandos em linguagem assembly podem ser intercalados.

� A intercalação depende de como os processos produtor e consumidor são atendidos pela CPU (scheduled).

Operating System Concepts

Page 9: sproc1pv2

Buffer-Limitado

� Considerando que counter é inicialmente 5. Podemos ter a seguinte intercalação de comandos:

T0 produtor: registrador1 = counter (registrador1 = 5)T1 produtor: registrador1 = registrador1 + 1 (registrador1 = 6)T2 consumidor: registrador2 = counter (registrador2 = 5)T3 consumidor: registrador2 = registrador2 – 1 (registrador2 = 4)

Operating System Concepts

T3 consumidor: registrador2 = registrador2 – 1 (registrador2 = 4)T4 produtor: counter = registrador1 (counter = 6)T5 consumidor: counter = registrador2 (counter = 4)

� O valor de counter poderia ser 4 ou 6, onde o resultado correto seria 5.

Page 10: sproc1pv2

Condição de Corrida

� Condição de Corrida : Situação onde vários processos acessam e manipulam dados compartilhados concorrentemente. O valor final do dado compartilhado depende de qual processo termina por último.

� Para previnir condições de corrida, processos concorrentes devem ser sincronizados .

Operating System Concepts

devem ser sincronizados .

Page 11: sproc1pv2

O Problema da Seção Crítica

� “n” processos todos competindo pelo uso de algum dado compatilhado.

� Cada processo tem um segmento de código, chamado seção crítica, no qual os dados compartilhados são acessados.

� Problema – assegurar que quando um processo está executando em sua seção crítica, a nenhum outro

Operating System Concepts

executando em sua seção crítica, a nenhum outro processo deve ser permitido executar na sua seção crítica.

Page 12: sproc1pv2

Solução para o Problema da Seção Crítica

1. Exclusão Mútua . Se o processo Pi está executando em sua seção crítica, então nenhum outro processo pode estar executando na seção crítica dele.

2. Progresso . Se nenhum processo está executando em sua seção crítica e se algum processo quiser entrar em sua seção crítica, somente aqueles processos que precisem alterar a variável compartilhada poderão participar da decisão sobre qual processo será o próximo a entrar em sua seção crítica e esta seleção não

Operating System Concepts

será o próximo a entrar em sua seção crítica e esta seleção não poderá ser adiada indefinidamente.

3. Espera Limitada . Existe um limite para o número de vezes em que outros processos podem obter permissão para entrar em suas seções críticas, depois que um processo tenha feito uma solicitação para entrar em sua seção crítica e antes que a solicitação seja atendida. � Admitimos que cada processo esteja executando a uma velocidade

diferente de zero. Entretanto, não podemos fazer qualquersuposição em relação à velocidade relativa dos “n” processos.

Page 13: sproc1pv2

Tentativas Iniciais para Resolver o Problema

� Somente 2 processos, P0 and P1

� Estrutura geral do processo Pi (outro processo Pj)do {

seção de entradaseção crítica

seção de saída

Operating System Concepts

seção de saídaseção remanescente

} while (1) ;� Os Processos podem compartilhar algumas variáveis

comuns para sincronizar as ações deles.

Page 14: sproc1pv2

Algoritmo 1

� Variáveis compartilhadas : � int turn ;

inicialmente turn = 0� turn = i ⇒ Pi pode entrar na sua seção crítica

� Processo Pi

do {while (turn != i) ;

Operating System Concepts

while (turn != i) ;seção critica

turn = j ;seção remanescente

} while (1) ;� Satisfaz exclusão mútua , mas não progresso

Por quê?

Page 15: sproc1pv2

Algoritmo 2

� Variáveis Compartilhadas� boolean flag[ 2 ] ;

inicialmente flag [0] = flag [ 1 ] = false.� flag [ i ] = true ⇒ Pi pronto para entrar na seção crítica

� Processo Pi

do {flag[ i ] := true;while (flag[ j ]) ;seção critica

Operating System Concepts

seção criticaflag [ i ] = false;

seção remanescente} while (1);

� Satisfaz exclusão mútua , mas não o requerimento de progresso e ainda pode deixar os 2 (dois) processos em deadlock, se ocorrer:T0 : P0 posiciona flag [0] = trueT1 : P1 posiciona flag [1] = true

Page 16: sproc1pv2

Algoritmo 3

� Combinação das variáveis compartilhadas dos algoritmos 1 e 2.� Processo Pi

do {flag [ i ]:= true;turn = j;while (flag [ j ] && turn == j) ;

seção critica

Operating System Concepts

seção criticaflag [ i ] = false;

seção remanescente} while (1);

� Reune todos os três requerimentos; resolve o problema da seção crítica para dois processos.

Page 17: sproc1pv2

Algoritmo da Padaria

� Antes de entrar na seção crítica, o processo recebe um número. O detentor do menor número entra na seção crítica.

� Se os processos Pi e Pj recebem o mesmo numero, se i < j, então P é servido primeiro; senão P é servido primeiro.

Seção Critica para n processos

Operating System Concepts

então Pi é servido primeiro; senão Pj é servido primeiro.� O esquema de numeração sempre gera números

incrementando a ordem de numeração; isto é, 1,2,3,4,5...

Page 18: sproc1pv2

Algoritmo da Padaria

� Notação <≡ ordem lexicográfica (ticket #, process id #)� (a,b) < (c,d) se “a < c” ou se “a = c” e “b < d”� max (a0,…, an-1) é um número, k, tal que k ≥ ai para i = 0, …, n – 1

� Dados compartilhadosboolean choosing[ n ];int number[ n ];

Operating System Concepts

As estruturas de dados são inicializadas para false e 0 respectivamente.

Page 19: sproc1pv2

Algoritmo da Padaria

do { choosing[ i ] = true;number[ i ] = max(number[ 0 ], number[ 1 ], …, numbe r [ n – 1 ]) + 1;choosing[ i ] = false;for (j = 0; j < n; j++) {

while (choosing[ j ]) ; while ((number[ j ] != 0) && ((number[ j], j ) < (number[ i], i ))) ;

Operating System Concepts

while ((number[ j ] != 0) && ((number[ j], j ) < (number[ i], i ))) ;}

seção criticanumber[ i ] = 0;

seção remanescente} while (1);

Page 20: sproc1pv2

Sincronismo por Hardware

• Desabilitar ou mascarar interrupções;

• Instrução TestAndSet ( read-modify-write - RMW );

Operating System Concepts

• Instrução Swap

Page 21: sproc1pv2

Sincronismo por Hardware

� Desabilitar ou mascarar interrupções:

Em um Sistema com Processador único poderia funcionar, entretanto nem sempre isso é possível.

Operating System Concepts

Page 22: sproc1pv2

Sincronismo por Hardware

� Instrução TestAndSet ( read-modify-write - RMW ):

Testa e modifica o conteúdo de uma palavra atomicamente.

boolean TestAndSet(boolean &target) {boolean rv = target;target = true;

Operating System Concepts

target = true;return rv;

}

Page 23: sproc1pv2

Exclusão Mútua com Test-and-Set� Dado compartilhado:

boolean lock = false;

� Processo Pi

do {while (TestAndSet(lock)) ;

seção críticalock = false;

Operating System Concepts

lock = false;seção remanescente

} while (1);

boolean TestAndSet (boolean &target) {

Page 24: sproc1pv2

� Troca as duas variáveis atomicamente.void Swap(boolean &a, boolean &b) {

boolean temp = a;a = b;b = temp;

}� Processo Pi

do {

Exclusão Mútua com Swap

Operating System Concepts

do {key = true;while (key == true)

Swap(lock,key);seção crítica

lock = false;seção remanescente

} while (1);

Page 25: sproc1pv2

Exclusão mútua com Espera Limitada TestAndSet� Dados compartilhados (inicializados com false ):

boolean lock;boolean waiting[n];

� Processo Pi

do {waiting [ i ] = true;key = true;while (waiting [ i ] && key)

key = TestAndSet (lock);waiting [ i ] = false;

Operating System Concepts

waiting [ i ] = false; seção crítica

j = ( i + 1 ) % n;while ( ( j != i ) && !waiting [ j ] )

j = ( j + 1 ) % n;if ( j == i )

lock = false;else

waiting [ j ] = false;seção remanescente

} while (1);

Page 26: sproc1pv2

Semáforos

� Semaphore S – variável inteira� Só pode ser acessada via duas operações indivisíveis (atômicas)

wait (S) { signal (S) { while ( S≤≤≤≤ 0) S++;

; // no-op; } S--;

}

Operating System Concepts

}

� espera em ação � spinlock (não requer mudança de contexto)

Dijkstra:Originalmente: “wait =P ” (do holandês “proberen”, testar);

“signal=V ” (do holandês “verhogen”, incrementar).

Page 27: sproc1pv2

Seção Crítica para n Processos

� Dado compartilhado:semaphore mutex; // inicialmente mutex = 1

� Processo Pi:

do {wait(mutex);

seção crítica

Operating System Concepts

seção críticasignal(mutex);

seção remanescente} while (1);

Page 28: sproc1pv2

Semáforo como uma Ferramenta Geral de Sincronização

� Executa B em Pj somente após executar A em Pi

� Usa o semáforo synch inicializado para 0� Código:

Pi Pj

M M

A wait(synch)

Operating System Concepts

A wait(synch)signal(synch) B

Page 29: sproc1pv2

Implementação de Semáforo

� Ferramenta de sincronização que não requer espera em ação� Define um semáforo como um registro

typedef struct {int value;struct process *L;

} semaphore;

Operating System Concepts

� Assume duas operações simples:� block suspende o processo que o invoca.� wakeup( P) retoma a execução do processo P bloqueado.

Page 30: sproc1pv2

Implementação

� As operações sobre Semáforos agora são definidas como:

void wait (semaphore S) {S.value--;if (S.value < 0) {

add this process to S.L;block( );

}}

Operating System Concepts

}}

void signal (semaphore S) {S.value++;if (S.value <= 0) {

remove a process P from S.L;wakeup(P);

}}

Page 31: sproc1pv2

Deadlock e Starvation (Inanição)

� Deadlock – dois ou mais processos estão esperando indefinidamente por um evento que só pode ser causado por um dos processos que estão em espera também.

� Suponha que S e Q são dois semáforos inicializados com 1P0 P1

wait(S); wait(Q);wait(Q); wait(S);

Operating System Concepts

wait(Q); wait(S);M M

signal(S); signal(Q);signal(Q) signal(S);

� Starvation – bloqueio indefinido. Um processo pode ficar indefinidamente em uma fila de semáforo na qual ele está suspenso.

Page 32: sproc1pv2

Dois Tipos de Semáforos

� Semáforo de Contagem – valor inteiro que pode variar sobre um domínio irrestrito.

� Semáforo Binário – valor inteiro que pode variar somente entre 0 e 1; pode ser facilmente implementado.

� Um Semáforo de Contagem S pode ser implementado em função de semaforos binários.

Operating System Concepts

em função de semaforos binários.

Page 33: sproc1pv2

Implementando S (semáforo de contagem)com Semáforos Binários

� Estruturas de dados:binary-semaphore S1, S2;int C:

� Inicialização:S1 = 1S2 = 0

Operating System Concepts

C = valor inicial do semaforo S

Page 34: sproc1pv2

� operação waitwait(S1);C--;if (C < 0) {

signal(S1);wait(S2);

}signal(S1);

void wait (semaphore S) {S.value--;if (S.value < 0) {

add this process toS.L;block( );

}}

Implementando S (semáforo de contagem)com Semáforos Binários

Operating System Concepts

� operação signalwait(S1);C ++;if (C <= 0)

signal(S2);else

signal(S1);

void signal (semaphore S) {S.value++;if (S.value <= 0) {

remove a processP from S.L;wakeup(P);

}}

Valores Iniciais: S1 = 1;S2 = 0;C = valor inicial do semáforoS;

Page 35: sproc1pv2

Problemas Clássicos de Sincronização

� O Problema do Buffer-Limitado

� O Problema dos Leitores-Gravadores

� O Problema dos Filósofos Comensais

Operating System Concepts

Page 36: sproc1pv2

O Problema do Buffer-Limitado

� Dados compartilhados

semaphore full, empty, mutex;

Inicialmente:

full = 0, empty = n, mutex = 1

Operating System Concepts

full = 0, empty = n, mutex = 1

Page 37: sproc1pv2

O Problema do Buffer-LimitadoProcesso Produtor

do { …

produz um item em nextp…

wait(empty);wait(mutex);

Operating System Concepts

…soma nextp ao buffer

…signal(mutex);signal(full);

} while (1);

Page 38: sproc1pv2

O Problema do Buffer-LimitadoProcesso Consumidor

do { wait(full)wait(mutex);

…remove um item do buffer para nextc

…signal(mutex);

Operating System Concepts

signal(mutex);signal(empty);

…consome o item em nextc

…} while (1);

Page 39: sproc1pv2

� 1º Problema dos Leitores-Gravadores:Nenhum Leitor espera, a menos que Gravador já esteja na seção crítica;

� 2º Problema dos Leitores-Gravadores:Gravador esperando para ter acesso bloqueia todos os novos leitores.

O Problema dos Leitores-Gravadores

novos leitores.

Operating System Concepts

Page 40: sproc1pv2

O Problema dos Leitores-Gravadores (1º Problema)

� Dados Compartilhados:

semaphore mutex, wrt;

Inicialmente:

mutex = 1, wrt = 1, readcount = 0

Operating System Concepts

mutex = 1, wrt = 1, readcount = 0

Page 41: sproc1pv2

O Problema dos Leitores -GravadoresProcesso Gravador

wait(wrt);…

gravação é realizada…

signal(wrt);

Operating System Concepts

Page 42: sproc1pv2

O Problema dos Leitores -GravadoresProcesso Leitor

wait(mutex);readcount++;if (readcount == 1)

wait(wrt);signal(mutex);

Operating System Concepts

…leitura é realizada

…wait(mutex);readcount--;if (readcount == 0)

signal(wrt);signal(mutex):

Page 43: sproc1pv2

O Problema dos Filósofos Comensais

Operating System Concepts

� Dados Compartilhados: semaphore chopstick[5];

Inicialmente todos os valores são 1

Page 44: sproc1pv2

O Problema dos Filósofos Comensais

� Filósofo i:do {

wait(chopstick[ i ])wait(chopstick[(i+1) % 5])

…come…

signal(chopstick[ i] );

Operating System Concepts

signal(chopstick[ i] );signal(chopstick[(i+1) % 5]);

…pensa…

} while (1);

Page 45: sproc1pv2

Evitando Deadlocks e Inanição

� Permitir que no máximo quatro filósofos estejam sentados simultaneamente à mesa;

� Permitir que um filósofo pegue seus pauzinhos somente se ambos estiverem disponíveis (para fazer isso ele deve pegá-los em uma seção crítica);

Operating System Concepts

� Usar uma solução assimétrica, isto é, um filósofo ímpar pega primeiro o pauzinho à sua esquerda e depois o pauzinho à sua direita, enquanto um filósofo par pega o pauzinho à sua direita e depois o que está a sua esquerda.

Page 46: sproc1pv2

Estruturas de Sincronização de Alto Nível

� Região Crítica ouRegião Crítica Condicional;

Operating System Concepts

� Monitor.

Page 47: sproc1pv2

Regiões CríticasErros de Programação:� signal (mutex);

. . .seção crítica. . .

wait (mutex);

� wait (mutex);

--> inversão da ordem das operações:violação do requisito de exclusão mútua;

--> substituição de signal por wait:

Operating System Concepts

� wait (mutex);. . .seção crítica. . .

wait (mutex);

� esquecimento do wait ou do signal

--> substituição de signal por wait:ocorrência de deadlock;

--> omissão do wait ou signal:violação da exclusão mútua e deadlock.

Page 48: sproc1pv2

Regiões Críticas

� Construção de sincronização de alto-nível� Uma variável compartilhada v do tipo T, é declarada como:

v: shared T� A variável v é accessada somente dentro do comando:

region v [ when B ] do S

onde B é uma expressão booleana.

Operating System Concepts

� Enquanto o comando S está sendo executado, nenhum outro processo pode acessar a variável v.

� A parte [ when B ] é opcional e quando usada transforma uma região crítica em uma região crítica condicional.

Page 49: sproc1pv2

Regiões Críticas

� As regiões relativas a mesma variável compartilhada só permitem a entrada de um processo por vez.

� Assim, se dois comandos:region v when (true) S1;region v when (true) S2;

forem executados concorrentemente, em processos sequenciais distintos, o resultado será equivalente à execução sequencial de:

Operating System Concepts

distintos, o resultado será equivalente à execução sequencial de:“S1 seguido de S2”; ou“S2 seguido de S1”.

� Quando um processo tenta entrar na região crítica, a expressão Bé avaliada. Se B for true, o comando S será executado. Se for false, o processo abandonará a exclusão mútua e entrará em espera até que B se torne true e que nenhum outro processo esteja na região associada com v.

Page 50: sproc1pv2

Exemplo – Buffer-Limitado

� Dados compartilhados:

struct buffer {int pool[ n ];int count, in, out;

}

Operating System Concepts

}

Page 51: sproc1pv2

Buffer-Limitado Processo Produtor

� O Processo Produtor insere nextp dentro do buffer compartilhado

region buffer when ( count < n) {pool [ in ] = nextp;in:= (in+1) % n;count++;

}

Operating System Concepts

}

Page 52: sproc1pv2

Buffer-Limitado Processo Consumidor

� O Processo Consumidor remove um item do buffer compartilhado e coloca-o em nextc

region buffer when (count > 0) {nextc = pool[out];out = (out+1) % n;count --;

Operating System Concepts

count --;}

Page 53: sproc1pv2

Implementação da construção da região condicional

� As seguintes variáveis estão associadas com a variável compartilhada x:

semaphore mutex, first-delay, second-delay;int first-count, second-count;

� O acesso mutuamente exclusivo à seção crítica é fornecido por mutex .

Operating System Concepts

fornecido por mutex .

� Se um processo não puder entrar na seção crítica porque a expressão boleana B é false, ele inicialmente irá esperar no semáforo first_delay ; movido para o semáforo second-delay antes de receber autorização para reavaliar B.

Page 54: sproc1pv2

wait (mutex);while (!B) {

first_count++;if (second_count > 0)

signal (second_delay);else

signal (mutex);wait (first_delay);first_count--;second_count++;if (first_count > 0)

signal (first_delay);

Implementação da construção da região condicional

Operating System Concepts

signal (first_delay);else

signal(second_delay);wait (second_delay);second_count--;

}S; // comando protegidoif (first_count) > 0)

signal (first_delay);else if (second_count > 0)

signal (second_delay);else

signal(mutex);

Page 55: sproc1pv2

� Observar o número de processos que estão esperando em first-delay e second-delay , com first-count e second-count respectivamente.

� O algoritmo assume a ordem FIFO no enfileiramento dos processos para o semáforo.

Implementação da construção da região condicional

Operating System Concepts

� Para uma disciplina de enfileiramento arbitrária, uma implementação mais complicada é requerida.

Page 56: sproc1pv2

Monitores

� Construção de sincronização de Alto-Nível que permite o compartilhamento seguro de um tipo abstrato de dado entre os processos concorrentes.

monitor monitor-name{

declarações de variáveis compartilhadasprocedure body P1 (…) {

. . .}procedure body P2 (…) {

Operating System Concepts

procedure body P2 (…) {. . .

} procedure body Pn (…) {

. . .} {

código de inicialização}

}

Page 57: sproc1pv2

Visão Esquemática de um Monitor

Operating System Concepts

Page 58: sproc1pv2

Monitores

� Para permitir que um processo espere em um monitor, uma variável do tipo condition deve ser declarada, como:

condition x, y;� As variáveis do tipo condition só podem ser usadas

com as operações wait e signal .� A operação

Operating System Concepts

� A operaçãox.wait();

significa que o processo que invoca esta operação é suspenso até que um outro processo invoque

x.signal();� A operação x.signal reinicia exatamente no ponto em

que o processo foi suspenso. Se nenhum processo está suspenso, então a operação signal não tem efeito.

Page 59: sproc1pv2

Monitor com Variáveis Condition

Operating System Concepts

Page 60: sproc1pv2

Continuidade após x.signal ( )

“x.signal ( )” invocada pelo processo “P”, e “Q” está suspenso associado à condição “x”:

Duas possibilidades:

Operating System Concepts

1. “P” espera até “Q” liberar o monitor ou espera por uma outra condição;

2. “Q” espera até “P” liberar o monitor ou espera por uma outra condição.

Page 61: sproc1pv2

Exemplo dos Filósofos Comensais

monitor dp {

enum { thinking, hungry, eating } state[5];condition self [ 5 ];void pickup (int i) // following slidesvoid putdown (int i) // following slidesvoid test (int i) // following slidesvoid init ( ) {

Operating System Concepts

void init ( ) {for ( int i = 0; i < 5; i++)

state [ i ] = thinking;}

}

Page 62: sproc1pv2

Filósofos Comensaisvoid pickup (int i) {

state [ i ] = hungry;test [ i ];if (state [ i ] != eating)

self [ i ].wait();}void putdown (int i) {

state[ i ] = thinking;// test left and right neighborstest ( ( i+4 ) % 5);

Operating System Concepts

test ( ( i+4 ) % 5);test ( ( i+1 ) % 5);

}void test (int i) {

if ( (state [ (i + 4) % 5] != eating) &&(state [ i ] == hungry) &&(state [ (i + 1) % 5] != eating ) ) {

state [ i ] = eating;self [ i ].signal( );

}}

Page 63: sproc1pv2

Filósofos Comensais

Quando o filósofo estiver faminto invoca “pickup” e, após ter conseguido comer, invoca “putdown” e começa a pensar:

dp.pickup (i);. . .

Operating System Concepts

. . .come. . .

dp.putdown (i);

Page 64: sproc1pv2

Implementação de Monitor usando Semáforos

� Variáveis semaphore mutex; // (initially = 1)semaphore next; // (initially = 0)int next-count = 0;

� Cada procedure externa F será substituída porwait(mutex);

…body of F;

Operating System Concepts

body of F;…

if (next-count > 0)signal(next)

else signal(mutex);

� A Exclusão Mútua com um monitor é assegurada.

Page 65: sproc1pv2

Implementação de Monitor

� Para cada variável condition x, nós teremos:semaphore x-sem; // (initially = 0)int x-count = 0;

� A operação x.wait pode ser implementada como:

x-count++;if (next -count > 0)

Operating System Concepts

if (next -count > 0)signal(next);

elsesignal(mutex);

wait(x-sem);x-count--;

Page 66: sproc1pv2

Implementação de Monitor

� A operação x.signal pode ser implementada como:

if (x-count > 0) {next-count++;signal(x-sem);wait(next);

Operating System Concepts

next-count--;}

Page 67: sproc1pv2

Implementação de Monitor

� Construção Condicional wait: x.wait(c);� c – expressão inteira avaliada quando a operação wait é

executada.� valor de c (um número de prioridade) armazenado com o

nome do processo que está suspenso.� quando x.signal é executada, o processo com menor número

de prioridade associado é o próximo a ser reiniciado.� Verificação de duas condições para estabelecer a exatidão

do sistema:

Operating System Concepts

do sistema:� Os processos do usuário devem sempre fazer suas

chamadas ao monitor em uma sequência correta.� Deve ser assegurado que um processo não-cooperativo não

ignore a porta de exclusão mútua fornecida pelo monitor, e tente acessar recursos compartilhados diretamente, sem usar o protocolo de acesso.

Page 68: sproc1pv2

Monitor para Alocação de um recurso

monitor ResourceAllocation{

boolean busy;condition x;

void acquire (int time) {if (busy)

x.wait (time);busy = true;

}

Operating System Concepts

}

void release () {busy = false;x.signal ();

}

void init () {busy = false;

}}

Page 69: sproc1pv2

Acesso ao recurso

r.acquire ( t );. . .acessa o recurso. . .

r.release ( );

Operating System Concepts

r.release ( );

Page 70: sproc1pv2

Sincronização Solaris 2

� Implementa uma variedade de travas para suportar multi-tarefa, multithreading (incluindo threads real-time), e multi-processamento.

� Usa mutexes adaptáveis para obter eficiência quando estiver protegendo dados de pequenos segmentos de código.

Operating System Concepts

� Usa variáveis condition e travas leitores-gravadoresquando longas seções de código precisam acessar aos dados.

� Usa turnstiles (porta giratória) para ordenar a lista de threads que estão esperando em um mutex adaptável ou em uma trava leitor-gravador.

Page 71: sproc1pv2

Sincronização Windows 2000

� Usa máscaras de interrupção para proteger o acesso a recursos globais em um sistema uniprocessador.

� Usa spinlocks em sistemas multiprocessadores.

� Fora do Kernel: fornece dispatcher objects (objetos despachantes) que podem funcionar de acordo com

Operating System Concepts

despachantes) que podem funcionar de acordo com mutexes e semáforos.

� Dispatcher objects também podem prover events. Um event age tal como uma variável condition.

� Um dispatcher object pode estar no estado signal ou não-signal.